【问题标题】:C++ Templates and PolymorphismC++ 模板和多态性
【发布时间】:2018-03-05 08:20:44
【问题描述】:

我正在研究决策树结构,由于我将使用类似的决策结构和不同的代理,我决定使用模板来构建基本功能。

目前我有一个名为BC_IsEnemyCloseDecision 的类,它继承自模板类。链是BC_IsEnemyCloseDecision -> DT_BoolDecision<T> -> DT_Decision<T> -> DT_Node<T>

DT_Node类:

template <class entity_type>
class DT_Node
{
public:

    DT_Node() {}
    virtual ~DT_Node()
    {
        mNodes.clear();
    }

    virtual DT_Node* decide(entity_type* pAgentPtr) = 0;

    virtual void addChild(std::unique_ptr<DT_Node>&& pNewChild)
    {
        mNodes.emplace_back( std::move(pNewChild) );
    }

protected:

    std::vector< std::unique_ptr<DT_Node> > mNodes;
};

DT_Decision 类:

template <class entity_type>
class DT_Decision : public DT_Node<entity_type>
{
public:

    DT_Decision()
        : DT_Node<entity_type>()
    {

    }

    virtual ~DT_Decision()
    {

    }

    DT_Node<entity_type>* decide(entity_type* pAgentPtr)
    {
        return getBranch(pAgentPtr)->decide(pAgentPtr);
    }

protected:

    virtual DT_Node<entity_type>* getBranch(entity_type* pAgentPtr) = 0;
};

DT_BoolDecision类:

template <class entity_type>
class DT_BoolDecision : public DT_Decision<entity_type>
{
public:

    enum eNODE_TYPE{ eNT_TRUE_NODE = 0, eNT_FALSE_NODE};

    DT_BoolDecision()
        : DT_Decision<entity_type>(),
          BRANCH_NUMBER(2)
    {

    }

    virtual ~DT_BoolDecision()
    {

    }

    void addChild(std::unique_ptr< DT_Node<entity_type> >&& pNewChild)
    {
        this->mNodes.emplace_back( std::move(pNewChild) );
    }

    void addChild(const eNODE_TYPE pNodeType, std::unique_ptr< DT_Node<entity_type> >&& pNewChild)
    {
        if(this->mNodes.size() <BRANCH_NUMBER)
        {
            this->mNodes.emplace( this->mNodes.begin() + (int)pNodeType, std::move(pNewChild) );
        }
    }

protected:

    virtual bool performTest(entity_type* pAgentPtr) = 0;

    DT_Node<entity_type>* getBranch(entity_type* pAgentPtr)
    {
        if( performTest(pAgentPtr) )
        {
            return this->mNodes[eNODE_TYPE::eNT_TRUE_NODE].get();
        }

        return this->mNodes[eNODE_TYPE::eNT_FALSE_NODE].get();
    }

    const int BRANCH_NUMBER;
};

BC_IsEnemyCloseDecision类:

// int for a simple test
class BC_IsEnemyCloseDecision : public DT_BoolDecision<int>
{
public:

    BC_IsEnemyCloseDecision();
    virtual ~BC_IsEnemyCloseDecision();

protected:

    bool performTest(int* pAgentPtr);
};

DT_Action(如果需要):

template <class entity_type>
class DT_Action : public DT_Node<entity_type>
{
public:

    DT_Action()
    : DT_Node<entity_type>()
    {}
    virtual ~DT_Action() {}

    DT_Node<entity_type>* decide(entity_type* pAgentPtr) { return this; }
    void addChild(std::unique_ptr< DT_Node<entity_type> >&& pNewChild) {}

    virtual void performAction(entity_type* pAgent) = 0;

};

最后是DecisionTree 类:

template <class entity_type>
class DecisionTree
{
public:

    DecisionTree(entity_type* pAgentPtr)
    {
        mAgentPtr = pAgentPtr;
    }

    DecisionTree(entity_type* pAgentPtr, std::unique_ptr< DT_Node<entity_type> >&& pRoot)
    {
        mAgentPtr = pAgentPtr;
        mRoot = std::move(pRoot);
    }

    ~DecisionTree()
    {

    }

    void addRoot(std::unique_ptr< DT_Node<entity_type> >&& pRoot)
    {
        mRoot = std::move(pRoot);
    }

    void decide()
    {
        DT_Action<entity_type>* resultantAction = (DT_Action<entity_type>*)(mRoot->decide(mAgentPtr));
        if(resultantAction != nullptr)
        {
            resultantAction->performAction(mAgentPtr);
        }
        else
        {
            std::cout<<"ERROR! DT! FACED WITH A NULL DT_ACTION";
        }
    }

private:

    std::unique_ptr<DT_Node<entity_type>> mRoot;

    entity_type* mAgentPtr;
};

编码完成后我决定用一个简单的类型来测试它(我选择了int)并执行了以下操作:

int test= 6;

std::unique_ptr<BC_IsEnemyCloseDecision> testRoot = std::make_unique<BC_IsEnemyCloseDecision>();
std::unique_ptr<BC_IsEnemyCloseDecision> testNode = std::make_unique<BC_IsEnemyCloseDecision>();

testRoot->addChild(testNode); // Error: No matching member function for call to 'addChild'
testRoot->addChild(DT_BoolDecision<int>::eNODE_TYPE::eNT_TRUE_NODE, testNode); // Error: No matching member function for call to 'addChild'

DecisionTree<int> dt(&test);
dt.addRoot(testRoot); // Error: No viable conversion from 'unique_ptr<BC_IsEnemyCloseDecision>' to 'unique_ptr<DT_Node<int>>

dt.decide();

并收到No matching member function for call to 'addChild'No viable conversion from 'unique_ptr&lt;BC_IsEnemyCloseDecision&gt;' to 'unique_ptr&lt;DT_Node&lt;int&gt;&gt; 错误。

我找不到与我的问题相关的任何有用信息,因此我没有解决问题的见解。

【问题讨论】:

  • 你觉得这里贴上3页代码找错是不是好点?为什么不缩小它以便任何人都可以重现问题?
  • 这个例子远非最小;请花一些时间自己缩小范围。阅读minimal reproducible example 是什么。
  • 并且类 DT_Action 不存在..所以什么都不能编译!
  • testRoot-&gt;addChild(testNode); virtual void addChild(std::unique_ptr&lt;DT_Node&gt;&amp;&amp; pNewChild) 你想move it吗?
  • @ciyo 好吧,如果您的函数需要rvalue, don't give it an lvalue,那并没有减少它的必要性。顺便说一句,如果您添加std::move,您的代码可能会编译,但我希望它会很快崩溃。你知道当你移动构造 unique_ptr 然后尝试访问原件时会发生什么,就好像什么都没发生一样吗?这是hint

标签: c++ templates inheritance polymorphism


【解决方案1】:

你的错误归结为

struct Receiver
{
    void method(std::unique_ptr<int> ptr) {}
};

int main()
{
    Receiver receiver;
    std::unique_ptr<int> ptr = std::make_unique<int>(10);
    receiver.method(ptr); // Error: No matching member function for call to 'method'
}

这是因为您试图复制 unique_ptrs。您需要移动它们。完成此操作后,从 unique_ptr 移出的位置将为空。

std::unique_ptr<BC_IsEnemyCloseDecision> testRoot = std::make_unique<BC_IsEnemyCloseDecision>();
std::unique_ptr<BC_IsEnemyCloseDecision> testNode = std::make_unique<BC_IsEnemyCloseDecision>();

testRoot->addChild(std::move(testNode));

// You don't have a node in testNode anymore, so you need a new one to add again
testNode = std::make_unique<BC_IsEnemyCloseDecision>(); 

testRoot->addChild(DT_BoolDecision<int>::eNODE_TYPE::eNT_TRUE_NODE, std::move(testNode)); 

int test= 6;
DecisionTree<int> dt(&test);
dt.addRoot(std::move(testRoot)); 

dt.decide();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-31
    • 1970-01-01
    • 2021-02-15
    • 2016-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多