C ++での基本的な演算子のオーバーロード構文

私が尋ねようとしていることの質問を形成するのに苦労しているので、私にあなたに例を挙げてみましょう:

私たちがベクトルクラスVec3を定義した3dシステムで作業しているとします。我々は明らかなresonsのためにいくつかの算術演算子をオーバーロードする。これらの中で、*演算子をオーバーロードして、2つのベクトルの内積を返します。これでコードは次のようになります。

class Vec3{
private:
    float x, y, z;
public:
    float operator*(const Vec3&) const; //dot product
.
.
.

ここでは、*演算子を何か(例えばfloat)で使用して、ベクトルを拡大/縮小できるようにしたいとします。これは次のように宣言することで可能です:

    Vec3 operator*(const float) const;
    friend Vec3 operator*(const float, const Vec3&);

これにより、2つのオーバーロードが発生し、単なる1つの方法で実行する方法があるかどうかが疑問です。つまり、上記の2つの行の代わりにこれを宣言します。

    friend Vec3 operator*(const Vec3&, const Vec3&);

Vec3 ctorのデフォルト値を追加してfloatからの変換を処理します。

この最後の例は、

    Vec3 someVec3 = 1.0 * otherVec3; //through friend Vec3 operator*(const float, const Vec3&)

しかし、これのためではない:

    Vec3 someVec3 = otherVec3 * 1.0;

コンパイラは2つのうちどちらを使用するかを知りませんでした。

    friend Vec3 operator*(const float, const Vec3&); //the one we want to use
or
    float operator*(const Vec3&) const; //the one for the dot product

助言がありますか?

ありがとうございました!

7
私が別のやり方をする唯一のことは、メンバではなくスカラ乗算friend関数の両方のバージョンを作成することです。そのため、コードは操作自体と同じ対称性を持ちます。
追加された 著者 Ben Voigt,
2つのオーバーロードで何が問題になっていますか?あなたが指摘しているように、それを単純化しようとすると、むしろ厄介なあいまいさが生まれます...
追加された 著者 Platinum Azure,
浮動小数点数を渡すだけのベクトルを構築することは非効率的です。これは実行時の非効率性ですが、余分なオーバーロードされた関数がインライン展開される可能性があります。
追加された 著者 QuentinUK,

3 答え

この場合、最初に、オペレータのオーバーロードに対してアドバイスします。なぜなら、 * がドットまたはクロス積を表すかどうかをユーザーがどのように知っているかです(両方とも、期待されるクライアントの使用に応じて妥当な意味です)。私は実際に operator * をサポートせず、 dot cross scale その後、複数の過負荷について心配する必要はなく、ユーザーには何が得られるのかは明らかです。

しかし、演算子を使いたい場合は、2つのオーバーロードがあることに間違いはありません。スケーリングを行うためのダミーの Vec3 を作成することは、意味的に間違っているだけでなく、少量の不必要なオーバーヘッドを追加することにもなります。

5
追加された

Boost.Operators can do most of the boiler-plate work for you. E.g.:

class Vec3 
  : boost::multipliable2
{
public:
  //... 

   Vec3 operator*=(float);
  //Vec3 operator*(Vec3, const float&) and
  //Vec3 operator*(const float&, Vec3) auto-generated
  //by multipliable. 
};
2
追加された

いくつかのオーバーロードには何も問題はありません。特に、互いに簡単に実装できるのであれば、

Vec3 operator*(const float scale, const Vec3& vec)
{ return vec * scale; }

それを簡単にするのは難しいです!

1
追加された