0

以下 C++ 代码无法编译:

class BaseA {
protected:
    BaseA &operator = (const BaseA &rhs);
};

template<typename T>
class BaseB {
public:
    T &operator = (const T &rhs) {
        return *static_cast<T *>(this);
    };
};

class Derived :
    public BaseA,
    public BaseB<Derived> {
};

int main() {
    Derived foo;
    Derived bar;
    foo = bar;
    return 0;
};

当我尝试编译它时,我收到一个BaseA &BaseA::operator = (const BaseA &)未定义的投诉。在 stackoverflow 上还有其他几个类似的问题,但是它们似乎都与编译器自动生成Derived &Derived::operator = (const Derived &)调用BaseA::operator = (const BaseA&). 在这种情况下,虽然Derived应该已经从BaseB<Derived>. 如果我按照另一个问题的建议并添加using BaseB<Derived>::operator =;Derived编译器抱怨Derived &operator = (const Derived &)不能重载。

一个类根本不可能继承这个运算符吗?

编辑:要清楚,我很困惑为什么编译DerivedDerived &operator = (const Derived &)已经T &operator (const T &) where [T = Derived]Base<Derived>. 我可以理解为什么通常会创建默认的复制赋值运算符并覆盖任何继承的赋值运算符,但在这种情况下Derived,它继承了一个与其复制赋值运算符具有完全相同签名的运算符。有没有办法BaseB让它的子类使用这个运算符?

4

3 回答 3

5

不,赋值运算符operator=不是继承的。你没有默认值

Derived& operator=(const BaseA& a);

在你的派生类中。

但是,会创建一个默认赋值运算符:

Derived& operator=(const Derived& a);

这从 调用赋值运算符BaseA。所以这不是继承赋值运算符的问题,而是通过派生类中默认生成的运算符调用它。还有一些注意事项:标准说(12.8):

赋值运算符应该由一个只有一个参数的非静态成员函数来实现。因为复制赋值运算符 operator= 如果未由用户声明,则为类隐式声明(12.8),基类赋值运算符始终被派生类的复制赋值运算符隐藏。

然后派生的赋值运算符调用你的基础

非联合类 X 的隐式定义的复制/移动赋值运算符执行其子对象的成员复制/移动赋值。首先分配 X 的直接基类,按照它们在基说明符列表中的声明顺序,然后按照它们在类定义中声明的顺序分配 X 的直接非静态数据成员.

于 2013-04-24T03:58:27.847 回答
1

赋值运算符是特殊的成员函数之一。如果您自己不提供一个,编译器将通过分配基数和成员来为您生成一个。如果任何基础没有赋值运算符,则会生成一个。

您的问题是您已经为 声明了赋值运算符BaseA,但没有提供定义。因为它是声明的,编译器不会为你生成一个,但它会尝试调用它来复制BaseA子对象。然后链接器将无法找到定义。

请注意,对于分配的特定情况,继承基本实现并没有真正意义。如果使用它,一旦一个基具有赋值运算符,对象的其余部分就不会被赋值。在大多数情况下,操作的语义会被破坏。

于 2013-04-24T04:12:28.343 回答
0

您可以继承基类运算符和所有其他方法,如果您没有在基类中声明它 - 默认赋值运算符将由编译器生成,如果您声明它 - 当您必须提供自己的实现时,您会收到错误由于 operator= 未在您的 BaseA 类中定义,仅声明。

于 2013-04-24T03:57:27.573 回答