1

次のような継承されたクラスを使用するオーバーロードされた算術演算子を作成しようとしています。

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の最初の経験ですが、私の考えは可能ですか?

4

2 に答える 2

5

一般に、演算子のオーバーロードと継承はうまく連携しません。これは、C++ では一般に演算子に値のセマンティクスがあるためです。ただし、大きな例外が 1 つあります。Addクラスのすべてのインスタンスが実際に (一時) の戻り値である場合は、operator+コンパイル時の式の評価 (非常に重要な最適化手法) を効果的に実装したことになります。(最近の C++ では、これは通常、継承ではなくテンプレートを使用して行われますが、原則は同じです。)

演算子には値のセマンティクスがあるため、ポインターではなく値を返す必要があります。これはいいえを意味しnewます。使用しないもう 1 つの理由は、ed されるnewものはnewすべて明示的に削除する必要があることです。ほとんどの場合、式の一部として返されるポインターを明示的に削除する方法はありません。また、そのようなポインターも逆参照する必要があります。

編集:

重要な点を忘れているようです。戻り式がこの型にコピーされるため、演算子の宣言された戻り値は、実際に返す型でなければなりません。したがって:

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

にも注意してくださいconst。これがないと、一時的に演算子を使用できません。たとえば、違法です( 、およびがタイプ、またはそれから派生したタイプであるa + b + cと仮定し ます)。abcBlock

于 2012-12-03T10:06:24.693 に答える
4

エラーの原因となるコードの特定の部分について言及していなかったので、それを指摘させてください。

Block operator + (Block &a, Block &b) {
    return new Add(a, b);
}

ここで何が起こっているのですか?さて、あなたはを返すことを約束してBlockいますが、実際にはを返しています。new Add(a, b)これはAdd*です。そして、それはコンパイラが不平を言っていることです。

これは、C++でのOOPの最初の経験です。

すべてのポインタとニュースと仮想から知ることができます。あなたのコードには深刻な生涯の問題があります。

C ++ OOPの知識を忘れて、C++に関する優れた入門書を読むことを強くお勧めします。

于 2012-12-03T09:49:16.527 に答える