我什么时候应该使用 C++ 私有继承?

2021-12-11 00:00:00 oop c++

与受保护的继承不同,C++ 私有继承进入了主流 C++ 开发.但是,我仍然没有找到它的好用途.

Unlike protected inheritance, C++ private inheritance found its way into mainstream C++ development. However, I still haven't found a good use for it.

你们什么时候使用它?

推荐答案

接受答案后的注意事项:这不是一个完整的答案.阅读其他答案,例如此处(概念上)和这里(都是理论上的和实践)如果你对这个问题感兴趣.这只是可以通过私有继承实现的奇特技巧.虽然很花哨这不是问题的答案.

Note after answer acceptance: This is NOT a complete answer. Read other answers like here (conceptually) and here (both theoretic and practic) if you are interested in the question. This is just a fancy trick that can be achieved with private inheritance. While it is fancy it is not the answer to the question.

除了 C++ 常见问题(链接在其他人的评论中)中显示的私有继承的基本用法之外,您还可以使用私有和虚拟继承的组合来密封一个类(在 .NET 术语中)或制作一个 final 类(在 Java 术语中).这不是一个常见的用途,但无论如何我觉得它很有趣:

Besides the basic usage of just private inheritance shown in the C++ FAQ (linked in other's comments) you can use a combination of private and virtual inheritance to seal a class (in .NET terminology) or to make a class final (in Java terminology). This is not a common use, but anyway I found it interesting:

class ClassSealer {
private:
   friend class Sealed;
   ClassSealer() {}
};
class Sealed : private virtual ClassSealer
{ 
   // ...
};
class FailsToDerive : public Sealed
{
   // Cannot be instantiated
};

Sealed 可以实例化.它派生自ClassSealer,可以像朋友一样直接调用私有构造函数.

Sealed can be instantiated. It derives from ClassSealer and can call the private constructor directly as it is a friend.

FailsToDerive 不会编译,因为它必须直接调用 ClassSealer 构造函数(虚拟继承要求),但不能编译,因为它在 Sealed 类,在这种情况下 FailsToDerive 不是 ClassSealer 的朋友.

FailsToDerive won't compile as it must call the ClassSealer constructor directly (virtual inheritance requirement), but it cannot as it is private in the Sealed class and in this case FailsToDerive is not a friend of ClassSealer.

编辑

评论中提到,在使用 CRTP 时,这无法通用.C++11 标准通过提供不同的语法来帮助模板参数消除该限制:

It was mentioned in the comments that this could not be made generic at the time using CRTP. The C++11 standard removes that limitation by providing a different syntax to befriend template arguments:

template <typename T>
class Seal {
   friend T;          // not: friend class T!!!
   Seal() {}
};
class Sealed : private virtual Seal<Sealed> // ...

当然这都是没有实际意义的,因为 C++11 提供了一个 final 上下文关键字正是为了这个目的:

Of course this is all moot, since C++11 provides a final contextual keyword for exactly this purpose:

class Sealed final // ...

相关文章