没有子类的C ++对象?

时间:2010-10-06 21:07:51

标签: c++

我想知道是否有办法在c ++中声明一个对象以防止它被子类化。是否有相当于在Java中声明最终对象?

6 个答案:

答案 0 :(得分:13)

来自C++ FAQ, section on inheritance

  

这被称为上课   “最后”或“一片叶子”。有三种   方法:简单的技术   方法,更简单的非技术性   方法,有点棘手   技术方法。

     

(简单)技术方法是   使类的构造函数成为私有的   并使用Named Constructor Idiom   创建对象。没人能   创建派生类的对象   自从基类的构造函数   将无法进入。 “命名   构造者“他们自己可以return by pointer if you want your objects allocated by new或他们可以return by value if you want the objects created on the stack

     

(更简单)非技术性   方法是一个大胖子   在类定义旁边发表评论。   例如,评论可以说是// We'll fire you if you inherit from this class,甚至只是/*final*/ class Whatever {...};。一些   程序员对此犹豫不决,因为它是   由人而不是由人强制执行   技术,但不要把它敲在脸上   价值:它非常有效   实践。

     

稍微棘手的技术方法   是利用virtual inheritance。   自the most derived class's ctor needs to directly call the virtual base class's ctor起,以下内容如下   保证没有具体的课程   继承自班级Fred

 class Fred;

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

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

班级Fred可以访问FredBase的ctor,   由于FredFredBase的朋友,   但没有派生自弗雷德的班级可以   访问FredBase的ctor,因此   没人能创造出具体的课程   源自Fred

     

如果你非常   空间受限的环境(如   作为嵌入式系统或手持设备   有限的记忆等),你应该   请注意上述技巧   可能会添加一个记忆词   sizeof(Fred)。这是因为大多数   编译器实现虚拟化   通过添加指针继承   派生类的对象。这是   编译具体;你的里程可能   而变化。

答案 1 :(得分:7)

不,确实没有必要。如果你的类没有虚拟析构函数,那么从它派生它是不安全的。所以不要给它一个。

你可以使用这个技巧,从Stroustrup's FAQ复制:

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

在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
{};

答案 2 :(得分:2)

最接近的是声明构造函数private,然后提供静态工厂方法。

答案 3 :(得分:2)

在C ++中没有直接的等效语言构造。

在技术上实现这一目标的通常习惯是将其构造函数声明为私有。要实例化这样的类,您需要定义一个公共静态工厂方法。

答案 4 :(得分:1)

从C ++ 11开始,您可以将最终关键字添加到您的班级,例如

class CBase final
{
...

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

答案 5 :(得分:-1)

真的没办法。你能做的最好的事情就是让你所有的成员函数都是非虚拟的,所有的成员变量都是私有的,所以从子类化类中没有任何好处。