Another way to prohibit a specific construction of a C ++ class other than declaring a private constructor?

Let's say I have a class with some const reference variable, and I would like to forbid a certain type of construction. Therefore, I declare the corresponding private constructor. Of course, the constructor must initialize all member variables of the const reference class. However, this leads to odd code:

class A { }; class B { B(const A& a): host(a) {} private: B():host(A()) {} // This is ugly and not needed !! const A& host; }; 

Is there any other way to prohibit a specific type of construct than declaring a private constructor? I do not want the compiler to write a constructor for me.

+6
source share
4 answers

Just don't define it:

 B():host(A()) {} // This is ugly and not needed !! 

That is, the following should do what you want to do:

 class B { B(const A& a): host(a) {} private: //B():host(A()) {} // This is ugly and not needed !! const A& host; }; 

The idea is that you have defined a constructor that takes parameter (s), then the default constructor is not generated by the compiler. This means that instances of the above class cannot be created by default!

  B b1; //error - needs default constructor which doesn't exist! B b2(a); //ok - only way to create an instance! 

C ++ 11 Solution

In C ++ 11, you can explain, the compiler does not generate a specific constructor, like:

 struct B { B(const A &a) {} B() = delete; //disable }; 

Not only this. There is more to this, as described below:

Now the interesting part

You can also selectively disable the constructor for selected types, which makes delete more interesting. Consider this,

 struct A { A (int) {} }; 

An object of this class can be created not only with the int argument, but also with any type that is implicitly converted to int . For instance,

 A a1(10); //ok A a2('x'); //ok - char can convert to int implicitly B b; A a3(b); //ok - assume b provides user-defined conversion to int 

Now suppose that for some reason I do not want class A users to create objects with char or class B , which, fortunately or unfortunately, can implicitly convert to int , then you can disable them as:

 struct A { A(int) {} A(char) = delete; //disable A(const B&) = delete; //disable }; 

Now you go:

 A a1(10); //ok A a2('x'); //error B b; A a3(b); //error - assume (even if) b provides user-defined conversion to int 

Online Demo: http://ideone.com/EQl5R

The error messages are very clear:

prog.cpp: 9: 5: error: remote function "A :: A (char)"
prog.cpp: 10: 5: error: remote function 'A :: A (const B &)'

+14
source

Just leave it. Once you create a custom constructor, no constructor is created automatically (except for the copy constructor).

If you want to forbid any construct - ultimately with a class that has only static members, you can simply declare the constructor as private, rather than defining it. Such a class is very rarely used in C ++ (since you cannot instantiate it); the only goal I can think of is to implement feature classes:

 template <typename T> struct type_to_color { static char const* value() { return "blue"; } private: type_to_color(); }; template <> struct type_to_color<int> { // Integers are red! static char const* value() { return "red"; } private: type_to_color(); } char const* char_color = type_to_color<char>::value(); char const* int_color = type_to_color<int>::value(); 

However, this is very rare: attribute classes are plentiful in C ++, but they never declare their constructors as private , but simply assume that everyone knows that they are not creating them.

+11
source

I will post a C ++ 11 solution: remove the constructor.

 class B { B() = delete; B(const A& a): host(a) {} private: const A& host; }; 
+2
source

As Conrad Rudolph said: when you provide your own constructor, no constructor is created automatically (except for the copy constructor).

Therefore, other options:

Declare the constructor closed (so that you cannot inherit your class), but do not provide a definition:

 class B { public: B(const A& a): host(a) {} private: B(); // not implemented! const A& host; }; 

Or in C ++ 11, as R. Martigno Fernandez says:

 class B { public: B() = delete; B(const A& a): host(a) {} private: const A& host; }; 
0
source

Source: https://habr.com/ru/post/896695/


All Articles