web-dev-qa-db-ja.com

「。」をオーバーロードできないのはなぜですかC ++の演算子?

をオーバーロードできると非常に便利です。 C++の演算子。オブジェクトへの参照を返します。

オーバーロードできますoperator->およびoperator* だがしかし operator.

これには技術的な理由がありますか?

76
Ferruccio

Bjarne Stroustrupからのこの引用 を参照してください:

演算子。 (ドット)は、原則として->で使用したのと同じ手法を使用してオーバーロードできます。ただし、そのようにすると、操作がオブジェクトのオーバーロードを意図しているかどうかについての質問につながる可能性があります。またはによって参照されるオブジェクト。例えば:

class Y {
public:
    void f();
    // ...
};

class X {    // assume that you can overload .
    Y* p;
    Y& operator.() { return *p; }
    void f();
    // ...
};

void g(X& x)
{
    x.f();    // X::f or Y::f or error?
}

この問題はいくつかの方法で解決できます。標準化の時点では、どちらの方法が最適かは明らかではありませんでした。詳細については、「 C++の設計と進化 」を参照してください。

62
Anton Gogolev

Stroustrup氏は、C++は拡張可能であるべきであるが、可変言語であってはならないと述べた。

ドット(属性アクセス)演算子は、オーバーロードを許可するには言語のコアに近すぎると見なされていました。

C++の設計と進化 、242ページのセクション11.5.2スマートリファレンスを参照してください。

演算子->のオーバーロードを許可することを決定したとき、演算子.も同様にオーバーロードできるかどうかを自然に考えました。

当時、私は次の引数が決定的だと考えました:objがクラスオブジェクトの場合、obj.mはそのオブジェクトのクラスのすべてのメンバーmに対して意味を持ちます。ビルトイン操作を再定義することにより、言語を可変にしないようにします(ただし、=が緊急に必要な場合、および単項の&の場合、この規則に違反します)。

クラスX.のオーバーロードを許可した場合、通常の方法ではXのメンバーにアクセスできません。ポインタと->を使用する必要がありますが、->&も再定義されている可能性があります。可変ではなく拡張可能な言語が必要でした。

これらの議論は重要ですが、決定的なものではありません。特に、1990年にJim Adcockは、演算子.のように、演算子->exactlyのオーバーロードを許可することを提案しました。

この引用の「I」はBjarne Stroustrupです。あなたはそれよりも権威を持つことはできません。

C++を本当に理解したい場合(「なぜこのようになっているのか」など)、この本を絶対にお読みください。

51
ddaa

Stroustrup この質問に対する答えがあります

演算子。 (ドット)は、原則として->で使用したのと同じ手法を使用してオーバーロードできます。ただし、そのようにすると、操作がオブジェクトのオーバーロードを意図しているかどうかについての質問につながる可能性があります。またはによって参照されるオブジェクト。例えば:

class Y {
public:
    void f();
    // ...
};
class X {   // assume that you can overload .
    Y* p;
    Y& operator.() { return *p; }
    void f();
    // ...
};
void g(X& x)
{
    x.f();  // X::f or Y::f or error?
}

この問題はいくつかの方法で解決できます。標準化の時点では、どちらの方法が最適かは明らかではありませんでした。詳細については、 D&E を参照してください。

29
mfazekas

演算子関数呼び出しの内部メカニズムを理解するのは非常に簡単です。クラス複合体は、実数部に2つのメンバーr、虚数部にiを持つことができます。 Complex C1(10,20)、C2(10,2) //クラス内にすでに2つの引数コンストラクターがあると仮定します。ここで、ステートメントとしてC1 + C2を記述した場合、コンパイラーは複素数の+演算子のオーバーロードバージョンを見つけようとします。ここで、私は+演算子をオーバーロードすると仮定します。したがって、C1 + C2は内部的にc1.operator +(c2)に変換されます。オペレーター。したがって、次の呼び出しを考えてくださいC1.disp() //複雑なオブジェクトのコンテンツを表示する内部表現として表現しようC1.operator。(------)、完全に乱雑なものが作成されました。それが、「。」をオーバーロードできない理由です。オペレーター

1
Sourav Ghosh