美文网首页编程语言爱好者程序员在深圳
没有学不会的C++:虚析构函数和智能指针

没有学不会的C++:虚析构函数和智能指针

作者: 程序员在深圳 | 来源:发表于2019-01-02 22:56 被阅读1次

    虚析构函数

    当我们想在程序中实现多态时,我们经常会这样做:

    #include <iostream>
    using namespace std;
    class Dog {
    public:
      Dog() {}
      ~Dog() { cout << "Dog destroy\n";}
    };
    
    class YellowDog : public Dog {
    public:
      YellowDog() {}
      ~YellowDog() { cout << "YellowDog destroy\n";}
      static Dog* createDog() { return new YellowDog(); }
    };
    

    即用工厂类或工厂方法来创建具体的对象,而在运行时通过对基类(这里是Dog)的指针或引用来实现对不同子类(这里是YellowDog)的调用,这样我们就实现了「多态」。不过,上面代码是有问题的,你可以看下面代码的输出:

    int main(int argc, char** argv) {
      Dog* dog = YellowDog::createDog();
      delete dog;
      return 0;
    }
    ----<output>----
    Dog destroy
    

    从输出结果可以看出,delete dog 时,只调用了基类的析构函数,而子类对象没有被析构,此时很可能会发生内存泄露,为了避免这种情况,我们需要在基类析构函数前加上 virtual 关键字,如下

    virtual ~Dog() { cout << "Dog destroy\n"; }
    

    接着重新编译后再运行程序,便可以看到子类对象被如期析构了

    ----<output>----
    YellowDog destroy
    Dog destroy
    

    用智能指针 shared_ptr 实现动态析构

    从 C++ 11 起,通过 shared_ptr 你同样可以实现动态析构,shared_ptr 定义在头文件 <memory>

    template< class T > class shared_ptr;
    

    下面我们就来看下智能指针的版本

    class Dog {
    public:
      Dog(){}
      ~Dog() { cout << "Dog destructor" << endl; }
    };
    
    class YellowDog : public Dog {
    public:
      YellowDog() {}
      ~YellowDog() { cout << "YellowDog destructor" << endl; }
    
      static shared_ptr<Dog> createDog() {
          return shared_ptr<YellowDog>(new YellowDog());
      }
    };
    
    int main() {
        shared_ptr<Dog> p = YellowDog::createDog();
        return 0;
    }
    

    从输出中可以看到虽然 Dog 类中的析构函数没有声明 virtual,但 YellowDog 的析构函数仍然被顺利调用了。

    注意:STL 中的所有类都没有 virtual 析构函数,所以当你从 STL 中派生子类时,要尽可能的使用 shared_ptr

    参考:https://www.youtube.com/watch?v=ZiNGWHg5Z-o&index=6&list=PLE28375D4AC946CC3

    相关文章

      网友评论

        本文标题:没有学不会的C++:虚析构函数和智能指针

        本文链接:https://www.haomeiwen.com/subject/jjqxrqtx.html