C++ 派生类继承基类赋值运算符?
在我看来,派生类不继承基类赋值运算符C++ 派生类继承基类赋值运算符?,c++,inheritance,assignment-operator,C++,Inheritance,Assignment Operator,在我看来,派生类不继承基类赋值运算符 如果派生类继承基类赋值运算符,请解释以下示例 在下面的代码中,我将重写派生中的基类运算符=以便派生类默认赋值运算符调用重载运算符= #include <iostream> using namespace std; class Base { public: Base(int lx = 0):x(lx) { } virtual Base& operator=(
如果派生类继承基类赋值运算符,请解释以下示例 在下面的代码中,我将重写派生中的基类运算符=以便派生类默认赋值运算符调用重载运算符=
#include <iostream>
using namespace std;
class Base
{
public:
Base(int lx = 0):x(lx)
{
}
virtual Base& operator=( const Base &rhs)
{
cout << "calling Assignment operator in Base" << endl;
return *this;
}
private:
int x;
};
class Derived : public Base
{
public:
Derived(int lx, int ly): Base(lx),y(ly)
{
}
Base& operator=(const Base &rhs)
{
cout << "Assignment operator in Derived"<< endl;
return *this;
}
private:
int y;
};
int main()
{
Derived d1(10,20);
Derived d2(30,40);
d1 = d2;
}
#包括
使用名称空间std;
阶级基础
{
公众:
基准(intlx=0):x(lx)
{
}
虚拟基和运算符=(常量基和rhs)
{
cout是的,只是基类=
运算符被派生类=
运算符隐藏。编译器为派生类生成一个默认赋值运算符(它隐藏了基类的运算符)。但是,默认赋值运算符调用类的成员和基类的所有赋值运算符。除非我误解了您想要实现的目标,否则您需要类派生
的赋值运算符,即将派生
作为输入的赋值运算符:
class Derived : public Base
{
/* ... */
public:
Derived& operator=(const Derived &rhs)
{
cout << "Assignment operator in Derived"<< endl;
return *this;
}
};
不用说,您定义的运算符无法轻松访问特定于派生的rhs
的数据成员:例如,要使用rhs.y
,您需要将rhs
向上转换到派生:
Derived& Derived::operator=(const Base& rhs)
{
/* ... */
Derived* rhs_d = dynamic_cast<Derived*>(&rhs);
if( rhs_d )
this->y = rhs_d->y;
}
Derived&Derived::operator=(常量Base&rhs)
{
/* ... */
派生*rhs\U d=动态演员阵容(&rhs);
若有(右舵)
这->y=rhs\U d->y;
}
如果您想要实现多病态行为,这意味着要覆盖基本方法,您应该编写以下代码:
int main (){
Derived * d1 = new Derived (10,20);
Derived * d2 = new Derived (30,40);
Base * b1 = d1 ;
Base * b2 = d2 ;
*b1 = *b2 ;
*d1 = *d2 ;
}
这将产生以下输出:
$> Assignment operator in Derived.
$> calling Assignment operator in Base.
我在这里做的是使用C++动态的隐式铸造。我不完全确定这是不是这样工作,但是为了说明我的观点,我认为这是有用的。
在b1和b2被取消引用的情况下调用赋值运算符,程序首先查找在派生类上调用的函数的重写方法,如果找不到任何方法,则调用基类方法。现在,当我从d1调用赋值运算符时,程序将派生的方法强制转换为基类,程序无法知道*d1是否存在s表示派生对象,因此它调用基方法
这就是所有人。引用标准(12.8.24):
因为复制/移动赋值运算符是为
类如果用户未声明,则为基类复制/移动分配
运算符始终由的相应赋值运算符隐藏
派生类(13.5.3)。引入
来自基类的赋值运算符,其参数类型为
可以是派生类的复制/移动赋值运算符
不被视为此类运算符的明确声明,并且
不抑制派生类运算符的隐式声明;
using声明引入的运算符由
派生类中隐式声明的运算符
我可以将基类运算符=重写为派生类吗?@Amit:您不能重写它。根据定义,非虚函数不能被重写,尽管它可以隐藏。也许您想在Derived
中重载复制赋值运算符。如果是这样,那么正确的签名是Derived&operator=(const-Derived&rhs)
。这是编译器在执行d1=d2
时查找的签名。由于找不到它,它将合成默认的复制赋值运算符,并调用Base::operator=(const Base&)
@Steve:我已经更改了代码,现在我的基类Operator=是虚拟的。@Amit:这几乎肯定是个错误,虚拟赋值运算符不能很好地工作。您不希望只允许任何旧的基
对象被赋值给派生的对象,因为基不提供赋值给对象e> y
。我想知道:这个解释对我来说似乎不正确,声称我们得到了预期的行为,但没有解释观察到的行为。当然,除非我完全误读了它。为什么要向上投票?代码缺少理解它所需的类定义,输出行错误(大概,即通过推理和完成代码),忽略了关键点:这里所示的是“多模”的完全相反的“隐式使用C++动态铸造”。如果这是多态性的,那么*b1=*b2
赋值也会报告它正在调用派生的操作符=
,但是它不会(一旦我们纠正了消息的错误方向)。(尝试使Base.operator=
成为虚拟的方法会打开一个不同的世界)
$> Assignment operator in Derived.
$> calling Assignment operator in Base.