假设我有一个带有 const reference 成员变量的类,我想禁止某种类型的构造。所以我会声明相应的构造函数 private 。当然,构造函数必须初始化类的所有 const引用成员变量。但是,这样做会产生奇怪的代码:
class A {
};
class B {
B(const A& a): host(a) {}
private:
B():host(A()) {} // This is ugly and not needed !!
const A& host;
};
除了将构造函数声明为私有之外,还有其他方法可以禁止某种构造类型吗?我不想让编译器为我编写构造函数。
答案 0 :(得分:14)
根本不要定义:
B():host(A()) {} // This is ugly and not needed !!
也就是说,以下内容应该做你想做的事情:
class B {
B(const A& a): host(a) {}
private:
//B():host(A()) {} // This is ugly and not needed !!
const A& host;
};
这个想法是,如果你定义了一个带参数的构造函数,那么编译器就不会生成默认的构造函数。这意味着,上述类的实例不能 默认创建!
B b1; //error - needs default constructor which doesn't exist!
B b2(a); //ok - only way to create an instance!
在C ++ 11中,您可以明确告诉编译器不要生成特定的构造函数:
struct B
{
B(const A &a) {}
B() = delete; //disable
};
不仅如此。还有更多内容,如下所述:
您还可以有选择地禁用所选类型的构造函数,这会使delete
更有趣。考虑一下,
struct A
{
A (int) {}
};
此类的对象不仅可以使用int
参数创建,还可以使用隐式转换为int
的任何类型创建。例如,
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
现在假设,无论出于何种原因,我都不希望类A
的用户创建char
或class B
的对象,幸运或遗憾的是隐式地< / em>转换为int
,然后您可以将它们禁用为:
struct A
{
A(int) {}
A(char) = delete; //disable
A(const B&) = delete; //disable
};
现在你走了:
A a1(10); //ok
A a2('x'); //error
B b;
A a3(b); //error - assume (even if) b provides user-defined conversion to int
错误消息非常清楚:
prog.cpp:9:5:错误:已删除的函数'A :: A(char)'
prog.cpp:10:5:错误:删除函数'A :: A(const B&amp;)'
答案 1 :(得分:11)
请不要理会。只要提供自定义构造函数,就不会自动生成其他构造函数(复制构造函数除外)。
如果你想禁止任何构造 - 最后只有一个只有静态成员的类 - 你可以简单地将构造函数声明为私有,而不是定义它。这样的类在C ++中很少有用(因为你不能创建它的实例);我能想到的唯一目的是实现特质类:
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();
然而,这是非常罕见的:特征类在C ++中很丰富,但它们从未将它们的构造函数声明为private
,它只是假设每个人都知道不实例化它们。
答案 2 :(得分:2)
我将发布C ++ 11解决方案: delete 构造函数。
class B {
B() = delete;
B(const A& a): host(a) {}
private:
const A& host;
};
答案 3 :(得分:0)
正如Konrad Rudolph所说:只要提供自定义构造函数,就不会自动生成其他构造函数(复制构造函数除外)。
因此,其他选择是:
将构造函数声明为private(以便您不能从类继承),但不提供定义:
class B {
public:
B(const A& a): host(a) {}
private:
B(); // not implemented!
const A& host;
};
或者在C ++ 11中,正如R. Martinho Fernandes所说:
class B {
public:
B() = delete;
B(const A& a): host(a) {}
private:
const A& host;
};