眾所周知,子類虛函數指針會把父類虛函數指針覆蓋,如果要子類調用父類虛函數,方法如下
1 class Father 2 { 3 virtual void show(){cout<<"this is father."<<endl;} 4 }; 5 6 class Son 7 { 8 virtual void show(){cout<<"this is son."<<endl;} 9 }; 10 11 int main() 12 { 13 Father* f = new Son; 14 f->show(); // 輸出“this is son.” 15 f->Father::show(); // 輸出“this is father.” 16 return 0; 17 }
擴展:如果繼承方式是A>B>C>D(A基類往下衍生),B* b = new D 能訪問到的到哪一步的虛函數?
1 class A 2 { 3 public: 4 A() { cout << "constructor A." << endl; } 5 virtual void show() { cout << "this is A." << endl; } 6 virtual ~A() { cout << "destructor A." << endl; } // 這里必須加virtual 不然子類不會調用析構函數 7 }; 8 9 class B : public A 10 { 11 public: 12 B() { cout << "constructor B." << endl; } 13 virtual void show() { cout << "this is B." << endl; } 14 ~B() { cout << "destructor B." << endl; } 15 }; 16 17 class C : public B 18 { 19 public: 20 C() { cout << "constructor C." << endl; } 21 virtual void show() { cout << "this is C." << endl; } 22 ~C() { cout << "destructor C." << endl; } 23 }; 24 25 class D : public C 26 { 27 public: 28 D() { cout << "constructor D." << endl; } 29 virtual void show() { cout << "this is D." << endl; } 30 ~D() { cout << "destructor D." << endl; } 31 }; 32 33 int main() 34 { 35 B* b = new D; 36 b->show(); 37 b->A::show(); 38 b->B::show(); 39 // b->C::show(); // 報錯,限定名不是類"B"或其基類 40 C* c = static_cast<C*>(b); // 轉換為類C 41 c->show(); 42 c->C::show(); // 輸出"this is C." 43 delete c; 44 return 0; 45 }
結果很明顯,B* b = new D 能訪問到A、B、D的show()虛函數,若要訪問到C,轉換為類C后再訪問即可。如下圖所示,因為new D的時候,分配了ABCD總共4個類的空間(好浪費內存),既然開辟了,那么類C虛函數肯定是存在的。
順便再強調一下,若父類析構函數沒有加virtual關鍵字,以非子類聲明指針,子類不會調用析構函數,結果如下
如果沒有轉換成類C,那么B* b = new D,在delete b時,只會調用A和B的析構函數,無形中產生內存泄漏。