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