C++:是否有可能继承赋值运算符?
下面的C++代码不能编译: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 &)
不能重载。
是它根本不可能为一个类继承这个操作?
编辑:要清楚,我很困惑,为什么编译器是给Derived
默认Derived &operator = (const Derived &)
时,它已经继承Base<Derived>
T &operator (const T &) where [T = Derived]
。我可以理解为什么默认的拷贝赋值运算符通常会被创建,并覆盖任何继承赋值运算符,但在这种情况下Derived
被继承的操作与完全相同的签名的拷贝赋值运算符。有没有办法写BaseB
以便它的子类使用这个操作符?
可以继承基类的运营商和所有其他的方法,如果你没有在基类中声明它 - 默认赋值运算符将被编译器生成,如果你声明它 - 当你必须提供你自己的实现,所以你由于operator =而得到的错误未在您的BaseA类中定义,只声明。
没有,赋值运算符operator=
不被继承。 您的Derived类中没有默认的
Derived& operator=(const BaseA& a);
。
默认的赋值运算符,但是,创建:
Derived& operator=(const Derived& a);
,这从BaseA
调用赋值运算符。所以这不是继承赋值运算符的问题,而是通过派生类中的默认生成运算符调用它。 还有一些注意事项: 标准说(12.8):
赋值运算符应以非静态成员函数 正好有一个参数来实现。因为复制赋值运算符 运算符=被隐含了一类声明,如果没有声明 由用户(12.8),基类赋值运算符总是由派生类的复制赋值运算符隐藏 。衍生
然后赋值运算符调用你的基地
的非工会 类X的隐式定义的复制/移动赋值运算符执行按成员禁止复制/移动其子对象的分配。 首先指定X的直接基类,按其在基指定符列表中的 声明的顺序,然后按照它们的 声明的顺序分配X的非静态数据成员的即时 在类定义中。
赋值运算符是特殊成员函数之一。如果你自己没有提供,那么编译器会通过分配基础和成员来为你生成一个。如果任何基地没有分配操作员,则会生成一个分配操作员。
您的问题是您已经声明BaseA
的赋值运算符,但尚未提供定义。因为它被声明了,所以编译器不会为你生成一个,但它会尝试调用它来复制BaseA
子对象。链接器将无法找到定义。
请注意,对于转让的具体情况,继承基本实现并没有什么意义。如果使用了这种情况,只要有一个基地有一个分配操作员,对象的其余部分就不会是分配给。在大多数情况下,操作的语义将被打破。
我不确定这个错误与您的问题有何关系。你得到这个错误是因为你声明了这个函数,但从来没有定义它。 – 2013-04-24 03:56:53
由于您只声明了BaseA&operator =',因此编译器非常正确。将其更改为'BaseA&operator =(const BaseA&rhs)= default;'并且它会很愉快地编译。 – Yuushi 2013-04-24 03:58:19
链接器不应该关心它没有被定义,因为它永远不会被调用。它会被调用的唯一原因是编译器正在生成它自己的Derived :: operator =(const Derived&)函数。 – Shum 2013-04-24 04:01:06