简体   繁体   English

没有子类的C ++对象?

[英]C++ object without subclasses?

I was wondering if there is a way to declare an object in c++ to prevent it from being subclassed. 我想知道是否有办法在c ++中声明一个对象以防止它被子类化。 Is there an equivalent to declaring a final object in Java? 是否有相当于在Java中声明最终对象?

From C++ FAQ, section on inheritance C ++ FAQ,继承部分

This is known as making the class "final" or "a leaf." 这被称为使课程“最终”或“一片叶子”。 There are three ways to do it: an easy technical approach, an even easier non-technical approach, and a slightly trickier technical approach. 有三种方法可以实现:简单的技术方法,更简单的非技术方法,以及稍微复杂的技术方法。

The (easy) technical approach is to make the class's constructors private and to use the Named Constructor Idiom to create the objects. (简单)技术方法是使类的构造函数为私有,并使用Named Constructor Idiom来创建对象。 No one can create objects of a derived class since the base class's constructor will be inaccessible. 没有人可以创建派生类的对象,因为基类的构造函数将无法访问。 The "named constructors" themselves could return by pointer if you want your objects allocated by new or they could return by value if you want the objects created on the stack . 如果您希望您的对象由new分配,那么 “命名构造函数”本身可以通过指针返回,或者如果您希望在堆栈上创建对象,它们可以按值返回

The (even easier) non-technical approach is to put a big fat ugly comment next to the class definition. (更简单的)非技术方法是在类定义旁边添加一个很大的丑陋评论。 The comment could say, for example, // We'll fire you if you inherit from this class or even just /*final*/ class Whatever {...}; 例如,评论可以说// We'll fire you if you inherit from this class// We'll fire you if you inherit from this class甚至只是/*final*/ class Whatever {...}; . Some programmers balk at this because it is enforced by people rather than by technology, but don't knock it on face value: it is quite effective in practice. 一些程序员对此不以为然,因为它是由人而不是技术强制实施的,但不要贬低它的表面价值:它在实践中非常有效。

A slightly trickier technical approach is to exploit virtual inheritance . 一种稍微棘手的技术方法是利用虚拟继承 Since the most derived class's ctor needs to directly call the virtual base class's ctor , the following guarantees that no concrete class can inherit from class Fred : 由于大多数派生类的ctor需要直接调用虚拟基类的ctor ,因此以下保证没有具体类可以从Fred类继承:

 class Fred;

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

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

Class Fred can access FredBase 's ctor, since Fred is a friend of FredBase , but no class derived from Fred can access FredBase's ctor, and therefore no one can create a concrete class derived from Fred . Fred类可以访问FredBase的ctor,因为FredFredBase的朋友,但是没有派生自Fred的类可以访问FredBase的ctor,因此没有人可以创建一个派生自Fred的具体类。

If you are in extremely space-constrained environments (such as an embedded system or a handheld with limited memory, etc.), you should be aware that the above technique might add a word of memory to sizeof(Fred) . 如果您处于极其空间受限的环境中(例如嵌入式系统或内存有限的手持设备等),您应该知道上述技术可能会向sizeof(Fred)添加一个内存字。 That's because most compilers implement virtual inheritance by adding a pointer in objects of the derived class. 这是因为大多数编译器通过在派生类的对象中添加指针来实现虚拟继承。 This is compiler specific; 这是编译器特定的; your mileage may vary. 你的旅费可能会改变。

No, there isn't really a need to. 不,没有必要。 If your class doesn't have a virtual destructor it isn't safe to derive from it anyway. 如果你的类没有虚拟析构函数,那么从它派生它是不安全的。 So don't give it one. 所以不要给它一个。

You can use this trick, copied from Stroustrup's FAQ : 您可以使用这个技巧,从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

In C++0x (and as an extension, in MSVC) you can actually make it pretty clean: 在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
{};

NO .

The closest you can come is to declare the constructors private , then provide a static factory method. 最接近的是将构造函数声明为private ,然后提供静态工厂方法。

There is no direct equivalent language construct for this in C++. 在C ++中没有直接的等效语言结构。

The usual idiom to achieve this technically is to declare its constructor(s) private. 通常在技术上实现这一目标的习惯是将其构造函数声明为私有。 To instantiate such a class, you need to define a public static factory method then. 要实例化这样的类,您需要定义一个公共静态工厂方法。

As of C++11, you can add the final keyword to your class, eg 从C ++ 11开始,您可以将final关键字添加到您的类中,例如

class CBase final
{
...

The main reason I can see for wanting to do this (and the reason I came looking for this question) is to mark a class as non subclassable so you can safely use a non-virtual destructor and avoid a vtable altogether. 我可以看到想要这样做的主要原因(以及我来寻找这个问题的原因)是将一个类标记为非子类,这样你就可以安全地使用非虚析构函数并完全避免使用vtable。

There is no way really. 真的没有办法。 The best you can do is make all your member functions non-virtual and all your member variables private so there is no advantage to be had from subclassing the class. 你能做的最好的事情就是让你所有的成员函数都是非虚拟的,所有的成员变量都是私有的,所以从子类化中没有任何好处。

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

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