当对象被创建为基类时,如何获取派生类型的shared_ptr?

时间:2018-02-20 01:59:06

标签: c++ templates inheritance shared-ptr

我正在尝试编写一个nodegraph库,可以重复使用它来在单个应用程序中实现几个具体的不同nodegraph类型。我有基类Node和Port。当节点请求时,按需创建端口。

我希望能够创建可以专门化并向Node和Port添加功能的子类MyNode和MyPort,但仍继承所有基本功能。

我特别指出的问题是我在Node类中使用std :: make_shared来创建Port对象,但是在MyNode对象中我希望将Port对象强制转换为MyPort对象。

我包括下面的代码,试着具体地说明我现在遇到的问题,但我想知道我的继承方法是不是正确的尝试下去的道路,所以我是对于如何构建我的基础/专用nodegraph库的方法非常开放。

#include <memory>
#include <string>
#include <iostream>
using namespace std;

class Port {
public:
    Port(string name) : m_name(name)   {}
    virtual ~Port() {}
    string getName()   {   return m_name; }
private:
    string m_name;
};

class Node {
public:
    shared_ptr<Port> getPort(string portName)
    {
        return make_shared<Port>(portName);
    }
};

class MyPort : public Port {
public:
    MyPort(string name) : Port(name) {}
    virtual ~MyPort() {}
    string getLongName()   {   return getName()+"_LONG";  }
};

class MyNode : public Node {
public:
    shared_ptr<MyPort> getPort(string portName)
    {
        shared_ptr<Port> tmpPort = Node::getPort(portName);
        return dynamic_pointer_cast<MyPort>(tmpPort);
    }
};

int
main (int argc, const char *argv[])
{
    MyNode node;
    shared_ptr<MyPort> port = node.getPort("Taco");

    if (port == nullptr) {
        cout << "null ptr" << std::endl;
    } else {
        cout << port->getName() << endl;
        cout << port->getLongName() << endl;
    }

    return 1;
}

当我运行此代码时,dynamic_pointer_cast返回一个nullptr。

2 个答案:

答案 0 :(得分:2)

您无法将派生类型的shared_ptr获取到基类对象。

为了将特定类型的shared_ptr获取到某个对象,该对象必须实际上属于该类型。但在这种情况下,它不是。该对象是Port - 它不是,也绝不会是MyPort

您需要确保首先创建MyPort。一种方法是添加createPort函数。然后,Node::createPort会创建一个新的Port,但您可以在MyNode中覆盖它,以便创建MyPort。或者,您可以覆盖getPort

答案 1 :(得分:0)

只需更新MyNode::getPort的定义,如下所示。

shared_ptr<MyPort> getPort(string portName)
{
    return make_shared<MyPort>(portName);
}

Live Example