基类中的赋值运算符在派生类中似乎不可用。鉴于这一守则:
#include <iostream>
class A{
int value;
public:
A& operator=(int value){
this->value = value;
return *this;
}
};
class B : public A{};
int main(){
B b;
b = 0; // Does not work
return 0;
}
GCC 6.4说:
错误:不匹配“operator=”(操作数类型为'B‘和'int')
这是怎么回事?
发布于 2019-02-06 02:50:10
当我们自己不提供赋值操作符时,每个类都至少有一个隐含定义的赋值运算符。
当派生类中的成员函数与基类中的成员同名定义时,它会隐藏该名称的所有基类定义。
您可以使用using声明,但请注意,它将提取名为operator=
的所有成员,并允许这样的代码:
A a;
B b;
b = a;
有点令人怀疑。
发布于 2019-02-06 02:48:27
为了使其正常工作,您需要将operator=
引入B
的范围:
class B : public A
{
public:
using A::operator=;
};
根据标准的class.copy.assign.class.copy.assign.分配/8
由于如果用户不声明,则为类隐式声明复制/移动赋值操作符,因此派生类的相应赋值运算符(16.5.3)总是隐藏基类副本/移动赋值运算符。
因此,因为B::operator=
是隐式声明的,所以它有隐藏的A::operator=
,如果您想要使用它,就需要将它带入作用域。
进一步引用标准over.ass/1
赋值操作符应由具有精确一个参数的非静态成员函数实现.,因为如果用户没有声明一个类,则为一个类隐式声明一个副本赋值操作符(15.8),因此派生类的副本赋值操作符总是隐藏基类赋值操作符。
重点是我的。
发布于 2019-02-06 02:49:20
正如其他现有答案所指出的,隐式生成的B
赋值运算符隐藏了在A
中定义的赋值运算符。对于基类中的任何非虚拟成员函数,这里唯一的特点是自动生成赋值操作符。
但首先要弄清楚你是否真的想这么做。假设您的类B
有需要以某种方式初始化的数据成员。使用来自A
的赋值是如何影响这些数据成员的?A
不知道其派生类数据成员的任何信息,它们将不受影响。查看以下场景,其中通过using指令使赋值操作符可用:
class B : public A {
public:
using A::operator=;
int m = 0; // Default-initialize data member to zero
};
B b;
b.m = 42;
b = 0; // Doesn't touch B::m... intended? A bug? Definitely weird.
因此,是的,这是可能的,但容易出错和危险,特别是当涉及到未来的修改子类。
https://stackoverflow.com/questions/54551695
复制相似问题