Say I have a class with some const reference member variable and I would like to forbid a certain type of construction. So I would declare the according constructor private. Of course, a constructor must initialise all const reference member variables of the class. Doing so, however, results in odd looking 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 another way to prohibit a certain construction type except than declaring the constructor private? I do not want to let the compiler write a constructor for me.
Simply don't define this:
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 if you've defined a constructor that takes parameter(s), then the default constructor is not generated by the compiler. That means, instances of the above class cannot be default created!
B b1; //error - needs default constructor which doesn't exist!
B b2(a); //ok - only way to create an instance!
In C++11, you can explicity tell the compiler not to generate a particular constructor as:
struct B
{
B(const A &a) {}
B() = delete; //disable
};
Not only that. There is more to it, as explained below:
You can also selectively disable constructor(s) for selected types which makes delete more interesting. Consider this,
struct A
{
A (int) {}
};
Object of this class can be created not only with int argument, but any type which implicitly converts to int. For example,
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, for whatever reason, I don't want the users of class A 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 here 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: deleted function 'A::A(char)'
prog.cpp:10:5: error: deleted function 'A::A(const B&)'
Just leave it out. As soon as you provide a custom constructor, no other constructor is auto-generated (except for a copy constructor).
If you want to forbid any construction – ending up with a class that has only static members – you can simply declare the constructor as private, and not define it. Such a class is very rarely useful in C++ (since you cannot create instances of it); the only purpose that I can think of is to implement trait 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 extremely uncommon: trait classes are abundant in C++ but they never declare their constructors as private, it’s just assumed that everybody knows not to instantiate them.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With