61

How to stop the class to be inherited by other class.

Nawaz
  • 353,942
  • 115
  • 666
  • 851
Shashi
  • 2,860
  • 2
  • 34
  • 45
  • 5
    IMHO, using /*final*/ class Whatever {...} should be enough – baris.aydinoz Jan 17 '11 at 12:20
  • @baris.aydinoz: no, that doesn't help the compiler deduce that a(n overridden) virtual method in `T` won't be overridden anywhere else and therefore calling it will require a virtual lookup (while, if you specify `final`, it's not necessary). – lorro Aug 28 '16 at 19:09

6 Answers6

95

C++11 solution

In C++11, you can seal a class by using final keyword in the definition as:

class A final  //note final keyword is used after the class name
{
   //...
};

class B : public A  //error - because class A is marked final (sealed).
{                   //        so A cannot be derived from.
   //...
};

To know the other uses of final, see my answer here:


C++03 solution

Bjarne Stroustrup's code : Can I stop people deriving from my class?

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

Generic_lock

So we can make use of template to make the Usable_lock generic enough to seal any class:

template<class T>
class  Generic_lock 
{
    friend T;
    Generic_lock() {}                     //private
    Generic_lock(const Generic_lock&) {}  //private
};

class Usable : public virtual Generic_lock<Usable>
{
public:
    Usable() {}
};

Usable a; //Okay
class DD : public Usable { };

DD dd; //Not okay!
Community
  • 1
  • 1
Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • Why do you need to say `private:` in `Usable_lock`? – user541686 Sep 04 '11 at 23:16
  • @Mehrdad: Ohh.. I didn't actually notice that `private` is in fact not needed. After all, I'm using `class` keyword here (not `struct`). Maybe, I just didn't dare modify [Bjarne's code](http://www2.research.att.com/~bs/bs_faq2.html#no-derivation) much when making it generic. – Nawaz Sep 05 '11 at 09:12
  • 3
    Note that `friend T;` is C++11 only, though MSVC allowed it in C++03 as an extension. – GManNickG Feb 01 '13 at 20:23
  • what if I use a private inheritance?`class Usable : private virtual Usable_lock` – Joey.Z Aug 20 '13 at 11:35
  • 2
    Will private inheritance be ok here? Actually, I've tested that the private virtual inheritance works fine. And can I say that use private inheritance will be more reasonable here? After all, you don't want some one to use a `Base*` to manipulate an `A` object, the Base class is not designed for OOP. It's just a utility. Plz comments. – Joey.Z Aug 20 '13 at 11:49
  • @zoujyjs: Yes, `private` inheritance makes more sense. Thanks for the improvement. Note that in C++11, you should prefer `final` over these workarounds. – Nawaz Aug 20 '13 at 12:19
  • Note that the C++03 method doesn't stop you declaring DD. MSVC only notices when you declare an item of type DD. – cup Apr 16 '14 at 18:38
10

There are two ways, the simple cheap, and the correct one. The two answers by @Naveen and @Nawaz deal with the correct one, that requires manual creation of a sealer class for each class that you actually want to seal.

The not fool-proof way, which is used in the adobe libraries is using a templated class for that. The problem is that you cannot declare the template argument as a friend, and that means that you will have to switch from private to the less safe protected:

template <typename T>
class sealer {
protected: sealer() {}
};
class sealed : virtual sealer<sealed> {};

And you can automate it with a macro (I don't remember the exact flavor of the macro in Adobe's code):

#define seal( x ) virtual sealer<x>
class sealed : seal(sealed) 
{};

Now this will catch people that mistakenly try to inherit without knowing that they shouldn't:

class derived : sealed {};
int main() {
   derived d;  // sealer<T>::sealer() is protected within this context
}

But it will not inhibit people that really want to from deriving, as they can gain access to the constructor by deriving from the template themselves:

class derived : sealed, sealer<sealed> {};
int main() {
   derived d;
};

I am not sure whether this will change in C++0x, I think I recall some discussions on whether a class template would be allowed to befriend one of it's arguments, but in a cursory search through the draft I cannot really tell. If that was allowed then this would be a fine generic solution:

template <typename T>
class sealer {
   sealer() {}
   friend class T; // Incorrect in C++03
};
Nawaz
  • 353,942
  • 115
  • 666
  • 851
David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
  • `protected` does not work with GCC (with neither of C++98, C++11, C++14 enabled). Wondering, why it should: `derived` inherits* `sealer`, virtually, thus directly and thus needs to initialize it - but as constructor is protected only... – Aconcagua Jan 24 '18 at 14:32
9

C++11 adds the ability to prevent inheriting from classes or simply preventing overriding methods in derived classes. This is done with the special identifier final. For example:

class Base final { };

class Derived1 : Base { }; // ill-formed because the class Base has been marked final

or

class Base {
    virtual void f() final;
};

class Derived : Base {
    void f(); // ill-formed because the virtual function Base::f has been marked final

Note that final is not a language keyword. It is technically an identifier; it only gains special meaning when used in those specific contexts. In any other location, it can be a valid identifier.

Aconcagua
  • 24,880
  • 4
  • 34
  • 59
AzP
  • 1,081
  • 1
  • 16
  • 27
0

Based on Bjarne Stroustrup's http://www.stroustrup.com/bs_faq2.html#no-derivation FAQ with small modification without friend keyword usage:

// SEALED CLASS DEFINITIONS
class Usable_lock {
protected:
    Usable_lock() {}
    Usable_lock(const Usable_lock&) {}
};
#define sealed_class private virtual Usable_lock

// SEALED CLASS USAGE EXMAPLES
class UsableLast : sealed_class {
public:
    UsableLast(){}
    UsableLast(char*){}
};
class DD : public UsableLast {};

// TEST CODE
template <class T> T createInstance() {
    return T();
}
int main()
{
    createInstance<UsableLast>();
//  createInstance<DD>();
    return 0;
}
Konstantin Burlachenko
  • 5,233
  • 2
  • 41
  • 40
-1

The following code shows how to define a sealed class in C++/CLI.

class A sealed
{
    //here goes the class code
};

class B : public A
{
};

Now B : cannot inherit from A as it has been declared as 'sealed'. Also a detailed explanation about sealed keyword can be found here http://msdn.microsoft.com/en-us/library/0w2w91tf.aspx

Update: Added C++/CLI , also other answers have shown the latest C++11 way of achieving the same using final keyword.

Krishna Oza
  • 1,390
  • 2
  • 25
  • 50
  • 3
    This is for C++/CLI, not standard C++. – scobi Jun 20 '14 at 09:29
  • You should mention this is for C++/CLI. The portable C++ way is to specify final after class name. – Tanveer Badar May 15 '18 at 05:15
  • @scobi Minor nitpick: MSVC allows the use of `sealed` even in native C++, which I consider separate from C++/CLI. As a compiler-specific hack, you can use `#define final sealed` if you need more recent, portable code to work on older MSVC versions. – Tom Lint Mar 17 '22 at 22:56
-12

You cannot. C++ is not Java or C#. And also there is no point, ever, IMHO.

wilx
  • 17,697
  • 6
  • 59
  • 114
  • @moo-juice If you aren't defining any virtual functions in you class, what harm could happen by inheriting from it? – ulidtko Jan 17 '11 at 12:23
  • Either it is useful to inherit from the given class then why should you trying to deny it? Or it is not useful and nobody is going to do it. – wilx Jan 17 '11 at 12:24
  • 4
    @wilx: or someone might consider it useful even if it unsafe to do so... Say that your library has a container of X, held by pointer and that `X` has no virtual functions *nor virtual destructor*. If user code extended `X` and managed to get an instance of the extended class into the container, and if the container clean up code `delete`d the pointers then you would run into undefined behavior --potentially leak resources or die. Just because the language allows you to do something, it does not mean that it is a good idea. – David Rodríguez - dribeas Jan 17 '11 at 12:54
  • 1
    A common example of that pattern of usage are standard containers. They were not designed to be extended, and still many people will derive from them to add functionality. If you create a `myvector` by inheriting from `std::vector`, and delete though a pointer to `std::vector` then you are running into undefined behavior. – David Rodríguez - dribeas Jan 17 '11 at 12:56
  • So the lesson here is don't let people delete objects they didn't allocate, got it. – Jimbo Jan 17 '11 at 16:06
  • 1
    Inheriting from standard containers is possible and useful in certain situations. Making them "final" would be horrible loss. It all boils down to that you have to be careful and you have to know what you are doing. And that is the spirit of C++. You can shoot yourself in a foot easily but you can also make great and useful things. – wilx Jan 24 '11 at 11:29
  • For my own knowledge, @wilx, can you provide a couple of those "certain examples"? If I were to inherit from a container, I would rather define a wrapper class (painful, yes) with a virtual destructor and inherit from that. Because even in the .net world, you almost never inherit from the collections. – Tanveer Badar May 15 '18 at 05:18