2011-01-30 2 views
0

まずはあなたの手がかりに感謝します。C++:2つの異なるクラスで同じ演算子をオーバーロードしているときの問題

課題を完了しようとする際に特に問題があります。私は、名前空間、ヘッダファイル、およびこれらすべてのものに間違ったものがあることは間違いないと確信していますが、実際に何がうまくいかないかはわかりません。

ポイントはこれです:2つの異なるクラス(それぞれCarCarShopとしましょう)が必要です。これらのクラスのそれぞれは、演算子+をオーバーロードする必要があります。

  • Car - >Car &operator+(const Car &c)(2台の車を "追加" する必要があり)
  • CarShop - >CarShop &operator+(const Car &c)(既存CarShopに車を "追加" する必要があり)

ファイルCarShop.hで、私のようにする必要があり#include "car.h"、これは異なる "car"オブジェクトで多く動作するためです。さらに、私の主なテストクラスでは、main.cppと言うと、#include "car.h"#include "carshop.h"も必要です。

エラーメッセージが表示されます。 Visual Studio(IDEとして使用しています)では、「LNK1169 & LNK2005」というエラーが表示され、「1つ以上のシンボルが同時に定義されています」というエラーが表示されます。

誰でも私を助けてくれますか? 2人のオーバーロードされたオペレータの間のこの衝突を避けるために、私は何をすべきですか?

PS。両方とも(2つのオーバーロードされた演算子)、(.hファイル内の)それぞれのクラスのフレンド関数として宣言され、それぞれの.cppファイルで実装されます。

+4

(1)コードをご記入ください。エラーを引き起こすコードを見ることなく、エラーを診断することは困難です。 (2)「2台の車を追加する」とはどういう意味ですか? (3) 'operator +'は組み込みの '+'の振る舞いに従うならば、参照ではなく値で返さなければなりません:オペランドのいずれかを変更してはならず、新しいオブジェクトを返すべきです。オペランドの1つを変更する場合は、 'operator + ='の使用を検討する必要があります。 –

+1

.hファイルに '#define'ガードがありますか? – Richard

+1

あなたの質問には矛盾があります。あなたが表示する関数宣言は、メンバー関数の演算子オーバーロードですが、オーバーロードが "friend関数として宣言されている"と言います。どちらですか? –

答えて

2

他の人が指摘したように、あなたはただの友達としてこれらを宣言することはできません。

Car &operator+(const Car &c); 
CarShop &operator+(const Car &c); 

あなたはそれをコンパイルしてリンクすることができたとしても、それだけで動作しません。また、同じシグネチャ(戻り値の型はシグネチャに含まれていないため)をリンクすることはできません。あなたは2つの選択肢があります:非会員の友人を持っているか、メンバー機能を持っている(友人宣言は必要ありません)。ジェームズが指摘したように、これらの演算子は参照を返すべきではない、ということ

Car operator+(const Car &c1, const Car &c2); 
CarShop operator+(const CarShop &cs, const Car &c); 

は注:非会員の友人をしたい場合は、両方のオペランドを指定して、このようにそれらを宣言している必要があります。彼らは定義によって新しいインスタンスを返します。

ただし、フレンド演算子は、最初のパラメータの型がコントロールの下にあるクラスと異なる場合にのみ必要です。たとえば、最初のパラメータの型がstd :: stringまたはintの場合、friend演算子を宣言する必要があります。ただし、これらはクラスであるため、演算子をメンバーとして宣言することをお勧めします。

Car operator+(const Car &c2); // this is declared inside the Car class 
CarShop operator+(const Car &c); // this is declared inside the CarShop class 

ここでメンバーはメンバーである必要はありません。カーのプライベートメンバーにアクセスしたい場合は、厳密に言えば、CarShop::operator+(const Car&)をCarクラスの友人として宣言したい場合があります。しかし、Car::operator+(const Car&)の場合は絶対に必要ありません。

1

あなたはCarタイプを宣言しています。 main.cppにはcar.hcarshop.hが含まれ、carshop.hにはすでにcar.hが含まれています。インクルードガードがなければ、リンカのエラーが発生します。

あなたは二つの可能性があります:

anyfile.h:オフのチャンスあなたに

#pragma once 

/* ... the rest of your code ... */ 

  • をこのような警備員を含め、あなたのmain.cpp
  • 使用から#include "Car.h"を削除コンパイラは0をサポートしていません

    myheader.h

    #ifndef MYHEADER_H 
    #define MYHEADER_H 
    
    /* ... your code here ... */ 
    
    #endif 
    
+1

エラーメッセージはリンクエラーを示しているようですので、おそらく既にこれを行っています。 – fbafelipe

1

短い答えを:あなたは常にあなたのヘッダーに少し面倒、マクロガードかかわらず、標準を使用することができますディレクティブは、友人として、これらの演算子を宣言しないでください。

長い答え: 関数がfriendとして宣言されている場合、関数が宣言されているクラスに属していないことを意味します(実際に関数を宣言していない)。関数(メンバー関数ではなくC関数になります)は、そのクラスの友人であり、プライベートデータにアクセスできます。

オペレータ< <(std :: ostream)のコードを使用しているコードを見たのでおそらく友人を使用していますが、std :: ostreamのメンバー関数である必要があるためメンバーになることはできません。友人を削除すると、 "this"が最初の演算子になります。

関連する問題