提问人:Montaner 提问时间:2/6/2019 最后编辑:Soner GönülMontaner 更新时间:2/6/2019 访问量:2100
赋值运算符在派生类中不可用
Assignment operator not available in derived class
问:
基类中的赋值运算符似乎在派生类中不可用。给定以下代码:
#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”)
发生了什么事情?
答:
为了让它工作,你需要将 the 引入 的范围:operator=
B
class B : public A
{
public:
using A::operator=;
};
根据标准 [class.copy.assign/8]:
由于复制/移动赋值运算符是隐式声明的 类(如果未由用户声明),则为基类复制/移动赋值 运算符始终被 派生类 (16.5.3)。
因此,由于 已被隐式声明,因此它已隐藏 ,如果您想使用它,则需要将其纳入范围。B::operator=
A::operator=
标准 [over.ass/1] 的进一步引用
赋值运算符应由非静态成员实现 函数,只有一个参数。因为复制分配 运算符 operator= 如果未声明,则为类隐式声明 对于用户 (15.8),基类赋值运算符始终处于隐藏状态 由派生类的复制赋值运算符。
重点是我的。
问题在于编译器将为类添加一个隐式赋值运算符,声明为B
B& operator=(const B&);
这个运算符会隐藏运算符,所以编译器不会知道它。A
解决方案是告诉编译器也使用带有关键字的运算符 from:A
using
class B : public A
{
public:
using A::operator=;
};
评论
B
A::operator=
正如其他现有答案所指出的,隐式生成的赋值运算符 隐藏了 中定义的赋值运算符。对于基类中的任何非虚拟成员函数都是如此,这里唯一的专长是自动生成的赋值运算符。B
A
但首先要弄清楚你是否真的想这样做。想象一下,您的类具有需要以某种方式初始化的数据成员。使用赋值 from 如何影响这些数据成员? 不知道其派生的类数据成员的任何内容,它们将保持不变。请看以下方案,其中赋值运算符已通过 using 指令可用:B
A
A
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.
所以是的,这是可能的,但容易出错且危险,尤其是在涉及子类的未来修改时。
评论
operator=
每个类至少有一个隐式定义的赋值运算符,而我们自己却不提供赋值运算符。
当派生类中的成员函数与基类中的成员同名时,它会隐藏该名称的所有基类定义。
您可以使用 using 声明,但请注意,它将拉取所有命名的成员并允许如下所示的代码:operator=
A a;
B b;
b = a;
这有点可疑。
评论