将公共方法私有化为基类的子类

问题描述 投票:0回答:1

我正在为图的类层次结构进行工作,在该结构中,我将此方法称为disjoint_union。因为基类包含需要为所有子类更新的属性(如邻接表),所以我在该类中放置了一个带有参数graph的方法,如下所示:

class graph {
    public:
        // ....
        void disjoint_union(const graph& g);
}

[它的两个子类是ugraph(无向图)和dgraph(有向图)。类dgraph需要更新“邻接”列表,即,图的每个顶点的邻接者的邻接列表。因此,我可以将方法graph::disjoint_union声明为虚拟方法,这就是故事的结尾。但是我不希望此类具有相同的方法(即,具有相同的参数类型),因为它会接受无向图。因此,我的“解决方案”(不是真的有问题)是:

class dgraph : public graph {
    public:
        // ....
        void disjoint_union(const dgraph& g);
        // ....
    private:
        using graph::disjoint_union;
}

如果我做这样的事情:

dgraph dG;
// initialise dG
ugraph uG;
// initialise uG
dG.disjoint_union(uG);

编译器会发出错误,因为唯一可以接受类disjoint_union中的ugraph的方法dgraph被声明为私有。这需要将方法声明为private只是一种解决方法,因为我可以执行以下操作:

graph* dG = new dgraph(); // I know smart pointers should be chosen over raw pointers
// initialise dG
ugraph uG;
// initialise uG
dG.disjoint_union(uG);

可以被认为是“坏”的东西,对于像生根树这样的子类,这种情况会更加恶化:

class rtree : public dgraph {
    public:
        // ....
        void disjoint_union(const rtree& t);
        // ....
    private:
        using dgraph::disjoint_union;
}

在执行此类操作后,必须更新自己的属性。显然,rtree::disjoint_union的可能实现是:

void rtree::disjoint_union(const rtree& t) {
    dgraph::disjoint_union(t);
    // update rtree's attributes
}

(在其他类中也是如此)。现在,C ++ 17允许这样做:

class graph {
    public:
        // ....
        virtual void disjoint_union(const graph& g);
}
class dgraph : public graph {
    public:
        // ....
        void disjoint_union(const dgraph& g);
        // ....
    private:
        // this time, graph::disjoint_union is not declared as private
        // using graph::disjoint_union;
}

但提出了一些警告,包括

graph.hpp:113: warning: ‘virtual void graph::disjoint_union(const graph&)’ was hidden [-Woverloaded-virtual]
  113 |   virtual void disjoint_union(const graph& g);
      |                ^~~~~~~~~~~~~~
dgraph.hpp:145: warning: 'dgraph::disjoint_union' hides overloaded virtual function

问题:是否有更好的方法可以重载方法disjoint_union?我担心这些警告告诉我,不能保证某些事情(如未调用适当的方法),或者这种重载方式允许调用父类的disjoint_union方法(我不想要)。任何帮助将不胜感激。

c++ inheritance overloading virtual-inheritance
1个回答
0
投票

是,您会收到此警告,因为签名disjoint_unions方法因参数类型而异。

解决此警告的最佳方法是在派生类中执行类似的操作

void disjoint_union(const graph& g)
{
    auto* d = dynamic_cast<dgraph*>(&g); // cast to pointer to avoid exceptions
    if (!d) {
        graph::disjoint_union(g);
        return;
    }
    // YOUR CODE IS HERE
}
© www.soinside.com 2019 - 2024. All rights reserved.