可能重复:
什么时候应该使用 C++ 私有继承?
我想创建这个社区维基,但没有看到按钮...有人可以添加它吗?
我想不出任何以非公开方式从类派生的案例,并且我不记得当时看到过执行此操作的代码。
我想听听现实世界中有用的示例和模式。
您的里程可能会有所不同...
最核心的答案是非公有继承是没有用的。
就我个人而言,我在两种情况下使用它:
virtual
函数无论哪种情况,我都会使用
private
继承,因为继承本身就是一个实现细节。
我看到人们在编写包装器或扩展行为时更自由地、近乎系统地使用
private
继承,而不是组合。 C++ 不提供“简单”的委托语法,因此这样做允许您编写 using Base::method;
来立即提供方法,而不是编写正确的转发调用(及其所有重载)。我认为这是不好的形式,尽管它确实节省了时间。
[[no_unique_address]]
属性,空基优化在 C++20 中已过时。
如果您选择继承来开发包装器,那么私有继承是正确的选择。您不再需要或不想从包装类外部访问基类的方法和成员。
class B;
class A
{
public:
A();
void foo(B b);
};
class BWrap;
class AWrap : private A
{
public:
AWrap();
void foo(BWrap b);
};
//no longer want A::foo to be accessible by mistake here, so make it private
由于
private
继承的唯一已知用途是实现继承,并且由于这始终可以使用包含来完成(使用起来不太简单,但更好地封装了关系),我想说它使用得太频繁了。
(因为没有人告诉我
protected
继承意味着什么,所以我们假设没有人知道它是什么,并假装它不存在。)
有时继承既没有任何
virtual
函数也没有 virtual
析构函数的类(例如 STL 容器),您可能必须采用非 public
继承。例如
template<typename T>
struct MyVector : private std::vector<T>
{ ... };
这将不允许基类 (
vector<>
) 的句柄(指针或引用)获取派生 class
(MyVector<>
):
vector<int> *p = new MyVector<int>; // compiler error
...
delete p; // undefined behavior: ~vector() is not 'virtual'!
由于我们在第一行本身就遇到编译器错误,因此我们将避免后续行中的未定义行为。
如果您从没有虚拟析构函数的类派生,那么公共继承会导致该类的用户可以在指向基类的指针上调用delete,从而导致未定义的行为。
在这种情况下,使用私有继承是有意义的。
最常见的示例是从没有虚拟析构函数的 STL 容器私有派生。
C++FAQ 有一个很好的私有继承示例,可以扩展到许多实际场景。
私有继承的合法、长期使用是当您想要构建一个使用 Wilma 类中的代码的 Fred 类,并且 Wilma 类中的代码需要调用新类 Fred 中的成员函数时。在这种情况下,Fred 调用 Wilma 中的非虚拟对象,而 Wilma 调用自身(通常是纯虚拟对象),这些都被 Fred 覆盖。如果用组合来做到这一点会困难得多。
代码示例:
class Wilma {
protected:
void fredCallsWilma()
{
std::cout << "Wilma::fredCallsWilma()\n";
wilmaCallsFred();
}
virtual void wilmaCallsFred() = 0; // A pure virtual function
};
class Fred : private Wilma {
public:
void barney()
{
std::cout << "Fred::barney()\n";
Wilma::fredCallsWilma();
}
protected:
virtual void wilmaCallsFred()
{
std::cout << "Fred::wilmaCallsFred()\n";
}
};
继承时使用非公有(几乎总是私有)继承 (仅)行为,而不是界面。 我大部分时间都用过,但没用过 独家,在 mixin 中。
为了更好地讨论该主题,您可能需要阅读 Barton 和 Nackman(科学与工程 C++:高级简介 技术和示例,ISBN 0-201-53393-6。 尽管有这个名字,但这本书的大部分内容都是 适用于所有 C++,而不仅仅是科学和工程 应用程序。 尽管它已经过时了,但仍然值得一读。)