虚基类继承中的析构函数问题
在很多教材里面对虚基类继承的构造函数问题讲的很多,但是却很少谈及虚基类继承中的析构函数问题。下面通过几个实验来说明C++在虚基类继承中是如何处理对象析构的。
实验1:使用派生类指针指向派生类对象,析构函数不加virtual
#include <iostream>
class A {
public:
A() { };
~A() { std::cout << "A的析构函数" << std::endl; }
};
class B1 :virtual public A {
public :
B1() {};
~B1() { std::cout << "B1的析构函数" << std::endl; }
};
class B2 :virtual public A {
public:
B2() {};
~B2() { std::cout << "B2的析构函数" << std::endl; }
};
class C :public B1, public B2 {
public:
C() {};
~C() { std::cout << "C的析构函数" << std::endl; }
};
int main() {
C* c1 = new C;
delete c1;
system("pause");
return 0;
}
实验一运行结果
这说明程序执行析构的顺序是正常的先派生类析构函数,再基类析构函数。
实验二:基类指针指向派生类对象,析构函数不加virtual
#include <iostream>
class A {
public:
A() { };
~A() { std::cout << "A的析构函数" << std::endl; }
};
class B1 :virtual public A {
public :
B1() {};
~B1() { std::cout << "B1的析构函数" << std::endl; }
};
class B2 :virtual public A {
public:
B2() {};
~B2() { std::cout << "B2的析构函数" << std::endl; }
};
class C :public B1, public B2 {
public:
C() {};
~C() { std::cout << "C的析构函数" << std::endl; }
};
int main() {
A* c1 = new C;
delete c1;
system("pause");
return 0;
}
实验二运行结果
出现了运行中断,原因我不太清楚…
实验三:用基类指针指向派生类对象,析构函数加virtual
#include <iostream>
class A {
public:
A() { };
virtual ~A() { std::cout << "A的析构函数" << std::endl; }
};
class B1 :virtual public A {
public :
B1() {};
virtual ~B1() { std::cout << "B1的析构函数" << std::endl; }
};
class B2 :virtual public A {
public:
B2() {};
virtual ~B2() { std::cout << "B2的析构函数" << std::endl; }
};
class C :public B1, public B2 {
public:
C() {};
virtual ~C() { std::cout << "C的析构函数" << std::endl; }
};
int main() {
A* c1 = new C;
delete c1;
system("pause");
return 0;
}
实验三运行结果
和实验1结果相同。
实验四:与实验二对照,看看是不是因为虚基类导致的问题
#include <iostream>
class A {
public:
A() { };
~A() { std::cout << "A的析构函数" << std::endl; }
};
class C :public A {
public:
C() {};
~C() { std::cout << "C的析构函数" << std::endl; }
};
int main() {
A* c1 = new C;
delete c1;
system("pause");
return 0;
}
实验四运行结果
的确是没有virtual的正常结果。
结论
再存在多重继承虚基类的情况下,如果使用的是派生类指针指向派生类对象,或者使用基类指针指向派生类对象且析构函数加了virtual,则和正常情况完全相同,即先执行派生类析构函数,再中间类2中间类1,再基类。但是如果使用基类指针指向派生类对象且析构函数没有加virtual,则会出现程序中断。具体原因还望有人能予以指点。