C++ 析构函数 何时 加 Virtual ?

2019-05-23  本文已影响0人  b036101467d7

首先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,否则会导致类的对象占用空间增大。

上一篇 下一篇

猜你喜欢

热点阅读