key 发表于 11-5-2009 16:43:14

类模板与友元的问题/Issue with class template and its friend method

泛型是C++的一个非常大的发明,我很喜欢这个发明。但可惜的是,
泛型在各个编译器中的支持各不相同。类模板及其友元的问题应该是其中
一个。我自己没有具体看C++98这类标准,只能从网上找一些片言只字去
了解一下,希望其他同学帮我解释和补充。谢谢

首先我们来看MSDN的一个例子:
http://msdn.microsoft.com/en-us/library/f1b2td24.aspx

例一可以简化为:template<class T> class X {
template<class T>
friend void method(int t, X<T> const & x);
};

template<class T> void method(int t, X<T> const & x) { cout << "hello friend." << endl; }

int main()
{
    X<int> k;

    method(1, k);
    return 0;
}这段代码可以很好地在Visual Studio 8中编译并运行,得到:
hello friend.

这样的结果。但在gcc4中,友元的声明就出错了。
t.cpp:7: error: declaration of 'class T'
t.cpp:6: error:shadows template parm 'class T'

好在,这里提示的出错是shadow了T这个模板名称,把第二个template<class T>改成template<class T2>,编译就顺利进行了。

例子二中揭示了另一种类模板友元的声明方式,虽然该例中要说明的是另一个问题。根据例二,上面的简化代码可以改成:template<class T> class X;
template<class T> void method(int t, X<T> const & x);

template<class T> class X {
friend void method<> (int t, X<T> const & x); //这里不需要重新写template <class T>这样的声明
};

template<class T> void method(int t, X<T> const & x) { cout << "hello friend." << endl; }

int main()
{
    X<int> k;

    method(1, k);
    return 0;
}当然了,例二中最想说明的其实是友元的特例化,也就是:template<class T> class X {
friend void method<int> (int t, X<int> const & x); //这里把友元函数特例化成只对T==int时才成立
};如果采用这种方式,在method<T>的实现中就不能访问类X的私有成员了。

例三说明的是类模板的友元类,看起来并不复杂,就不讨论了。

我想补充的时,对于例一,还有一种内嵌的实现方式:template<class T> class X {
friend void method(int t, X<T> const & x){ cout << "hello friend." << endl; }
};用这种内嵌的方式,可以把友元的声明简化到和一般的类方法声明并不多,就是多了一个friend关键字。
然而,采用这种方式声明的友元是不可以和实现分离的。

[ 本帖最后由 key 于 17-5-2009 11:20 编辑 ]
页: [1]
查看完整版本: 类模板与友元的问题/Issue with class template and its friend method