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 我正在使用 Visual Studio 2008。

4

2 回答 2

3

The problem is that when you do something like

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

and you instantiate AA with like this

AA<int> a;

the friend declaration will be instantiated like

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

which is a non-template function! This means the compiler will not match the friend declaration with your print function.

The solution is basically to declare print before AA and explicitly tell the compiler that your friend declaration is talking about a template function. Like this:

#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);
}

It is interesting to see what happens if you do not add the <> in the friend declaration. You will get a linker error. Why? Well, because the compiler cannot match the friend declaration with your template print function, it will implicitly assume a function with prototype

void print(const AA<int>&);

exists. Since I didn't explicitly provide a template parameter to the call to print (which isn't necessary because the compiler should be able to deduce this), the compiler will match this call with the function declared as friend. This function is nowhere implemented, hence the linker error.

于 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 回答