先說結果: 父類定義的虛函數,子類如果重載了 ,那就必須定義具體實現,不能弄個沒有函數體的函數名放那裏碰瓷。
- #include<iostream>
-
- using namespace std;
-
- class parent
- {
- public:
- parent(){
- std::cout<<"parent constructor no param"<<std::endl;
- };
- private:
- parent(int a){
- std::cout<<"parent constructor: "<<a<<std::endl;
- };
- public:
- virtual ~parent(){
- std::cout<<"parent disconstructor~"<<std::endl;
- };
- virtual void opt(){
- std::cout<<"parent opt"<<std::endl;
- };
- };
-
- class child:public parent
- {
- public:
- child(int a){
- cout<<"child constructor: "<<a<<endl;
- };
- ~child();
- void opt(){
- std::cout<<"child opt"<<std::endl;
- };
- void child_do(){
- std::cout<<"child do"<<std::endl;
- };
- };
-
- int main()
- {
- int b = 10;
- parent* test = new child(b);
- test->opt();
- reinterpret_cast<child*>(test)->child_do();
- delete parent;
- return 0;
- }
- /tmp/cc3sxtLw.o: In function `child::child(int)':
- test.cpp:(.text._ZN5childC2Ei[_ZN5childC5Ei]+0x1d): undefined reference to `vtable for child'
找了好一會,發現是子類的析構函數只是聲明瞭,沒有定義,
改成 ~child(){}; 定義上就好了。
但是我記得之前也有過忘記定義析構函數具體內容的情況,編譯並沒有報錯,
於是回過頭注意到 這句報錯的含義好像並不是說子類的析構函數沒有定義,
undefined reference to `vtable for child' -> 對child的虛表未定義的引用,
這裏 vtable 應該就是指的虛函數表,
嘗試着換一種方式修改 ~child(); 這個不變, 把 virtual ~parent 改爲 ~parent,
果然 也不報錯了,但是我們都知道這樣改的後果是啥,就是父類指針指向的子類對象析構不會調用子類的析構函數了。
- [root@iZuf6iemoke3l0asocwqo5Z 繼承]# ./a.out
- parent constructor no param
- child constructor: 10
- child opt
- child do
- parent disconstructor~
- [root@iZuf6iemoke3l0asocwqo5Z 繼承]#
所以,老老實實給父類的析構函數加上 virtual, 然後完善對子類析構函數的定義.
- virtual ~parent(){
- std::cout<<"parent disconstructor~"<<std::endl;
- };
- ~child(){
- cout<<"child disconstructor"<<endl;
- };