重载C ++算术运算符

时间:2012-12-03 09:46:45

标签: c++ oop

我正在尝试创建一些使用这样的继承类的重载算术运算符:

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体验,所以我的想法甚至可能吗?

2 个答案:

答案 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。另一个原因不是 使用newnew ed的任何内容都必须明确 删除,在大多数情况下,没有办法明确删除 作为表达式的一部分返回的指针。而这样的指针 也必须被解除引用。

编辑:

我似乎忘记了一个重点:操作符的声明返回值必须是您要返回的实际类型,因为返回表达式将被复制到此类型中。因此:

Add
operator+( Block const& lhs, Block const& rhs )
{
    return Add( lhs, rhs );
}

另请注意const。没有它,您无法使用运算符 临时的;例如a + b + c将是非法的(假设 abc属于Block类型,或某种类型派生 从它)。