繁体   English   中英

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

[英]Derived class inherit base class assignment operator?

在我看来,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中调用赋值运算符

我已经将基类operator =重写为派生类,所以如果派生类继承了基类operator =那么它应该被operator =覆盖(我已经在派生类中编写),现在Derived类默认operator =应该调用重写版本而不是基类operator =。

编译器为Derived生成默认赋值运算符(隐藏Base的运算符)。 但是,默认赋值运算符会调用类成员和基类的所有赋值运算符。

是的,它只是由Derived class =运算符隐藏Base class =运算符。

引用标准(12.8.24):

因为如果未由用户声明,则为类隐式声明复制/移动赋值运算符,则基类复制/移动赋值运算符始终由派生类的相应赋值运算符隐藏(13.5.3)。 使用声明(7.3.3)从基类引入一个赋值运算符,其参数类型可以是派生类的复制/移动赋值运算符的参数类型,不被视为此类运算符的显式声明,并且不抑制派生类运算符的隐式声明; using-declaration引入的运算符由派生类中隐式声明的运算符隐藏。

除非我误解了你想要实现的目标,否则你需要一个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和数据成员的分配不会自动发生。


另一种情况是,如果您真的希望从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;
}

如果你想实现多态行为,这意味着重写你的基本方法,你应该写这个:

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方法。

这就是所有人。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM