派生类继承基类赋值运算符

Derived class inherit base class assignment operator?

本文关键字:赋值运算符 基类 继承 派生      更新时间:2023-10-16

在我看来,派生类似乎没有继承基类赋值运算符
如果派生类继承基类赋值运算符,你能解释一下下面的例子吗

在下面的代码中,我覆盖了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和数据成员的分配不会自动发生。


另一种情况是,如果您真的希望从BaseDerived进行赋值,例如将其与Base的其他导数一起使用。然后,您定义的运算符将起作用,但为了将其应用于Derived的实例,您需要将此实例强制转换为Base:

Derived d1(10,20);  
Derived d2(30,40);  
d1 = static_cast<Base&>(d2);

不用说,您定义的运算符无法轻松访问特定于Derivedrhs的数据成员:例如,要使用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代表派生对象,所以它调用基方法。

这就是所有的人。