如何使用std :: shared_ptr实现多态?

时间:2014-12-16 10:53:48

标签: c++11 gcc casting polymorphism shared-ptr

我已经看到了关于这个主题的一些其他问题,但仍然没有找到答案 - 我想我错过了一些东西:

我定义了两个简单的测试类:

class TestBase
{

  public:

    TestBase ( ) { };
    ~ TestBase ( ) { };

  protected:

    inline virtual int getInt ( )
    {
        return 0;
    }

};

class TestDerived : public TestBase
{

  protected:

    inline int getInt ( ) override
    {
        return 1;
    }

};

我声明了typedef以简化std::shared_ptr:

的使用
typedef std::shared_ptr<TestBase> spBase;
typedef std::shared_ptr<TestDerived> spDerived;

问题:我无法编译代码以多态方式使用这些shared_ptr声明,即使base在所有这些情况下实际上都是spDerived的实例:

spBase base;
spDerived derived = static_cast < spDerived > ( base );
     

错误:没有匹配函数来调用'std :: shared_ptr :: shared_ptr(spBase&amp;)

spDerived derived = dynamic_cast < spDerived > ( base );
     

错误:不能使用dynamic_cast'base'(类型'spBase {aka class std :: shared_ptr}')来输入'spDerived {aka class   std :: shared_ptr}'(目标不是指针或引用)

spDerived derived = static_pointer_cast < spDerived > ( base );
     

错误:从'std :: shared_ptr&gt;'转换为非标量类型   'spDerived {aka std :: shared_ptr}'要求

spDerived derived = dynamic_pointer_cast < spDerived > ( base );
     

错误:从'std :: shared_ptr&gt;'转换为非标量类型   'spDerived {aka std :: shared_ptr}'要求

我在带有默认GCC工具链的Ubuntu 14.04盒子上使用C ++ 11。编译器是gcc-4.9。 我究竟做错了什么?不能以多态方式使用shared_pointer吗?

1 个答案:

答案 0 :(得分:15)

作为第一个类型模板参数传入std::static_pointer_caststd::dynamic_pointer_cast的类型是转换后的指针类型本身的类型,而不是 smart 的类型指针类型:

static_pointer_cast<T>(arg);
                .~~~^  
                v 
template <class T, class U> 
           .~~~~^  
           v 
shared_ptr<T> static_pointer_cast(const shared_ptr<U>& r);


dynamic_pointer_cast<T>(arg);
                .~~~~^  
                v 
template <class T, class U> 
           .~~~~^  
           v 
shared_ptr<T> dynamic_pointer_cast(const shared_ptr<U>& r);

话虽如此,你可以这样称呼它:

spBase base = std::make_shared<TestDerived>();
spDerived derived = std::dynamic_pointer_cast<spDerived::element_type>(base);
// or:
spDerived derived2 = std::dynamic_pointer_cast<TestDerived>(base);