我正在尝试创建一些使用这样的继承类的重载算术运算符:
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());
}
但我得到了以下信息:error: conversion from 'Add*' to non-scalar type 'Block' requested
这是我第一次使用C ++进行OOP体验,所以我的想法甚至可能吗?
答案 0 :(得分:4)
由于您未提及导致错误的代码的特定部分,因此请指出:
Block operator + (Block &a, Block &b) {
return new Add(a, b);
}
这到底发生了什么?好吧,您承诺返回Block
,但实际上您正在返回new Add(a, b)
,这是一个Add*
。这就是编译器所抱怨的。
这是我在C ++中使用OOP的第一次经历
可以从所有指针,新闻和虚拟中分辨出来。您的代码存在严重的终身问题。
我强烈建议您忘记您的C ++ OOP知识并阅读a good introductory book on C++。
答案 1 :(得分:4)
作为一般规则,运算符重载和继承不会
一起工作很好,因为在C ++中,运营商通常都有价值
语义。然而,有一个主要的例外,如果全部的话
您的Add
类的实例实际上是返回值
你的operator+
(临时),你有效
实现编译时表达式评估 - 非常
重要的优化技术。 (在现代C ++中,这是
通常使用模板完成,而不是继承,但是
原则是一样的。)
因为运算符具有值语义,所以它们应该返回
值,而不是指针。这意味着没有new
。另一个原因不是
使用new
是new
ed的任何内容都必须明确
删除,在大多数情况下,没有办法明确删除
作为表达式的一部分返回的指针。而这样的指针
也必须被解除引用。
编辑:
我似乎忘记了一个重点:操作符的声明返回值必须是您要返回的实际类型,因为返回表达式将被复制到此类型中。因此:
Add
operator+( Block const& lhs, Block const& rhs )
{
return Add( lhs, rhs );
}
另请注意const
。没有它,您无法使用运算符
临时的;例如a + b + c
将是非法的(假设
a
,b
和c
属于Block
类型,或某种类型派生
从它)。