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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4712992/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 16:15:19  来源:igfitidea点击:

How to define sealed class in C++?

c++classinheritancederived-classsealed

提问by Shashi

How to stop the class to be inherited by other class.

如何阻止该类被其他类继承。

回答by Nawaz

C++11 solution

C++11 解决方案

In C++11, you can seal a class by using finalkeyword in the definition as:

在 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.
   //...
};

To know the other uses of final, see my answer here:

要了解 final 的其他用途,请在此处查看我的答案:



C++03 solution

C++03解决方案

Bjarne Stroustrup's code: Can I stop people deriving from my class?

Bjarne Stroustrup 的代码我可以阻止人们从我的班级派生吗?

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

通用锁

So we can make use of template to make the Usable_lockgeneric enough to seal any class:

所以我们可以利用模板来使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!

回答by David Rodríguez - dribeas

There are two ways, the simple cheap, and the correct one. The two answers by @Naveen and @Nawaz deal with the correct one, that requires manual creation of a sealerclass for each class that you actually want to seal.

有两种方法,一种简单便宜,一种正确。@Naveen 和 @Nawaz 的两个答案处理的是正确的答案,即需要为您实际想要密封的每个类手动创建一个密封器类。

The not fool-proof way, which is used in the adobe libraries is using a templated class for that. The problem is that you cannot declare the template argument as a friend, and that means that you will have to switch from privateto the less safe protected:

adobe 库中使用的并非万无一失的方法是为此使用模板化类。问题是您不能将模板参数声明为友元,这意味着您必须从不private安全的切换到protected

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

And you can automate it with a macro (I don't remember the exact flavor of the macro in Adobe's code):

你可以用一个宏自动化它(我不记得 Adob​​e 代码中宏的确切风格):

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

Now this will catch people that mistakenly try to inherit without knowing that they shouldn't:

现在这将捕获那些错误地尝试继承而不知道他们不应该继承的人:

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

But it will not inhibit people that reallywant to from deriving, as they can gain access to the constructor by deriving from the template themselves:

但它不会阻止真正想要派生的人,因为他们可以通过自己从模板派生来访问构造函数:

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

I am not sure whether this will change in C++0x, I think I recall some discussions on whether a class template would be allowed to befriend one of it's arguments, but in a cursory search through the draft I cannot really tell. If that was allowed then this would be a fine generic solution:

我不确定这是否会在 C++0x 中改变,我想我记得关于是否允许类模板与其中一个参数成为朋友的一些讨论,但在草稿中粗略搜索我无法确定。如果允许,那么这将是一个很好的通用解决方案:

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

回答by AzP

C++11 adds the ability to prevent inheriting from classes or simply preventing overriding methods in derived classes. This is done with the special identifier final. For example:

C++11 添加了防止从类继承或简单地防止在派生类中覆盖方法的能力。这是通过特殊标识符完成的final。例如:

class Base final { };

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

or

或者

class Base {
    virtual void f() final;
};

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

Note that final is not a language keyword. It is technically an identifier; it only gains special meaning when used in those specific contexts. In any other location, it can be a valid identifier.

请注意,final 不是语言关键字。从技术上讲,它是一个标识符;只有在这些特定上下文中使用时,它才会获得特殊含义。在任何其他位置,它可以是有效标识符。

回答by bruziuz

Based on Bjarne Stroustrup's http://www.stroustrup.com/bs_faq2.html#no-derivationFAQ with small modification without friend keyword usage:

基于 Bjarne Stroustrup 的http://www.stroustrup.com/bs_faq2.html#no-derivationFAQ,稍加修改,没有使用朋友关键字:

// 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;
}

回答by Krishna Oza

The following code shows how to define a sealed class in C++/CLI.

以下代码显示了如何在 C++/CLI 中定义密封类。

class A sealed
{
    //here goes the class code
};

class B : public A
{
};

Now B : cannot inherit from A as it has been declared as 'sealed'. Also a detailed explanation about sealed keyword can be found here http://msdn.microsoft.com/en-us/library/0w2w91tf.aspx

现在 B :不能从 A 继承,因为它已被声明为“密封”。还可以在此处找到有关 Sealed 关键字的详细说明http://msdn.microsoft.com/en-us/library/0w2w91tf.aspx

Update: Added C++/CLI , also other answers have shown the latest C++11 way of achieving the same using finalkeyword.

更新:添加了 C++/CLI ,其他答案也显示了使用final关键字实现相同的最新 C++11 方式。

回答by wilx

You cannot. C++ is not Java or C#. And also there is no point, ever, IMHO.

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