以下代码为行" e = f"提供了编译错误(至少在使用MS VS 2008时)。在main():
错误C2582:'运营商='功能在' B'
中不可用
class A {
public:
A() { }
static const double x;
};
const double A::x = 0.0;
class B {
public:
B() : x(0.0) { }
const double x;
};
int main( int argc, char *argv[] )
{
A c,d;
B e,f;
c = d;
e = f;
return 0;
}
应为两个类A和B生成默认赋值运算符!?
12.8.10中的:"如果类定义没有明确声明a 复制赋值运算符,其中一个是隐式声明的。"
答案 0 :(得分:15)
隐式生成的运算符将递归地分配每个非静态成员。但是,x
为const
,因此无法将其分配给class A
。这可以防止生成隐式运算符(具体而言,它会将其定义为已删除)。
这在C ++ 11 12.8 / 23中指定:
如果X具有:
,则将类X的默认复制/移动赋值运算符定义为已删除
- ...
- const非类类型(或其数组)的非静态数据成员,或
- ...
(虽然我只是注意到你的编译器早于C ++ 11;规则是相似的,但是用不同的语言指定,在旧的方言中没有"删除"函数的概念。)
如果你想要一个不能重新分配成员(或基类)的类的赋值运算符,你必须自己定义它。
在{{1}}中,常量成员是静态的,因此不构成对象的一部分。因此,它不会阻止(空)对象被分配。
答案 1 :(得分:4)
字段'x'
是const限定类型const double
,默认赋值运算符将毫无意义,并且隐式已删除此处
答案 2 :(得分:2)
A类和B类之间的明显区别是const成员x beeing静态与非静态。 在任何情况下,对const变量的赋值都是不可能的。
编译器显然会尝试为B类生成默认赋值运算符方法,并默默地决定不生成一个,因为成员x不允许赋值。
花了很长时间才发现这个......
BTW:如果省略了B类中x的初始化,编译器就足够聪明地发现了这个错误。