C++ 将派生类的成员更改为其专用版本

Posted

技术标签:

【中文标题】C++ 将派生类的成员更改为其专用版本【英文标题】:C++ change a member of derived class to it's specialized version 【发布时间】:2018-11-20 21:31:15 【问题描述】:

假设我有两个类 - GraphVertex,它们具有表示一般 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++ 将派生类的成员更改为其专用版本的主要内容,如果未能解决你的问题,请参考以下文章

在其派生类C++的构造函数中调用基类的构造函数[重复]

C++中的派生类,可以不定义对象直接调用基类的成员和调用自己的成员函数嘛???

在 C++ 中将指向基类的指针传递给派生类的成员函数

通过基类指针C++访问派生类的成员

C++基类和派生类的构造函数

C++ 派生模板类:访问实例的受保护成员