• c++中的模板(8) -- 模板和友元函数


    目录

    分三种情况:

    1.  类模板和普通的友元函数 

    1)函数中不使用类模板对象作为参数和返回值 

    2)如果此函数使用类模板的作为函数参数或者返回值 

    2. 普通类和函数模板 

    3. 函数模板和类模板 

    总结: 

    之前学到过,我们可以使用友元,可以使外界的类或者函数访问类内部的私有成员。那么在使用模板之后,是否还可以使用友元函数呢?

    分三种情况:

    1.  类模板和普通的友元函数 

    1)函数中不使用类模板对象作为参数和返回值 

     和不使用模板的情况是一样的,直接在类模板中声明友元函数就行。

    1. template <typename T>
    2. class A {
    3. public:
    4. friend void test();
    5. A(const T a);
    6. T getA()const;
    7. private:
    8. T a;
    9. };
    10. template <typename T>
    11. A<T>::A(const T a) {
    12. this->a = a;
    13. }
    14. template <typename T>
    15. T A<T>::getA()const {
    16. return a;
    17. }
    18. void test() {
    19. A<int> i1(10);
    20. cout << i1.a << endl;
    21. }
    22. int main(void) {
    23. test();
    24. system("pause");
    25. return 0;
    26. }

    代码分析: 

    1.  我们在test()函数中,定义了一个类模板对象,在定义对象的时候,传入一个int用来实例化类模板的类型参数。然后我们让test()函数作为类模板的友元函数,这样就可以在test()函数中直接使用对象访问私有的成员。 -- 其实就是定义类模板对象和友元函数的使用

    2)如果此函数使用类模板的作为函数参数或者返回值 

    那么其实就和实现类模板中的成员函数是类似的,也需要写类模板使用的虚拟类型的定义。而且在声明友元函数的时候也应该加上。 

    1. template <typename T>
    2. class A {
    3. public:
    4. template <typename T>
    5. friend A<T> checkNub(A<T>& a1, A<T>& a2);
    6. A(const T a);
    7. T getA()const;
    8. private:
    9. T a;
    10. };
    11. template <typename T>
    12. A<T>::A(const T a) {
    13. this->a = a;
    14. }
    15. template <typename T>
    16. T A<T>::getA()const {
    17. return a;
    18. }
    19. // 使用函数将对象中的值进行相加,然后返回(返回局部变量,所以使用值返回)
    20. template <typename T>
    21. A<T> checkNub(A<T>& a1,A<T>& a2) {
    22. // 定义临时的对象存放相加的数据
    23. A<T> tmp(0);
    24. tmp.a = a1.a + a2.a; // 直接访问数据进行相加
    25. return tmp; // 返回相加之后的数据
    26. }
    27. int main(void) {
    28. A<int> a1(10);
    29. A<int> a2(20);
    30. A<int> a3 = checkNub(a1, a2);
    31. cout << a3.getA() << endl;
    32. system("pause");
    33. return 0;
    34. }

    代码分析: 

    1.  我们使用checkNub()函数实现将两类对象中的数据进行相加,然后再将结果以对象的形式返回。 

    2.   因为我们处理对象时,我们也不固定对象中数据的类型,所以我们可以使用类模板作为参数返回值,可以提高代码的复用性,在调用函数时再实例化类型参数。 

    3.   所以我们在定义函数时,也需要加上模板的定义,并且在声明友元函数时,也应该加上模板的定义。 

    4.   在我们调用函数时,会传入两个对象,编译器会根据传入对象的类型参数来实例化函数中的类型参数。(例如:传入a1的类型参数为int)

    2. 普通类和函数模板 

    1. class A {
    2. public:
    3. template <typename T>
    4. friend void test(T a);
    5. A(const int b);
    6. int getA()const;
    7. private:
    8. int b;
    9. };
    10. A::A(const int b) {
    11. this->b = b;
    12. }
    13. int A::getA()const{
    14. return b;
    15. }
    16. // 函数模板
    17. template <typename T>
    18. void test(T t) {
    19. A a1(10);
    20. // 直接使用对象访问私有成员
    21. cout << a1.b << endl;
    22. }
    23. int main(void) {
    24. test(10);
    25. system("pause");
    26. return 0;
    27. }

    代码分析: 

    1.  其实函数模板作为普通类的友元函数,和前面的相差不大。 

    2.  就是我们将函数模板作为友元函数的时候,也需要加上函数模板的定义。 

    3. 函数模板和类模板 

    其实就是1中的情况(2)。 

    总结: 

     不建议使用太多的友元函数

     结论:   (其也类似)
     1.  类内部声明友元函数,必须写成以下形式:
         template
         friend A checkNub(A& a,A&B);

     2.  友元实现 必须写成
         template
         A checkNub(A& a,A&B){
          ...
        }

     3.  友元函数调用 必须写成 (虽然可以不写,但是我们还是建议写上)
        A t = checkNub(c1,c2);
     

  • 相关阅读:
    【CV】第 6 章:使用迁移学习的视觉搜索
    在线手写汉字
    yarn的介绍、安装及使用
    测试工程师多年面试问题整理
    TaskWeaver使用记录
    神经网络 深度神经网络,深度神经网络通俗理解
    湖仓一体电商项目(十五):实时统计商品及一级种类、二级种类访问排行业务需求和分层设计及流程图
    Amazon EC2的出现,是时代的选择了它,还是它选择了时代
    Linux修改主机名
    【计算机视觉 | 目标检测】目标检测常用数据集及其介绍(十四)
  • 原文地址:https://blog.csdn.net/weixin_68026222/article/details/136239337