2013-04-24 88 views
0

下面的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以便它的子类使用这个操作符?

+0

我不确定这个错误与您的问题有何关系。你得到这个错误是因为你声明了这个函数,但从来没有定义它。 – 2013-04-24 03:56:53

+0

由于您只声明了BaseA&operator =',因此编译器非常正确。将其更改为'BaseA&operator =(const BaseA&rhs)= default;'并且它会很愉快地编译。 – Yuushi 2013-04-24 03:58:19

+0

链接器不应该关心它没有被定义,因为它永远不会被调用。它会被调用的唯一原因是编译器正在生成它自己的Derived :: operator =(const Derived&)函数。 – Shum 2013-04-24 04:01:06

回答

0

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

5

没有,赋值运算符operator=不被继承。 您的Derived类中没有默认的

Derived& operator=(const BaseA& a); 

默认的赋值运算符,但是,创建:

Derived& operator=(const Derived& a); 

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

赋值运算符应以非静态成员函数 正好有一个参数来实现。因为复制赋值运算符 运算符=被隐含了一类声明,如果没有声明 由用户(12.8),基类赋值运算符总是由派生类的复制赋值运算符隐藏 。衍生

然后赋值运算符调用你的基地

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

1

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

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

请注意,对于转让的具体情况,继承基本实现并没有什么意义。如果使用了这种情况,只要有一个基地有一个分配操作员,对象的其余部分就不会是分配给。在大多数情况下,操作的语义将被打破。