更多 C++ 惯用法/最终类
外观
- 部分模拟 C++11 和其他语言中的 final 类特性。
- 部分阻止类进一步子类化或继承。
- 密封类
类设计者可能希望强制执行特定类不能被类用户进一步扩展或子类化。其他面向对象的语言,如 Java 和 C#,为类设计者提供了此功能。在 Java 中,关键字称为 final,而在 C# 中,它称为 sealed。最终类惯用法是在 C++ 中部分模拟此效果的一种方法。
最终类惯用法利用虚拟继承和友元类来创建 final 类的效果。该惯用法依赖于以下 C++ 规则:虚拟继承类的构造函数(和析构函数)由最派生类直接调用。如果阻止访问此类虚拟继承类的构造函数或析构函数,则该类不能进一步子类化。
class MakeFinal
{
MakeFinal() {} // private by default.
friend class sealed;
};
class sealed : virtual MakeFinal
{ };
class test : public sealed
{ };
int main (void)
{
test t; // Compilation error here.
}
在上面的示例中,test 类继承自 sealed 类,main 函数尝试实例化 test 类型的对象。实例化失败,因为 test 类无法访问 MakeFinal 类的私有构造函数,因为它被定义为私有并被虚拟继承。但是,友谊不可继承,因此无法创建 test 类型的对象。
请注意,该错误仅在实例化 test 类时才会发生。此行为与 Java 和 C# 中最终类行为不同。事实上,此惯用法不会阻止继承 sealed 类中定义的静态方法。只要 test 类未实例化,并且它仅访问 sealed 类的静态成员,编译器就不会报错。
C++11 标准提供了 final 修饰符,它可以用于阻止类被子类化。
class Base final { };
class test : public Base { }; // incorrect