zoukankan      html  css  js  c++  java
  • std::shared_ptr 可调用父类的非虚析构函数

     1 struct IBase
     2 {
     3     IBase() {
     4         std::cout << "IBase::IBase()" << std::endl;
     5     }
     6     virtual ~IBase() {
     7         std::cout << "IBase::~IBase()" << std::endl;
     8     }
     9     virtual void execute() = 0;
    10 };
    11 using IBaseSP = std::shared_ptr<IBase>;
    12 using IBaseUP = std::unique_ptr<IBase>;
    13 
    14 class Foo : public IBase
    15 {
    16 public:
    17     Foo() {
    18         std::cout << "Foo::Foo()" << std::endl;
    19     }
    20     ~Foo() override {
    21         std::cout << "Foo::~Foo()" << std::endl;
    22     }
    23     void execute() override {
    24         std::cout << "Foo::execute()" << std::endl;
    25     }
    26 };
    27 
    28 class Bar : public IBase
    29 {
    30 public:
    31     Bar() {
    32         std::cout << "Bar::Bar()" << std::endl;
    33     }
    34     ~Bar() override {
    35         std::cout << "Bar::~Bar()" << std::endl;
    36     }
    37     void execute() override {
    38         std::cout << "Bar::execute()" << std::endl;
    39     }
    40 };
     1 int main() {
     2     IBase* p = new Foo();
     3     p->execute();
     4     delete p;
     5 
     6     std::cout << "----------" << std::endl;
     7 
     8     std::queue<IBaseUP> queueUP;
     9     {
    10         queueUP.push(std::make_unique<Foo>());
    11         queueUP.push(std::make_unique<Bar>());
    12     }
    13 
    14     while (!queueUP.empty()) {
    15         auto &p = queueUP.front();
    16         p->execute();
    17         queueUP.pop();
    18     }
    19 
    20     std::cout << "----------" << std::endl;
    21 
    22     std::queue<IBaseSP> queueSP;
    23     {
    24         queueSP.push(std::make_shared<Foo>());
    25         queueSP.push(std::make_shared<Bar>());
    26     }
    27 
    28     while (!queueSP.empty()) {
    29         auto &p = queueSP.front();
    30         p->execute();
    31         queueSP.pop();
    32     }
    33 
    34     return 0;
    35 }

    本测试环境为VS2015。支持C++11标准。

    一般的我们通过指针或引用在C++中实现多态。如果要把数据存入容器,则可以使用智能指针。

    如果要确保对象可以正常析构,则需要将父类的析构函数声明为虚函数。这样通过父类指针delete时,可确保子类对象的析构函数被正常调用。

    正常情况下的执行结果如下图所示,父类及子类的析构函数都可以被调用:

    如果父类的析构函数不是虚函数,则结果如下图:

    可以看到,只有父类的析构函数被调用了。子类的析构函数并没有被调用,则产生错误。

    这一点上,对于原始的指针或者std::unique_ptr。其表现是一致的。也符合C++基本的语法。

    但是对于std::shared_ptr。即便父类析构函数并非虚函数,其子类的析构函数依然可以被调用。

    对于此种行为的原因尚未查明(待更新)。也许这是std::shared_ptr专门设计的一种特性。但为谨慎起见,我们也未必需要此特性。

    C++11中引入了新的关键字“override”。对于子类中要实现多态(即要对父类方法进行override)的方法。在函数定义中使用override关键子,则编译器会帮助检测语法错误。如果父类方法未声明virtual则报错,提升代码质量。

    如果使用了override关键字,则可不必在函数开头声明virtual。

  • 相关阅读:
    [慢查优化]建索引时注意字段选择性 & 范围查询注意组合索引的字段顺序
    telnet报“Unable to connect to remote host:Connection refused”错误
    问题总结-2016
    vim保存文件时,生成.un~文件
    用uniq来处理文件重复数据--交集,差集,计数等(转)
    ThinkPHP的URL访问
    PHP中Exception异常
    Git Stash紧急处理问题,需要切分支
    git 命令学习
    gdb调试PHP扩展错误
  • 原文地址:https://www.cnblogs.com/waterfall/p/10173478.html
Copyright © 2011-2022 走看看