c++ primer 類中函數調用過程解析(虛函數與作用域) P550疑問解析

函數調用過程

即c++ primer 第五版中P549所談,這裏強調幾點。
假定是p->mem() 或者obj.mem()

  • 首先確定靜態類型,即p的類型。
  • 然後在這個靜態類型中名字查找函數,即查找有沒有mem。即 名字查找
  • 若沒有則去靜態類型(即p的類型)的直接基類中找,仍沒有繼續向基類中找。直到基類頂端。仍沒有的話,就返回查找失敗,發生錯誤。
  • 若找到了,接着類型檢查,如果類型匹配就看這個函數是否是虛函數
  • 若類型不匹配,則直接返回類型匹配錯誤因爲編譯器名字查找,只要查到了,就停止名字查找了。
  • 若是虛函數,並且用指針或者引用調用,那麼調用這個虛函數的哪個版本,依據是對象的動態類型
  • 否則,就常規調用,即用靜態類型來調用。

P550疑問

主要對P550的bp2->fcn();bp2->f2();有疑問。可以看如下代碼:

class Base{
friend class Pal;
public:
    virtual int fcn(){ std::cout << "基類的虛函數" << std::endl; return 1; }
private:
    char priv_mem;
protected:
    int prot_mem;
};

class D1 :public Base{
public:
    int fcn(int a){ std::cout << "D1類的有參數的fcn" << std::endl; return a; }
    virtual void f2(){ std::cout << "D1類的虛函數f2()" << std::endl; };//新的虛函數
};

class D2 :public D1{
public:
    int fcn(int a){ std::cout << "D2類的有參數的fcn" << std::endl; return a; };
    int fcn(){ std::cout << "D2類的無參數的fcn" << std::endl; return 1; };
    void f2(){ std::cout << "D2的f2()" << std::endl; };
};

int main(int argc, const char *argv[])
{
    Base bobj; D1 d1obj; D2 d2obj;
    Base *bp1 = &bobj, *bp2 = &d1obj, *bp3 = &d2obj;
    bp1->fcn();
    bp2->fcn();
    bp3->fcn();
    //bp2->f2(); //錯誤 Base沒有名爲f2的成員
    system("pause");
    return 0;
}

1.首先解釋bp2->fcn()爲什麼調用的是基類的那個虛函數。
根據函數調用規則,先在靜態類型即Base類中找fcn,名字查找,找到了。接着進行類型檢查,確實是無參類型,再看是否是虛函數,是的,那麼依據動態類型來調用。動態類型是D1類,即調用D1::fcn();。但是D1類沒有覆蓋fcn()虛函數,是直接繼承的,故調用的仍是Base::fcn()

2.再看bp2->f2();依然先名字查找,靜態類型爲Base,沒有f2,故報錯Base類無成員f2

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章