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.