首先Virtual用于类的多态,当设计一个类,用做其他类的父类时,且有Virtual修饰的方法,这些方法可被子类覆盖定义,此时的析构函数必须加Virtual。原因如下:上述场景一般使用工厂设计模式,定义一个父类的指针,指向子类对象,而在delete 父类指针时,期望释放对象。但父类析构函数不加Virtual修饰,则只会调用父类析构函数,而不调用子类析构函数,导致只释放了对象的父类部分,而子类部分没有释放。Virtual含义就是有一个函数映射表,调用时会去查映射表调用对应的方法。
例如:
class Test {
public:
Test(int test) : mTest(test){}
virtual ~Test(){
std::cout << "In ~Test" << std::endl;
}
virtual int getTest() {
return mTest++;
}
private:
int mTest;
};
class TestA : public Test {
public:
TestA(int test) : mTestA(test){}
~TestA(){
std::cout << "In ~TestA" << std::endl;
}
int getTest() {
return mTestA++;
}
private:
int mTestA;
}
class TestB : public Test {
public:
TestB(int test) : mTestB(test) {}
~TestB(){
std::cout << "In ~TestB" << std::endl;
}
int getTest(){
return mTestB++;
}
private:
int mTestB;
};
Test *pTest = new TestA(100);
......
delete pTest;
上述Test *pTest = new TestA(100);执行后,父类Test的指针指向子类TestA对象,在delete pTest时
将只会调用Test的析构函数,而不会调用TestA的析构函数。
上述只是简单验证,一般使用时,可能涉及到多个子类,使用工厂方法,同样会有这样的问题。因此
对于:父类有方法被子类被覆盖的,同时使用的是指向父类的指针时,切记一定将父类析构函数定义为virtual。
另一方面,如果一个类,不会被继承,则不应该定义析构函数或者其他函数为virtual,否则会导致类的对象占用空间增大。
网友评论