我正在尝试创建一些使用继承类的重载算术运算符,如下所示:
class Block {
public:
Block() {}
virtual double Value() {};
};
class Constant : public Block {
public:
Constant(double v) { value = v; }
virtual double Value() { return value; }
private:
double value;
};
class Add : public Block {
public:
Add(Block &a, Block &b) { value1 = &a; value2 = &b; }
virtual double Value() { return value1->Value() + value2->Value(); }
private:
Block *value1;
Block *value2;
};
Block operator + (Block &a, Block &b) {
return new Add(a, b);
}
int main() {
Constant a(5.0);
Constant b(6.0);
printf("%.3f", (a+b).Value());
}
Run Code Online (Sandbox Code Playgroud)
但我得到以下信息: error: conversion from 'Add*' to non-scalar type 'Block' requested
这是我第一次在 C++ 中使用 OOP,所以我的想法可能吗?
作为一般规则,运算符重载和继承不能很好地协同工作,因为在 C++ 中,运算符通常具有值语义。然而,有一个主要的例外,如果您的Add类的所有实例实际上都是您的operator+(临时)的返回值,那么您已经有效地实现了编译时表达式评估——一种非常重要的优化技术。(在现代 C++ 中,这通常是使用模板来完成的,而不是继承,但原理是一样的。)
因为运算符具有值语义,所以它们应该返回值,而不是指针。这意味着没有new。另一个不使用的原因new是任何newed 必须被显式删除,并且在大多数情况下,没有办法显式删除作为表达式一部分返回的指针。并且这样的指针也必须取消引用。
编辑:
我似乎忘记了一个重要的点:运算符声明的返回值必须是您返回的实际类型,因为您的返回表达式将被复制到该类型中。因此:
Add
operator+( Block const& lhs, Block const& rhs )
{
return Add( lhs, rhs );
}
Run Code Online (Sandbox Code Playgroud)
也请注意const。没有它,您就不能在临时对象上使用运算符;ega + b + c将是非法的(假设
a、b和c属于 类型Block,或者是从它派生的某种类型)。