2015-09-01 35 views
-1

我有一个函数,接受Base类型的共享指针,然后std::dynamic_pointer_cast到派生类型。但是,派生指针是一个NULL,我不明白为什么。我已经确保在我的基类中包含一个虚拟析构函数。我不想使用静态转换,因为这不能保证我的派生成员变量和函数被保留了吗?std :: dynamic_pointer_cast std ::共享从基地到派生返回NULL

的代码如下:

基类:

class Base 
{ 
public: 
    mType get_type() 
    { 
     return msg_type; 
    } 

    void set_type(mType type) 
    { 
     msg_type = type; 
    } 

    virtual ~cMsg() = default; 
protected: 
    mType msg_type; 
    message msg; 
}; 

派生类:

class Derived : public Base 
{ 
public: 
    void set_i(int j) 
    { 
     i = j; 
    } 

    int get_i() 
    { 
     return i; 
    } 
private: 
    int i; 
}; 

功能执行铸造:

void callback(std::shared_ptr<Base> msg_received) 
{ 
    std::cout<< "Callback called\n"; 
    auto real_msg = std::dynamic_pointer_cast<Derived>(msg_received); 

    if (real_msg != NULL) 
    { 
     std::cout << "i value is: " << real_msg->get_i() << "\n"; 
    } 

} 

功能创建派生对象和调用功能:

int main() 
{ 
    Derived test_msg; 

    test_msg.set_i(1);  
    test_msg.set_type(mSystem::TEST_MSG); 

    std::shared_ptr<Base> msg_ptr = std::make_shared<Base>(test_msg);  

    callback(msg_ptr); 

    return 0; 
} 

任何帮助,将不胜感激。

编辑:纠正错字

+2

当然。 'msg_ptr'被构建为'Base',而不是'Derived'。 – Barry

+0

此外,您的意思是将'msg_ptr'传递给'callback()',并请清理您的示例为[minimal,complete,and verifiable](http://www.stackoverflow.com/help/mcve)。 – Barry

+0

什么是“NULL类型”? –

回答

2

你完全切片。你的动态分配的对象(由该共享指针管理)只是一个Base,从Derived构建的副本。事后你不能“得到派生”,而不能设计出只有其中一个车轮的施工计划的跑车。

我认为你在这里的关键困惑是认为make_shared使共享东西。它没有。它使得新的东西分享。

+0

你完全正确!我完全误解了make_shared。我现在纠正了它。我从来没有把make_shared/unique看作是类似于新的。 – John

+0

@John:伴侣别担心;这是C++的错,不是你的。这种语言一直都是非常愚蠢的,而且一天到晚才变得如此。我希望像这样的页面驱动bloomin'委员会。 –

1

您正在型基地shared_ptr的,即使你为它提供派生类型的对象。请记住,所有make_shared(在使用分配器分配内存之后)正在调用由提供给make_shared的参数指定的类型的构造函数。

在你的情况下,它创建一个Base类型的对象,并给它一个Derived的实例。 Base复制的构造函数比被调用的,传递的Derived对象隐式转换为对Base的const引用。