2

次のコードでは、演算子のオーバーロードの例を示しています。

#include <iostream>
using namespace std;

template <typename T>
class A
{
public:
    A()   {};
    A( T &obj) {value = obj;};
    ~A() {};
    T value;
    template <typename E>
    A<T>& operator = (const A<E> &obj)
    {
        cout<<"equal operator"<<endl;
        if(this == &obj)
            return *this;

        value = obj.value;
        return *this;
    }

};



int main()
{
    int temp;
    temp = 3;
    A<int> myobjects(temp);
    cout<<myobjects.value<<endl;

    temp = 7;
    A<int> yourobjects(temp);
    yourobjects = myobjects;
    cout<<yourobjects.value<<endl;



    return 0;
}

ただし、このプログラムをデバッグすると、メインプログラムがequal演算子のオーバーロード関数を呼び出さないことがわかりました。ただし、次のように等号演算子を変更すると、次のようになります。

   A<T>& operator = (const A<T> &obj)
    {
        cout<<"equal operator"<<endl;
        if(this == &obj)
            return *this;

        value = obj.value;
        return *this;
    }

それが動作します。初期機能が機能しない理由はありますか?

4

2 に答える 2

7

代入演算子のテンプレート バージョンは、クラスのコンパイラ提供の非テンプレート コピー代入演算子の生成を抑制しません。コンパイラは、次のシグネチャを使用してコピー代入演算子を暗黙的に宣言および定義します。

A<T>& operator =(const A<T>&);

コピー代入のオーバーロード解決プロセスでは、コンパイラが提供するバージョンが優先されます (より特殊化されているため)。

代入演算子のテンプレート バージョンは、変換代入に対してのみ考慮されます。A<int>たとえば、ある時点でオブジェクトをオブジェクトに割り当てたい場合A<double>、代入演算子のテンプレート バージョンが使用されます。ただし、コンパイラで宣言されたバージョンの方が一致するため、演算子に割り当てるA<int>A<int>無視されます。

独自のバージョンのコピー代入を宣言するとき

A<T>& operator =(const A<T>&);

署名、コンパイラによって生成されたものを抑制します。あなたのバージョンが使用されます。

これは、独自のコピー代入演算子テンプレート変換代入演算子が必要な場合は、クラスに両方を明示的に実装する必要があることを意味します。

PS As '@Cheers and hth. - Alf' が正しく指摘したように、代入演算子のテンプレート バージョンは一般的なケースでは有効ではありません。ポインターthis&obj一般に、関連のないさまざまな型があります。関連のない異なる型のポインターを比較することはできません。

于 2012-07-09T17:12:21.103 に答える
4

T& operator=(T const&)独自のコピー代入演算子を定義しない場合、署名付きのコピー代入演算子はコンパイラによって自動的に宣言および定義されます。

代入演算子テンプレートはテンプレートであるため、コピー代入演算子ではありません (テンプレートはコピー代入演算子ではありません)。

あなたの例では、myobjectsandyourobjectsは両方とも typeA<int>です。operator=コンパイラが選択できるオーバーロードは 2 つあります。

  1. A<int>& operator=(A<int> const&)コンパイラによって暗黙的に提供される、または
  2. A<int>& operator=(A<int> const&)、テンプレートの特殊化。

これらの両方がまったく同じ署名を持っていることに気付くでしょう。オーバーロード解決の規則の 1 つは、他のすべての条件が同じであれば、非テンプレートがテンプレートよりも望ましいということです。暗黙的に宣言されたコピー代入演算子はテンプレートではなく、オーバーロードはテンプレートであるため、暗黙的に宣言されoperator=たものが選択されます。

暗黙的に宣言されたコピー代入演算子を抑制するには、独自に宣言して定義する必要があります。

A& operator=(A const&) { /* etc. */ }
于 2012-07-09T17:13:02.923 に答える