3

私は次のコードを書きました:

#include <iostream>
using namespace std;

template <class T>
class AA
{
  T a;

public:
AA()
{
 a = 7;
}

friend void print(const AA<T> & z);
};

template <class T>
void print(const AA<T> & z)
{
    cout<<"Print: "<<z.a<<endl;
}

void main()
{
AA<int> a;
print<int>(a);
}

そして、次のエラーが発生します。

error C2248: 'AA<T>::a' : cannot access private member declared in class 'AA<T>'
1>        with
1>        [
1>            T=int
1>        ]
1>        c:\users\narek\documents\visual studio 2008\projects\aaa\aaa\a.cpp(7) : see declaration of 'AA<T>::a'
1>        with
1>        [
1>            T=int
1>        ]
1>        c:\users\narek\documents\visual studio 2008\projects\aaa\aaa\a.cpp(30) : see reference to function template instantiation 'void print<int>(const AA<T> &)' being compiled
1>        with
1>        [
1>            T=int
1>        ]

どうしたの?

PS私はVisualStudio2008を使用しています。

4

2 に答える 2

3

問題は、あなたが次のようなことをするときです

template<class T>
class AA {friend void print(const AA<T>&);};

AAこのようにインスタンス化します

AA<int> a;

友達宣言は次のようにインスタンス化されます

friend void print(const AA<int>&);

これは非テンプレート関数です!これは、コンパイラがフレンド宣言を関数と一致させないことを意味しますprint

解決策は基本的に、print前に宣言AAし、フレンド宣言がテンプレート関数について話していることをコンパイラに明示的に伝えることです。このような:

#include <iostream>
using namespace std;

//forward declare AA because print needs it
template<class T>
class AA;

//declare print before AA to make the friend declaration
//match with this function
template<class T>
void print(const AA<T> & z);

template <class T>
class AA
{
        //the <> is needed to make sure the compiler knows we're
        //dealing with a template function here
        friend void print<>(const AA<T> & z);

    public:
        AA() {a = 7;}

    private:
        T a;
};

//implement print
template<class T>
void print(const AA<T> & z)
{
    cout<<"Print: "<<z.a<<endl;
}

int main()
{
    AA<int> a;
    print(a);
}

<>フレンド宣言にを追加しないとどうなるかを見るのは興味深いことです。リンカエラーが発生します。なんで?さて、コンパイラはフレンド宣言をテンプレートprint関数と一致させることができないため、プロトタイプの関数を暗黙的に想定します

void print(const AA<int>&);

存在します。呼び出しにテンプレートパラメーターを明示的に指定しなかったためprint(コンパイラーはこれを推測できるはずなので、これは必要ありません)、コンパイラーはこの呼び出しをフレンドとして宣言された関数と照合します。この関数はどこにも実装されていないため、リンカエラーが発生します。

于 2010-06-15T07:37:58.070 に答える
1

クラス定義内でフレンド関数を定義することもできます。

#include <iostream>
using namespace std;

template <class T>
class AA
{
    T a;
  public:
    AA()
    {
      a = 7;
    }

    friend void print(const AA<T> &z)
    {
      cout<<"Print: "<<z.a<<endl;
    }
};

int main()
{
  AA<int> a;
  print(a);
}
于 2010-06-15T10:17:29.487 に答える