使用Derived类和Base类的std :: shared_ptr

时间:2015-11-22 20:06:33

标签: c++ c++11 shared-ptr c++14

以下方法是否合适?

class TA      {  };
class TB : TA {  };

std::shared_ptr<TA> spta;
spta.reset(new TB);

3 个答案:

答案 0 :(得分:3)

显示的代码存在一个问题,TB必须从TA公开继承。您有一个shared_ptr<TA>,因此要存储在其中的指针必须可以转换为TA,但是private继承,基数是不可访问的,因此您的代码将无法编译。

class TA             {  };
class TB : public TA {  };

除此之外,代码没有错误并且表现良好。通常,当您通过基类指针执行派生类实例的多态删除时,您需要基类&#39;析构函数为virtual,因此调用派生类析构函数,但在shared_ptr的情况下,这不是必需的。 shared_ptr::reset是一个函数模板,它接受任何可转换为托管指针类型的Y*shared_ptr constructor template {/ 3}}也是如此。

话虽如此,你应该更喜欢制作基础课程。析构函数virtual,特别是如果涉及的类具有其他virtual函数。

答案 1 :(得分:2)

不,TA不是私有的。

此外,正如评论中所建议的,基类的析构函数应该是虚拟。这通常是一种很好的做法,因为你不能保证你的类的实例只能用于共享指针。

要使其正常工作,您必须至少修改这些行:

class TA {  };
class TB : TA {  };

如下:

class TA { virtual ~TA() { } };
class TB : public TA {  };

那些,因为以下示例 good

class TA { virtual ~TA() { } };
class TB : public TA {  };

TA *spta = nullptr;
spta = new TB;

这主要取决于 good 对你意味着什么。这至少是合法的。

答案 2 :(得分:0)

这不是问题的答案,它试图澄清有关shared_ptr看似神奇的能力以避免使用虚拟析构函数的任何混淆。

这是一个小小的演示程序:

#include <iostream>
#include <memory>

struct A {
    ~A() { std::cout << __func__ << std::endl; }

    void foo() { do_foo(); }

protected:
    virtual void do_foo() {
        std::cout << "A::" << __func__ << std::endl;
    }
};

struct B : A {
    ~B() { std::cout << __func__ << std::endl; }

    virtual void do_foo() override {
        std::cout << "B::" << __func__ << " ";
        A::do_foo();
    }
};

using namespace std;

auto main() -> int
{
    std::shared_ptr<A> p = std::make_shared<A>();
    p->foo();
    p = std::make_unique<B>();
    p->foo();

    cout << "deleting B:" << endl;
    return 0;
}

预期产出:

A::do_foo
~A
B::do_foo A::do_foo
deleting B:
~B
~A

请注意,当在main()的末尾销毁B时,会调用正确的析构函数。