为啥不能从派生类对象访问父类的赋值运算符

Posted

技术标签:

【中文标题】为啥不能从派生类对象访问父类的赋值运算符【英文标题】:Why assignment operators of parent class are not accessible from derived class objects为什么不能从派生类对象访问父类的赋值运算符 【发布时间】:2012-04-21 12:00:06 【问题描述】:

例子:

class C

  public:
    void operator =(int i) 
;

class SubC : public C

;

以下给出编译错误:

SubC subC;
subC = 0;

“'subC = 0'中的'operator='不匹配”

一些消息来源指出这是因为赋值运算符不是继承的。但这不只是因为SubC 的默认构造复制分配使它们黯然失色吗?

【问题讨论】:

【参考方案1】:

复制赋值运算符在派生类中自动生成。由于 C++ 的常规名称隐藏规则,这会导致基类的赋值运算符被隐藏。您可以通过“使用”指令取消隐藏基类中的名称。例如:

class C

  public:
    void operator =(int i) 
;

class SubC : public C

  public:
    using C::operator=;
;

【讨论】:

或者直接调用subC.C::operator =(0);【参考方案2】:

基类的复制赋值运算符没有派生类的复制赋值运算符所需的签名。它由派生类继承,但不构成其中的复制赋值运算符。所以即使赋值运算符是继承的,就像其他成员函数一样,它不提供复制赋值。

【讨论】:

这不是真的。比如operator+可以被继承。【参考方案3】:

我还没有这样做,但根据The Man Himself (Stroustrup),它是 C++11 的一个特性,可以使用构造函数来实现,但自 C++98 以来就一直在使用其他方法。

这是直接从链接中提取的:

人们有时会对普通范围规则这一事实感到困惑 适用于班级成员。特别是,基类的成员不是 与派生类的成员在同一范围内:

struct B 
    void f(double);
;

struct D : B 
    void f(int);
;

B b;   b.f(4.5);  // fine
D d;   d.f(4.5);  // surprise: calls f(int) with argument 4

在 C++98 中,我们可以从基类中“提升”一组重载函数 类转化为派生类:

struct B 
    void f(double);
;

struct D : B 
    using B::f;     // bring all f()s from B into scope
    void f(int);    // add a new f()
;

B b;   b.f(4.5);  // fine
D d;   d.f(4.5);  // fine: calls D::f(double) which is B::f(double)

所以你去。即使在 C++11 之前,您也可以“随心所欲地接受它”,尽管我自己还没有尝试过。

【讨论】:

【参考方案4】:

除了复制赋值操作符,其他重载操作符都可以继承。

我同意 SubC 的默认构造复制赋值掩盖了 C 的重载赋值运算符的观点。

如果 SubC 不提供复制赋值操作符,编译器将合成复制赋值操作, 如下:

class SubC : public C
 
public:
    SubC & operator=( const SubC & other );

那么 'SubC & operator=( const SubC & other )' 掩盖了 C 的赋值运算符, 导致编译错误。

如果

SubC other;
SubC subC;

subC = other;

那么,本例,编译ok。

【讨论】:

以上是关于为啥不能从派生类对象访问父类的赋值运算符的主要内容,如果未能解决你的问题,请参考以下文章

赋值兼容原则

C++的探索路12继承与派生之高级篇--派生类与赋值运算符及多重继承

检测基类对指向派生类的引用的分配

包含指向派生模板类的基类指针的类的赋值运算符和复制构造函数

派生自std :: exception的类的赋值运算符

继承