简体   繁体   中英

Making a class non-inheritable by defining default private constructor

Although I have seen final and virtual inheritance methods achieve this, I cannot understand why defining no constructors, except a default private one, does not prevent a class from being inherited. (Also, base class's copy constructor and copy assignment methods should be declared private as a precaution.)

Basically what I mean is if a base class's constructor is private and it has no other constructors, then, when a derived class wants to extend this base class:

  1. The derived class cannot call the default constructor of the base class because it is defined private

  2. The derived class cannot call any non-default constructors of the base class since there are no such constructors

So it is a compile time error and I cannot find another way to get over this.

I am sure I am wrong somewhere; otherwise, I could find a page on the internet that offers this as a way of making a class non-inheritable, but please, explain to me why I am wrong.

final and private constructor are not the same thing.

Consider this:

struct A final {};
struct B: A {};

int main() {}

It won't compile, that's a fact.
Now consider this:

class A { A() {} };
struct B: A {};

int main() {}

It compiles. Ok, it happens that B() constructor is deleted but you are not using it. It won't compile if you change slightly the definition to:

struct B: A { B(): A() {} };

Anyway, the previous example just works (for some mean of works ), so what's the difference?
final forbids inheritance. A private constructor doesn't allow you to construct objects of that type but you can still define that type. Therefore you can do something like this (that doesn't make much sense but gives you an idea):

#include<type_traits>

class A { A() {}};
struct B: A {};

template<typename T>
void f() {
    static_assert(std::is_base_of<A, B>::value, "!");
    // ...
}

int main() {
    f<B>();
}

How is it that it compiles if you cannot inherit from A ? Because your assumption was wrong, you can inherit from A . You can't construct an object of type B , but you can still use B as a type as long as you don't try to create instances. On the other side, if you put there final you get a compile-time error and that's all, you cannot use type B in any way.

Why would the standard forbid that? In theory, nothing prevents you from declaring your Derived class a friend of the Base class. That would ensure the only possible way to extend your base class is through very well known classes. I can't think of any practical case and I think it's bad, but it is POSSIBLE to do such horror...

struct BaseClass
{
friend struct DerivedClass;

private:
    BaseClass() {}
};

struct DerivedClass : BaseClass
{
public:
    DerivedClass() {}
};

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