C++ 将派生类的成员更改为其专用版本
Posted
技术标签:
【中文标题】C++ 将派生类的成员更改为其专用版本【英文标题】:C++ change a member of derived class to it's specialized version 【发布时间】:2018-11-20 21:31:15 【问题描述】:假设我有两个类 - Graph 和 Vertex,它们具有表示一般 Graph 所需的一些基本成员和方法。它们已经完全实现并且非常适用于标准图。
class Vertex
int id;
Vertex(int id) : id(id)
// ...
class Graph
std::vector<Vertex *> vertices;
void addVertex(int id)
vertices.push_back(new Vertex(id));
// ...
我想扩展这些类以添加一些与问题相关的功能。例如,我想要一个 Vertex 来存储它的颜色。这就是为什么我声明另一个名为VertexC 的类,它继承自Vertex 并添加了一个新成员。所以现在我想要一个专门版本的 Graph - GraphC 可以管理新的 VertexC 属性。
class VertexC: Vertex
string colour;
string getColour()
return colour;
class GraphC: Graph
void doSomething(string colour)
for(auto &v: vertices)
if(v->getColour() == "red") // Do something...
但我不能这样做,因为 Graph::vertices 的类型是 Vertex * 而不是 VertexC * 所以他们不会有 getColour() 方法。有什么建议可以解决这个问题吗?
编辑:稍微更改了描述以更直接地介绍我的问题。
【问题讨论】:
使用它们的东西要么需要颜色,要么不需要。如果它需要颜色,它应该总是取一个顶点。如果不是,那么它不应该。通过在顶点对象列表上执行 dynamic_cast 以检查它们在运行时是否是 vertexc 对象,您正处于做一些糟糕的设计的风口浪尖。不要这样做。相反,答案是从 Graph 中取出顶点,使其成为仅接口类,然后制作一个颜色图和一个无颜色图,每个图都存储了他们需要的适当顶点类型。您还可以使用模板来指定要存储的 Vertex 类型 @xaxxon 一切听起来都很合理,但问题是 Graph 类已经实现,它提供了您可能需要使用图形的大量方法。您不认为提供与图本身无关的功能,而是与一些与问题相关的细节相关的功能应该在一些从 Graph 类继承主要实现的专用类中完成吗? 我建议搜索虚拟方法 "Graph 类已经实现" - 听起来你是在误用它作为基类。在听起来像 Graph 的设计目的和您尝试使用它的目的之间存在根本的设计分歧。不是每个类都是好的基类。 您的额外要求应在您的问题中详细说明,以激发您正在寻找的答案。但是,由于Graph
不能存储VertexC
(因为addVertex
的定义方式),GraphC
的设计似乎有缺陷。
【参考方案1】:
一种选择是模板化 Graph 类。比如:
template<typename TVert> class Graph
std::vector<TVert> vertices;
// ...
;
这意味着特化可以声明为:
class GraphC : public Graph<VertexC*>
// ...
;
不过,可能需要对 addVertex 方法做一些事情。可以这样声明:
void addVertex(int id)
vertices.push_back(new TVert(id));
虽然这意味着 Graph 类的任何特化只能是包含一个构造函数的类型,该构造函数采用单个 int 参数。另一种方法是:
void addVertex(TVert vert)
vertices.push_back(vert);
还要注意在 GraphC 的类声明中添加了 public 关键字。这将需要通过 GraphC 的实例使 Graph 的 addVertex 方法可用。
【讨论】:
以上是关于C++ 将派生类的成员更改为其专用版本的主要内容,如果未能解决你的问题,请参考以下文章