繁体   English   中英

没有子类的C ++对象?

[英]C++ object without subclasses?

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

C ++ FAQ,继承部分

这被称为使课程“最终”或“一片叶子”。 有三种方法可以实现:简单的技术方法,更简单的非技术方法,以及稍微复杂的技术方法。

(简单)技术方法是使类的构造函数为私有,并使用Named Constructor Idiom来创建对象。 没有人可以创建派生类的对象,因为基类的构造函数将无法访问。 如果您希望您的对象由new分配,那么 “命名构造函数”本身可以通过指针返回,或者如果您希望在堆栈上创建对象,它们可以按值返回

(更简单的)非技术方法是在类定义旁边添加一个很大的丑陋评论。 例如,评论可以说// We'll fire you if you inherit from this class// We'll fire you if you inherit from this class甚至只是/*final*/ class Whatever {...}; 一些程序员对此不以为然,因为它是由人而不是技术强制实施的,但不要贬低它的表面价值:它在实践中非常有效。

一种稍微棘手的技术方法是利用虚拟继承 由于大多数派生类的ctor需要直接调用虚拟基类的ctor ,因此以下保证没有具体类可以从Fred类继承:

 class Fred;

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

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

Fred类可以访问FredBase的ctor,因为FredFredBase的朋友,但是没有派生自Fred的类可以访问FredBase的ctor,因此没有人可以创建一个派生自Fred的具体类。

如果您处于极其空间受限的环境中(例如嵌入式系统或内存有限的手持设备等),您应该知道上述技术可能会向sizeof(Fred)添加一个内存字。 这是因为大多数编译器通过在派生类的对象中添加指针来实现虚拟继承。 这是编译器特定的; 你的旅费可能会改变。

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

您可以使用这个技巧,从Stroustrup的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
{};

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

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

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

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

class CBase final
{
...

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM