C++;没有子类的对象? 我想知道是否有一种方法来声明C++中的对象,以防止它被子类化。是否有一种等价于在Java中声明最终对象的方法?

C++;没有子类的对象? 我想知道是否有一种方法来声明C++中的对象,以防止它被子类化。是否有一种等价于在Java中声明最终对象的方法?,c++,C++,不,实际上不需要这样做。如果您的类没有虚拟析构函数,那么从它派生是不安全的。所以不要给它一个 您可以使用此技巧,复制自: 在C++0x中(作为扩展,在MSVC中),您实际上可以使其非常干净: template <typename T> class final { private: friend T; // C++0x, MSVC extension final() {} final(const final&) {} }; class no_deri

不,实际上不需要这样做。如果您的类没有虚拟析构函数,那么从它派生是不安全的。所以不要给它一个

您可以使用此技巧,复制自:

在C++0x中(作为扩展,在MSVC中),您实际上可以使其非常干净:

template <typename T>
class final
{
private:
    friend T; // C++0x, MSVC extension

    final() {}
    final(const final&) {}
};

class no_derived :
    public virtual final<no_derived> // ah, reusable
{};
模板
期末考试
{
私人:
friend T;//C++0x,MSVC扩展
最终(){}
最终(常量最终&){}
};
类别编号:
公共虚拟最终版//啊,可重用
{};

真的没有办法。您所能做的最好的事情就是将所有成员函数设置为非虚函数,并将所有成员变量设置为私有变量,这样子类化就没有任何好处了。


最接近的是声明构造函数<代码>私下<代码>,然后提供静态工厂方法。

C++中没有直接的等价语言构造。 在技术上实现这一点的常用习惯用法是将其构造函数声明为私有。要实例化这样一个类,您需要定义一个公共静态工厂方法

这就是所谓的“制作课堂” “最后一个”或“一片叶子”。有三个 方法:一个简单的技术 方法,一种更简单的非技术性方法 方法,和一个稍微棘手 技术方法

简单的技术方法是 使类的构造函数私有 使用 创建对象。没有人能 创建派生类的对象 因为基类的构造函数 将无法访问。名为 构造器“自己可以也可以

非技术性(更简单) 方法是把一个大胖子放在一个丑陋的地方 类定义旁边的注释。 例如,评论可以说,
//
如果你继承了我们的遗产,我们会解雇你
这门课是
甚至是/*期末考试*/ 类{…}。一些 程序员对此犹豫不决,因为它是 由人而不是由人来执行 技术,但不要在脸上敲打它 价值观:这是相当有效的 练习

一种略显棘手的技术方法 就是利用。 自,以下 保证没有具体的类可以 从类继承Fred:

Class
Fred
可以访问
FredBase
的ctor, 由于Fred是FredBase的朋友, 但是没有从Fred派生的类可以 访问FredBase的ctor,因此 没有人可以创建一个具体的类 源于Fred

如果你处于极度危险之中 空间受限环境(例如 作为嵌入式系统或手持设备 由于内存有限等),您应该 请注意,上述技术 可能会增加一个单词的记忆
sizeof(Fred)
。那是因为大多数 编译器实现虚拟 通过在中添加指针进行继承 派生类的对象。这是 编译器特定的;你的里程数可能会增加 变化


从C++11开始,您可以将final关键字添加到类中,例如

class CBase final
{
...

我看到想要这样做的主要原因(也是我来寻找这个问题的原因)是将一个类标记为非子类化,这样你就可以安全地使用非虚拟析构函数并完全避免vtable。

如果你这样做了,如果你做了
类派生:私有基
,它还不能子类化吗?(这里是C++noob)@dreamlax,不,它没有帮助。私有继承只会进一步限制对基类成员的访问。@Péter:很高兴知道。是时候从同事那里获取我的C++书籍了。你真的想阻止一个类被子类化吗?很难真正了解一个类的未来用法。在C++中停止类被子类化是一个真正的需要。你不需要虚拟方法,在每个实例中都会节省4字节。实际上,我不打算限制子类。我只是好奇,因为我正在从java背景中学习C++,谢谢你的详细回答+1。我在标准的副本中找不到。我不知道标准,我没有读过,但是它在Bjarne Stroustrup的C++ 11中被记录了——新的ISO C++标准在OK,现在我实际上在语言标准中找到了这个用法。没有像
class Base final
这样的例子,但是在第9章第一段的文本中提到了它的用法:“如果一个类用class virt说明符
final
标记,并且它在一个Base子句(第10条)中显示为一个基类型说明符,那么程序的格式就不正确。”。这意味着,
class Base final
不能从中派生。
 class Fred;

 class FredBase {
 private:
   friend class Fred;
   FredBase() { }
 };

 class Fred : private virtual FredBase {
 public:
   ...
 }; 
class CBase final
{
...