【问题标题】:c++ interdependent class templates, pointer casting derived classesc++相互依赖的类模板,指针转换派生类
【发布时间】:2012-08-02 18:02:03
【问题描述】:

您好,我正在编写一个显示/显示和基准测试不同图表的程序。一个图由节点和边组成......所以我的问题是我有两个模板类(模板),它们是所有派生类的基础

template <class Node>
class Edge
{
public:
    Edge() : startN(0), endN(0), price(0) {}
    Edge(Node *startN, Node *endN, int price) : startN(startN), endN(endN), price(price)
    {
        startN->toEdges.push_back(this); // PROBLEM HERE
        endN->fromEdges.push_back(this); // PROBLEM HERE
    }

    Node *startNode() const {
        return startN;
    }
    Node *endNode() const {
        return static_cast<Node *>(endN);
    }
    int getPrice() const {
        return price;
    }
    void setPrice(int price) {
        this->price = price;
    }

private:
    Node *startN;
    Node *endN;

    int price;
}; 


template<template<class> class EdgeTemplate >
class NodeBase
{
public:
    NodeBase() : nodeId(0), key(0), state(UNLABELED), prev(0) {}
    NodeBase(int id, int key) : nodeId(id), key(key), state(UNLABELED), prev(0) {}

    void addToEdges(EdgeTemplate<NodeBase> *edge) {
        toEdges.push_back(static_cast<EdgeTemplate<NodeBase> *>(edge));
    }

    int nodeId;
    int key;
    State state;
    NodeBase *prev; // prevous scanned

    QVector<EdgeTemplate<NodeBase> *> fromEdges; // start
    QVector<EdgeTemplate<NodeBase> *> toEdges; // end
};

在另一个模板类中发生错误:

template <template<class> class EdgeTemplate, class Node>
class DijkstraAlgorithm {
...
QVector<EdgeTemplate<Node> *> Edges; // the problem for derived classes
...
};

叮当声:

error: cannot initialize a parameter of type 'Edge<NodeBase<Edge> > *' with an rvalue of type 'Edge<DNode> *'
        startN->addToEdges(this);
                           ^~~~

海合会:

error: no matching function for call to 'QVector<Edge<NodeBase<Edge> >*>::push_back(Edge<DNode>* const)'

据我了解,问题是派生类DNode (class DNode : public NodeBase &lt;Edge&gt;) 不能存储在基本类型NodeBase&lt;Edge&gt; 的硬币容器中...我试过转换它,但它没有工作。

谁能解释一下我做错了什么以及如何解决这个问题?

【问题讨论】:

    标签: c++ qt templates gcc clang


    【解决方案1】:

    在查看模板时,继承关系船舶根本不重要。

    struct B {};
    struct D : B {};
    
    template<typename T>
    struct C {};
    
    C<B> *c = new C<D>; // error C<D> is completely different and has no relationship to C<B>
    
    // you might as well say:
    float *f = new char[50];
    

    考虑:

    template<>
    struct C<B> {
        int a,b,c;
        int foo() { return a+b+c;}
    };
    
    template<>
    struct C<D> {
        std::string s;
        std::string bar();
    };
    
    C<B> *c = new C<D>; // pretend it works.
    c->foo(); // C<D> doesn't have a,b or c and doesn't have a method foo...
    

    也许 NodeBase 应该只将边缘类型作为模板参数而不是边缘模板。

    template<typename Edge> struct NodeBase {
        QVector<Edge *> fromEdges;
    };
    

    那么DNode继承自NodeBase&lt;Edge&lt;DNode&gt;&gt;

    可能有更好的方法,可能更直接地使用 CRTP,但如果不了解更多当前设计,就很难说。

    【讨论】:

    • 我不知道并感谢您指出(继承和模板)。如果我将 addToEdges(EdgeTemplate *edge) 更改为 addToEdges(void *edge),则该代码有效,但这会扰乱基准测试过程(减慢 alg 并且时间不一致)。我会重新考虑程序的设计并研究 CRTP,如果失败,我会考虑你提出的解决方案。我的主要目标是不重复自己和更容易维护。再次感谢您的回复,非常有帮助。
    • 建议的解决方案 NodeBase>,就像一个魅力,所以你的回答非常有帮助,再次感谢对模板和继承的简要说明。确实尝试了几件事,但最后我仍然最终使用了您的解决方案。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2013-03-26
    • 1970-01-01
    • 2013-09-23
    • 1970-01-01
    • 1970-01-01
    • 2016-10-10
    • 2012-03-22
    • 2013-05-29
    相关资源
    最近更新 更多