在我看来,Derived类不会继承基类Assignment操作符
如果Derived类继承了Base类赋值运算符,请解释下面的例子
在下面的代码中,我在Derived中覆盖了基类operator =,因此Derived类的默认赋值运算符调用了重载的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;
}
它给出输出
在Base
中调用Assignment运算符
我已经将基类operator =重写为派生类,所以如果派生类继承了基类operator =那么它应该被operator =覆盖(我已经在派生类中编写),现在Derived类默认运算符=应调用重写版本,而不是从基类operator =。
答案 0 :(得分:4)
编译器为Derived生成默认赋值运算符(隐藏Base的运算符)。但是,默认赋值运算符会调用类成员和基类的所有赋值运算符。
答案 1 :(得分:3)
是的,它只是Derived类=
运算符隐藏了基类=
运算符。
答案 2 :(得分:1)
除非我误解了你想要达到的目标,否则你需要一个类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
'数据成员。如果您如上所示定义了分配,则不会发生这种情况,并且会调用您的运营商;请注意,在这种情况下,Base
和数据成员的分配不会自动发生。
另一种情况是,如果您真的希望从Base
到Derived
进行分配,例如与Base
的其他衍生物一起使用。然后,您定义的运算符将起作用,但为了将其应用于Derived
的实例,您需要将此实例强制转换为Base
:
Derived d1(10,20);
Derived d2(30,40);
d1 = static_cast<Base&>(d2);
毋庸置疑,您定义的运营商无法轻松访问rhs
特定于Derived
的数据成员:例如要使用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;
}
答案 3 :(得分:1)
引自标准(12.8.24):
因为隐式声明了a的复制/移动赋值运算符 如果用户未声明类,则为基类复制/移动赋值 运算符始终由相应的赋值运算符隐藏 派生类(13.5.3)。引入的使用声明(7.3.3) 从基类中赋值运算符,其参数类型为 可以是派生类的复制/移动赋值运算符 不被视为此类运营商的明确声明,并且确实如此 不抑制派生类运算符的隐式声明; 由using声明引入的运算符被隐藏 在派生类中隐式声明的运算符。
答案 4 :(得分:-1)
如果你想实现多态行为,这意味着重写你的基本方法,你应该写这个:
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调用赋值运算符时,程序转换为派生到base并且程序无法知道* d1代表Derived对象,因此它调用base方法。
这就是所有人。