6

例子:

class C
{
  public:
    void operator =(int i) {}
};

class SubC : public C
{
};

以下给出编译错误:

SubC subC;
subC = 0;

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

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

4

4 回答 4

11

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

class C
{
  public:
    void operator =(int i) {}
};

class SubC : public C
{
  public:
    using C::operator=;
};
于 2012-04-09T00:31:02.387 回答
2

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

于 2012-04-09T00:27:52.763 回答
1

我还没有这样做,但是根据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 之前,您也可以“随心所欲地接受它”,尽管我自己没有尝试过。

于 2012-04-09T00:36:02.743 回答
0

除复制赋值运算符外,其他重载运算符都可以被继承。

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

如果 SubC 不提供复制赋值操作符,Compiler 会合成复制赋值操作,如下:

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

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

如果

SubC other;
SubC subC;

subC = other;

那么,这种情况下,编译就ok了。

于 2012-04-09T01:00:25.753 回答