C++虛函數和靜態函數調用方式


簡單情況:

#include<iostream>
using namespace std;
class A
{
public:
    virtual void foo()
    {
        cout << "virtual void foo()" << endl;
    }
};

int main()
{
    //通過對象調用,會當成普通成員函數來看待。
    A a;
    a.foo();
    cout << "---------------------" << endl;
    A *b = new A();
    b->foo();
    //編譯器視角
    /*
    ((*(b->vptr))[0])();
    通過虛函數表指針調用
    */
    while (1);
    return 0;
}

總結:

1.如果通過對象調用虛函數,編譯器直接找到虛函數的地址。

2.對於虛函數和成員函數,編譯器都會隱式的傳入this指針。

3.對於指針和引用的形式來調用虛函數,編譯器走的則是虛函數表的路線。

4.無論是成員函數還是虛函數,他的地址都是在編譯期間就已經確定下來了,接下來就看你怎么去找到這個虛函數的地址,可以直接找,也可以通過虛函數表.

 

復雜情況以及靜態成員函數的調用形式:

#include<iostream>
using namespace std;
class A
{
public:
    virtual void foo()
    {
        cout << "virtual void foo()" << endl;
        //foo2();//如果虛函數里面這么調用還是會通過虛函數表找到虛函數的地址,所以為了效率,通過類調用(因為在函數內部,所以接下來通過類調用這個this指針編譯器可以找的到)
        /*
        既然在外部已經進入到該虛函數內部了,說明該對象是生成了的,也就是這個this指針存在了
        所以接下來的A::foo2();調用會成功,如果在main函數中直接調用A::foo1(),肯定失敗,因為編譯器隱式傳進去的形參this根本就找不到
        */
        A::foo2();
    }
    virtual void foo1()
    {
        cout << "virtual void foo1()" << endl;
    }
    static void foo2()
    {
        cout << "virtual void foo2()" << endl;
    }
    void aa()
    {
        cout << "fds" << endl;
    }
    int data = 3;
};
int main()
{
    //如果想讓非成員函數像靜態成員函數一樣被調用。
    ((A*)0)->aa();//前提是函數體中不能用到隱式傳進去的0指針。
    /*
    對於成員函數aa(),編譯器會隱式的傳進去0指針,這個0指針實際上里面並沒有保存類A的內容,作用僅僅是用來調用該成員函數,類似於:A*p;
    p->aa();只是用了一種詭異的手法將這兩步進行合並,再調用。
    不管是0還是其他的地址,都無所謂,只要用不到那個指針就行,比如 ((A*)899980)->aa();同樣也能正常運行,因為前面那個地址僅僅是生成A類型的指針。
    如果寫成cout<<((A*)0)->data來打印里面的數據成員就錯了,因為0地址里面實際並沒有保存真正的類A的內容。
    */

    //對於靜態的成員函數,它不依賴於類對象,所以編譯器並不會給他隱式的傳進去this指針。
    //所以可以直接用類成面來調用。
    A::foo2();

    //對於虛函數,通過對象調用相當於普通成員函數的調用,用指針和用引用調用則是通過虛函數表來找到對應的虛函數。
    /*A ss;
    //ss.foo();

    cout<<"通過虛函數表找到虛函數的地址"<<endl;
    A&p = ss;
    p.foo();

    A*p=new A();
    p->foo();
    
    A&cc = *p;
    cc.foo();
    */

    /*
    普通的成員函數和虛函數在調用的時候編譯器都會隱式的傳入this指針,而對於靜態函數則例外。
    */

    while (1);
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM