C++ c++;相互依赖的类模板、指针转换派生类

C++ c++;相互依赖的类模板、指针转换派生类,c++,qt,templates,gcc,clang,C++,Qt,Templates,Gcc,Clang,您好,我正在编写一个程序,显示/显示和基准测试不同的图形。图由节点和边组成。。。所以我的问题是我有两个模板类(templates),它们是所有派生类的基础 template <class Node> class Edge { public: Edge() : startN(0), endN(0), price(0) {} Edge(Node *startN, Node *endN, int price) : startN(startN), endN(endN), pr

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

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
};
模板
阶级边缘
{
公众:
Edge():startN(0),endN(0),price(0){}
边缘(节点*startN,节点*endN,整数价格):startN(startN),endN(endN),price(price)
{
开始->脚趾。向后推(这个);//这里有问题
endN->fromdedges.push_back(this);//这里有问题
}
节点*startNode()常量{
返回起始点;
}
Node*endNode()常量{
返回静态_-cast(endN);
}
int getPrice()常量{
退货价格;
}
无效设定价格(整数价格){
这个->价格=价格;
}
私人:
节点*startN;
节点*endN;
国际价格;
}; 
模板
类节点基
{
公众:
NodeBase():nodeId(0),键(0),状态(未标记),prev(0){
NodeBase(int-id,int-key):nodeId(id),key(key),state(未标记),prev(0){
无效添加边缘(边缘样板*边缘){
脚趾向后推(静态铸造(边缘));
}
int-nodeId;
int键;
国家;
NodeBase*prev;//prevous已扫描
QVector fromEdge;//开始
QVector toEdges;//结束
};
另一个模板类中出现错误:

template <template<class> class EdgeTemplate, class Node>
class DijkstraAlgorithm {
...
QVector<EdgeTemplate<Node> *> Edges; // the problem for derived classes
...
};
模板
类dijkstra算法{
...
QVector Edges;//派生类的问题
...
};
叮当声:

error: cannot initialize a parameter of type 'Edge<NodeBase<Edge> > *' with an rvalue of type 'Edge<DNode> *'
        startN->addToEdges(this);
                           ^~~~
错误:无法使用“Edge*”类型的右值初始化“Edge*”类型的参数
startN->addToEdges(本);
^~~~
通用条款:

错误:调用'QVector::push_back(Edge*const)'时没有匹配的函数
因此,据我所知,问题是派生类
DNode
classdnode:public NodeBase
)不能存储在基类型
NodeBase
的共容器中。。。我试过铸造它,但没有成功


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

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

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];
结构B{}; 结构D:B{}; 模板 结构C{}; C*C=新的C;//错误C完全不同,与C无关 //你不妨说: float*f=新字符[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...
模板
结构C{
INTA、b、c;
int foo(){返回a+b+c;}
};
模板
结构C{
std::字符串s;
std::string bar();
};
C*C=新的C;//假装它有效。
c->foo();//C没有a、b或C,也没有方法foo。。。
也许NodeBase应该只将边缘类型作为模板参数,而不是边缘模板

template<typename Edge> struct NodeBase {
    QVector<Edge *> fromEdges;
};
模板结构节点库{
边向量;
};
然后DNode继承自
节点库


也许有更好的方法,也许可以更直接地使用CRTP,但很难说没有看到更多当前的设计。

我不知道,谢谢你指出(继承和模板)。如果我将addToEdges(EdgeTemplate*edge)更改为addToEdges(void*edge),则代码可以工作,但这会扰乱基准测试过程(减慢alg,并且时间不一致)。我会重新考虑这个程序的设计,然后看看CRTP,如果失败了,我会考虑你提出的解决方案。我的主要目标是不重复我自己和更容易的维护。再次感谢您的回复,非常有帮助。建议的解决方案NodeBase非常有魅力,因此您的回答非常有帮助,再次感谢您对模板和继承的简要解释。我确实尝试了一些方法,但最终我还是使用了你的解决方案。谢谢
template<typename Edge> struct NodeBase {
    QVector<Edge *> fromEdges;
};