我正在尝试编写一个带有一些纯虚拟二元运算符的抽象类,它应该由派生类实现,以实现运算符多态性。这是一个简化的例子:
class Base {
public:
virtual const Base& operator+ (const Base&) const = 0;
};
class Derived : public Base {
public:
const Derived& operator+ (const Derived&) const;
};
const Derived& Derived::operator+ (const Derived& rvalue) const {
return Derived();
}
现在运算符的作用并不重要,重要的部分是它返回的内容:它返回一个临时的Derived对象或对它的引用。现在,如果我尝试编译,我会得到这个:
test.cpp: In member function ‘virtual const Derived& Derived::operator+(const Derived&) const’:
test.cpp:12:17: error: cannot allocate an object of abstract type ‘Derived’
test.cpp:6:7: note: because the following virtual functions are pure within ‘Derived’:
test.cpp:3:22: note: virtual const Base& Base::operator+(const Base&) const
怎么了?是不是操作符+(Base中唯一的纯虚函数)被覆盖?为什么Derived也应该是抽象的?
答案 0 :(得分:6)
尽管Derived
中的返回类型可以与基本类型共同变化,但您不能对参数类型执行相同的操作。即,重写函数应如下所示:
class Derived : public Base
{
public:
const Derived& operator+ (const Base&) const;
};
答案 1 :(得分:2)
使用普通的抽象类无法以干净的方式进行这种重载。首先:您应该声明+为非成员Overload operators as member function or non-member (friend) function?。
如果您确实需要此功能,那么您可以获得的最好的方法是从模板化界面继承:
template<typename T>
class AddEnabled {
public:
friend T operator+ (T const& left, T const& right) {
return left+=right;
}
};
现在你写了
class Foo: public AddEnabled<Foo>{
Foo():mVal(0){
}
Foo& operator+=(Foo const& foo){
mVal+=foo.mVal;
}
private:
int mVal;
}
如果你注释掉Foo& operator+=(Foo const& foo){
,你会收到编译错误,说明运算符没有实现。如果您想了解更多相关原则,请查看http://en.wikipedia.org/wiki/Barton%E2%80%93Nackman_trick和http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern