简体   繁体   中英

C++ object without subclasses?

I was wondering if there is a way to declare an object in c++ to prevent it from being subclassed. Is there an equivalent to declaring a final object in Java?

From C++ FAQ, section on inheritance

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. 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 .

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 {...}; . 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 :

 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 .

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) . 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 :

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:

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.

There is no direct equivalent language construct for this in 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

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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