在我看来,派生类似乎没有继承基类赋值运算符
如果派生类继承基类赋值运算符,你能解释一下下面的例子吗
在下面的代码中,我覆盖了Derived中的基类运算符=,因此Derived类默认赋值运算符调用重载运算符=
#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;
}
它给出输出
调用基本中的分配运算符
我已经将基类运算符=重写到了派生类中,所以如果派生类继承了基类运算符=,那么它应该被运算符=覆盖(我在派生类中写的),现在派生类默认运算符=应该调用覆盖的版本,而不是从基类运算符=调用。
编译器为Derived生成默认赋值运算符(它隐藏Base的运算符)。但是,默认赋值运算符调用类成员和基类的所有赋值运算符。
=
运算符被派生类=
运算符隐藏。
除非我误解了您想要实现的目标,否则您需要Derived
类的赋值运算符,即以Derived
为输入的运算符:
class Derived : public Base
{
/* ... */
public:
Derived& operator=(const Derived &rhs)
{
cout << "Assignment operator in Derived"<< endl;
return *this;
}
};
代码中发生了什么(Bo Persson的回答和评论中已经解释过):在Derived
中,您实现了一个赋值运算符,它采用了Base
的实例;但在main()
中,您分配了一个Derived
的实例;编译器没有看到Derived
的赋值运算符(取Base
的运算符不计算在内),因此它生成了一个运算符,它调用Base::operator=()
,然后为Derived
的数据成员赋值。如果您如上所示定义了分配,则不会发生这种情况,并且会调用您的操作员;请注意,在这种情况下,CCD_ 13和数据成员的分配不会自动发生。
另一种情况是,如果您真的希望从Base
到Derived
进行赋值,例如将其与Base
的其他导数一起使用。然后,您定义的运算符将起作用,但为了将其应用于Derived
的实例,您需要将此实例强制转换为Base
:
Derived d1(10,20);
Derived d2(30,40);
d1 = static_cast<Base&>(d2);
不用说,您定义的运算符无法轻松访问特定于Derived
的rhs
的数据成员:例如,要使用rhs.y
,您需要将rhs
"向上转换"为Derived
:
Derived& Derived::operator=(const Base& rhs)
{
/* ... */
Derived* rhs_d = dynamic_cast<Derived*>(&rhs);
if( rhs_d )
this->y = rhs_d->y;
}
引用标准(12.8.24):
因为复制/移动赋值运算符是为类,如果用户未声明,则为基类复制/移动赋值运算符总是被的相应赋值运算符隐藏派生类(13.5.3)。引入基类中具有参数类型的赋值运算符可以是派生类的复制/移动赋值运算符不被视为此类操作员的明确声明,并且不抑制派生类运算符的隐式声明;using声明引入的运算符被派生类中隐式声明的运算符。
如果你想实现多功能行为,这意味着要覆盖你的基本方法,你应该写这样的:
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被取消引用的情况下调用赋值运算符,程序首先查找在派生类上调用的函数的overriden方法。如果找不到,则调用基类。现在,当我从d1调用赋值运算符时,程序将派生转换为基,程序不可能知道*d1代表派生对象,所以它调用基方法。
这就是所有的人。