如何在C ++中定义密封类?

如何阻止类被其他类inheritance。

C ++ 11解决scheme

在C ++ 11中,可以通过在定义中使用final关键字来封闭一个类:

 class A final //note final keyword is used after the class name { //... }; class B : public A //error - because class A is marked final (sealed). { // so A cannot be derived from. //... }; 

要知道最终的其他用途,请参阅我的答案:

  • C ++ 11中的“final”关键字用于函数的目的是什么?

C ++ 03解决scheme

Bjarne Stroustrup的代码 : 我可以阻止派生自我class的人吗?

 class Usable; class Usable_lock { friend class Usable; private: Usable_lock() {} Usable_lock(const Usable_lock&) {} }; class Usable : public virtual Usable_lock { public: Usable(); Usable(char*); }; Usable a; class DD : public Usable { }; DD dd; // error: DD::DD() cannot access // Usable_lock::Usable_lock(): private member 

Generic_lock

所以我们可以利用模板来使Usable_lock通用性足以Usable_lock任何类:

 template<class T> class Generic_lock { friend T; Generic_lock() {} //private Generic_lock(const Generic_lock&) {} //private }; class Usable : public virtual Generic_lock<Usable> { public: Usable() {} }; Usable a; //Okay class DD : public Usable { }; DD dd; //Not okay! 

有两种方法,简单便宜,正确。 @Naveen和@Nawaz的两个答案处理了正确的答案,那就是需要手动为每个你想要封闭的类创build一个封闭类。

在adobe库中使用的不是傻瓜式的方法是使用模板类。 问题是你不能将模板参数声明为朋友,这意味着你将不得不从private切换到不太安全的protected

 template <typename T> class sealer { protected: sealer() {} }; class sealed : virtual sealer<sealed> {}; 

你可以用macros自动化(我不记得在Adobe的代码中的macros的确切味道):

 #define seal( x ) virtual sealer<x> class sealed : seal(sealed) {}; 

现在,这会发现错误地尝试inheritance的人不知道他们不应该:

 class derived : sealed {}; int main() { derived d; // sealer<T>::sealer() is protected within this context } 

但是它不会阻止那些真正想从中得到的人,因为他们可以通过从模板本身获得来访问构造函数:

 class derived : sealed, sealer<sealed> {}; int main() { derived d; }; 

我不确定这是否会在C ++ 0x中发生变化,我想我回想一下是否允许类模板与其中一个参数交换的讨论,但是通过草稿的粗略search我无法确定。 如果允许,那么这将是一个很好的通用解决scheme:

 template <typename T> class sealer { sealer() {} friend class T; // Incorrect in C++03 }; 

C ++ 11增加了防止inheritance类的能力,或者简单地防止派生类中的重写方法。 这是通过特殊标识符final来完成的。 例如:

 class Base final { }; class Derived1 : Base1 { }; // ill-formed because the class Base has been marked final 

要么

 class Base { virtual void f() final; }; class Derived : Base { void f(); // ill-formed because the virtual function Base::f has been marked final 

请注意,final不是一个语言关键字。 它在技术上是一个标识符; 在这些特定的情况下,它只会得到特殊的含义。 在任何其他位置,它可以是有效的标识符。

以下代码显示了如何在VS 2010中定义密封类。

 class A sealed { //here goes the class code }; class B : public A { }; 

现在B:不能从Ainheritance,因为它已被声明为“密封”。 另外关于密封关键字的详细解释可以在这里findhttp://msdn.microsoft.com/en-us/library/0w2w91tf.aspx

根据Bjarne Stroustrup的http://www.stroustrup.com/bs_faq2.html#no-derivation常见问题解答(FAQ)进行小修改,无需使用friend关键字:;

 // SEALED CLASS DEFINITIONS class Usable_lock { protected: Usable_lock() {} Usable_lock(const Usable_lock&) {} }; #define sealed_class private virtual Usable_lock // SEALED CLASS USAGE EXMAPLES class UsableLast : sealed_class { public: UsableLast(){} UsableLast(char*){} }; class DD : public UsableLast {}; // TEST CODE template <class T> T createInstance() { return T(); } int main() { createInstance<UsableLast>(); // createInstance<DD>(); return 0; } 

你不能。 C ++不是Java或C#。 恕我直言,没有任何意义。