Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to forbid deriving from a class at compile time?

Tags:

c++

I have a value class according to the description in "C++ Coding Standards", Item 32. In short, that means it provides value semantics and does not have any virtual methods.

I don't want a class to derive from this class. Beside others, one reason is that it has a public nonvirtual destructor. But a base class should have a destructor that is public and virtual or protected and nonvirtual.

I don't know a possibility to write the value class, such that it is not possible to derive from it. I want to forbid it at compile time. Is there perhaps any known idiom to do that? If not, perhaps there are some new possibilities in the upcoming C++0x? Or are there good reasons that there is no such possibility?

like image 728
SebastianK Avatar asked Jun 16 '09 11:06

SebastianK


4 Answers

Bjarne Stroustrup has written about this here.


The relevant bit from the link:

Can I stop people deriving from my class?

Yes, but why do you want to? There are two common answers:

  • for efficiency: to avoid my function calls being virtual.
  • for safety: to ensure that my class is not used as a base class (for example, to be sure that I can copy objects without fear of slicing)

In my experience, the efficiency reason is usually misplaced fear. In C++, virtual function calls are so fast that their real-world use for a class designed with virtual functions does not to produce measurable run-time overheads compared to alternative solutions using ordinary function calls. Note that the virtual function call mechanism is typically used only when calling through a pointer or a reference. When calling a function directly for a named object, the virtual function class overhead is easily optimized away.

If there is a genuine need for "capping" a class hierarchy to avoid virtual function calls, one might ask why those functions are virtual in the first place. I have seen examples where performance-critical functions had been made virtual for no good reason, just because "that's the way we usually do it".

The other variant of this problem, how to prevent derivation for logical reasons, has a solution. Unfortunately, that solution is not pretty. It relies on the fact that the most derived class in a hierarchy must construct a virtual base. For example:

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

(from D&E sec 11.4.3).

like image 85
Simon P Stevens Avatar answered Oct 06 '22 07:10

Simon P Stevens


If you are willing to only allow the class to be created by a factory method you can have a private constructor.

class underivable {
    underivable() { }
    underivable(const underivable&); // not implemented
    underivable& operator=(const underivable&); // not implemented
public:
    static underivable create() { return underivable(); }
};
like image 30
Motti Avatar answered Oct 06 '22 08:10

Motti


Even if the question is not marked for C++11, for people who get here it should be mentioned that C++11 supports new contextual identifier final. See wiki page

like image 6
Tony Avatar answered Oct 06 '22 06:10

Tony


Take a good look here.
It's really cool but it's a hack.
Wonder for yourself why stdlib doesn't do this with it's own containers.

like image 4
the_drow Avatar answered Oct 06 '22 08:10

the_drow