目录
分三种情况:
1. 类模板和普通的友元函数
1)函数中不使用类模板对象作为参数和返回值
2)如果此函数使用类模板的作为函数参数或者返回值
2. 普通类和函数模板
3. 函数模板和类模板
总结:
之前学到过,我们可以使用友元,可以使外界的类或者函数访问类内部的私有成员。那么在使用模板之后,是否还可以使用友元函数呢?
1. 类模板和普通的友元函数
1)函数中不使用类模板对象作为参数和返回值
和不使用模板的情况是一样的,直接在类模板中声明友元函数就行。
代码分析:
1. 我们在test()函数中,定义了一个类模板对象,在定义对象的时候,传入一个int用来实例化类模板的类型参数。然后我们让test()函数作为类模板的友元函数,这样就可以在test()函数中直接使用对象访问私有的成员。 -- 其实就是定义类模板对象和友元函数的使用
2)如果此函数使用类模板的作为函数参数或者返回值
那么其实就和实现类模板中的成员函数是类似的,也需要写类模板使用的虚拟类型的定义。而且在声明友元函数的时候也应该加上。
代码分析:
1. 我们使用checkNub()函数实现将两类对象中的数据进行相加,然后再将结果以对象的形式返回。
2. 因为我们处理对象时,我们也不固定对象中数据的类型,所以我们可以使用类模板作为参数和返回值,可以提高代码的复用性,在调用函数时再实例化类型参数。
3. 所以我们在定义函数时,也需要加上模板的定义,并且在声明友元函数时,也应该加上模板的定义。
4. 在我们调用函数时,会传入两个对象,编译器会根据传入对象的类型参数来实例化函数中的类型参数。(例如:传入a1的类型参数为int)
2. 普通类和函数模板
代码分析:
1. 其实函数模板作为普通类的友元函数,和前面的相差不大。
2. 就是我们将函数模板作为友元函数的时候,也需要加上函数模板的定义。
3. 函数模板和类模板
其实就是1中的情况(2)。
不建议使用太多的友元函数
结论: (其也类似)
1. 类内部声明友元函数,必须写成以下形式:
template <typename T>
friend A<T> checkNub(A<T>& a,A<T>&B);
2. 友元实现 必须写成
template<typename T>
A<T> checkNub(A<T>& a,A<T>&B){
...
}
3. 友元函数调用 必须写成 (虽然可以不写,但是我们还是建议写上)
A<int> t = checkNub<int>(c1,c2);