我正在尝试定义一个图形,其中顶点类是用模板定义的。然后,我如何在另一个类中定义指向此模板化顶点的指针。
template<class T1, class T2>
class Vertex {
public:
virtual T1 run(T2) = 0;
};
class Graph {
std::map<std::string, Vertex*> vertices; // <--- How do I do something like this
int** adjacency_matrix;
public:
void run() {
...
}
};
我一直在寻找关于Stack-Overflow的其他一些问题,常见的建议似乎是使用一个没有模板化的基类,并使用指针并将常用函数放在该类中。
但是,在我的代码中,函数run()
是常见函数,并使用模板作为返回类型。所以我不明白如何使用基类。
有什么想法吗?
答案 0 :(得分:5)
没有名为Vertex
的类,只有类的模板。
简单的方法是使用多态,因为你只存储指针:
定义一个基类所有Vertex
实例(专有与否)继承自。
template<class T1, class T2>
class Vertex : VertexBase {
public:
virtual T1 run(T2) = 0;
};
struct VertexBase {
~VertexBase() = default;
template<class T1, class T2> T1 run(T2 x) {
return dynamic_cast<Vertex<T1,T2>&>(*this).run(x);
}
};
无论如何,还要看看std::function
,看看这是否足以解决您的问题。
答案 1 :(得分:1)
您可以指定如下类型:
std::map<std::string, Vertex<int, int>*> vertices;
或者Graph
也是模板化的:
template<class T1, class T2>
class Graph {
std::map<std::string, Vertex<T1, T2>*> vertices;
答案 2 :(得分:1)
首先,正如我所说,你需要一个Vertex
继承的非模板基类:
struct Base
{
virtual ~Base() = default;
};
template<class T1, class T2>
class Vertex : public Base
{
public:
virtual T1 run(T2) = 0;
};
然后在您的Graph
功能中使用std::shared_ptr<Base>
代替Vertex*
:
class Graph {
std::map<std::string, std::shared_ptr<Base>> vertices;
public:
void run();
};
现在在run()
指针上调用Vertex
时,需要dynamic_cast
指针返回相应的派生类。在您的情况下,由于run()
是纯虚函数,因此无法在Vertex*
上实际调用Vertex::run()
。
int main()
{
Graph g;
g.vertices["xyz"] = std::make_shared<Vertex<int, int>>();
// error: field type 'Vertex<int, int>' is an abstract class
}
如果要调用Vertex
,请将run()
设为非纯虚函数并为其提供实现,或者使用派生类进行实现:
class Derived : public Vertex<int, int>
{
public:
int run(int n) { std::cout << n << '\n'; return 0; }
};
class Graph {
std::map<std::string, std::shared_ptr<Base>> vertices;
public:
template<class T2>
void call_run(std::shared_ptr<Base> p, T2 value)
{
if (auto derived = std::dynamic_pointer_cast<Derived>(p))
derived->run(value);
if (/* other derived classes... */);
}
void run();
};