在基 class 的子 class 中私有化 public 方法
Privatising a public method in a subclass of a base class
我正在为图表开发 class 层次结构,其中我有一个名为 disjoint_union
的方法。因为基 class 包含需要为所有子 class 更新的属性(如邻接表),所以我在这个 class 中放置了一个方法,参数为 graph
,像这样:
class graph {
public:
// ....
void disjoint_union(const graph& g);
}
它的两个子class是ugraph
(无向图)和dgraph
(有向图)。 class dgraph
需要更新 "in-adjacency" 列表,即图中每个顶点的邻接列表。所以,我可以将方法 graph::disjoint_union
声明为虚拟方法,这就是故事的结尾。但我不希望此 class 具有相同的方法(即具有相同的参数类型),因为它会接受无向图。所以,我的"solution"(不是说它真的有问题)是:
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);
编译器发出错误,因为唯一可以在 class dgraph
中接受 ugraph
的名为 disjoint_union
的方法被声明为私有。这需要将方法声明为私有只是一种解决方法,因为我可以做类似的事情:
graph* dG = new dgraph(); // I know smart pointers should be chosen over raw pointers
// initialise dG
ugraph uG;
// initialise uG
dG.disjoint_union(uG);
可以被视为 "bad" 的东西,并且对于子 class 像有根树这样的子 class 甚至进一步加剧:
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
}
(在其他 classes 中也是如此)。现在,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
方法 class(我不想要)。任何帮助将不胜感激。
是的,您收到此警告是因为签名 disjoint_unions
方法因参数类型而异。
解决此警告的最佳方法是在派生的 class
中执行类似的操作
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
}
我正在为图表开发 class 层次结构,其中我有一个名为 disjoint_union
的方法。因为基 class 包含需要为所有子 class 更新的属性(如邻接表),所以我在这个 class 中放置了一个方法,参数为 graph
,像这样:
class graph {
public:
// ....
void disjoint_union(const graph& g);
}
它的两个子class是ugraph
(无向图)和dgraph
(有向图)。 class dgraph
需要更新 "in-adjacency" 列表,即图中每个顶点的邻接列表。所以,我可以将方法 graph::disjoint_union
声明为虚拟方法,这就是故事的结尾。但我不希望此 class 具有相同的方法(即具有相同的参数类型),因为它会接受无向图。所以,我的"solution"(不是说它真的有问题)是:
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);
编译器发出错误,因为唯一可以在 class dgraph
中接受 ugraph
的名为 disjoint_union
的方法被声明为私有。这需要将方法声明为私有只是一种解决方法,因为我可以做类似的事情:
graph* dG = new dgraph(); // I know smart pointers should be chosen over raw pointers
// initialise dG
ugraph uG;
// initialise uG
dG.disjoint_union(uG);
可以被视为 "bad" 的东西,并且对于子 class 像有根树这样的子 class 甚至进一步加剧:
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
}
(在其他 classes 中也是如此)。现在,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
方法 class(我不想要)。任何帮助将不胜感激。
是的,您收到此警告是因为签名 disjoint_unions
方法因参数类型而异。
解决此警告的最佳方法是在派生的 class
中执行类似的操作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
}