zoukankan      html  css  js  c++  java
  • 19 友元的尴尬能力

    1 友元的概念

    • 什么是友元?

      • 友元是 C++ 中的一种关系

      • 友元关系发生在函数与类之间或者类与类之间

      • 友元关系是单向的,不能传递

        • 左边的函数是右边类的友元,所以左边的函数可以访问右边类的成员

    • 友元的用法

      • 在类中以 friend 关键字声明友元
      • 类的友元可以是其他类或者具体函数
      • 友元不是类的一部分
      • 友元不受类中访问级别的限制
      • 友元可以直接访问具体类的所有成员 => 破坏了类的封装性
    • 友元的语法

      • 在类中用 friend 关键字对函数或类进行声明
    • 示例:友元的使用

      • Demo

        #include <stdio.h>
        #include <math.h>
        
        class Point
        {
            double x;
            double y;
        public:
            Point(double x, double y)
            {
                this->x = x;
                this->y = y;
            }
            
            double getX()
            {
                return x;
            }
            
            double getY()
            {
                return y;
            }
               
            friend double func(Point& p1, Point& p2);
        };
        
        double func(Point& p1, Point& p2)
        {
            double ret = 0;
            
            ret = (p2.y - p1.y) * (p2.y - p1.y) +
                  (p2.x - p1.x) * (p2.x - p1.x);
                  
            ret = sqrt(ret);
            
            return ret;
        }
        
        int main()
        {
            Point p1(1, 2);
            Point p2(10, 20);
            
            printf("p1(%f, %f)
        ", p1.getX(), p1.getY());
            printf("p2(%f, %f)
        ", p2.getX(), p2.getY());
            printf("|(p1, p2)| = %f
        ", func(p1, p2));
            
            return 0;
        }
        
      • 编译运行

        p1(1, 2)
        p2(10, 20)
        |(p1, p2)| = 20.124612
        

    2 友元的尴尬

    • 友元是为了兼顾 C 语言的高效而诞生的
    • 友元直接破坏了面对对象的封装性
    • 友元在实际产品中的高效是得不偿失的
    • 友元在现代软件工程中已经逐渐被遗弃

    3 注意事项

    • 友元关系不具备传递性

    • 类的友元可以是其他类的成员函数

    • 类的友元可以是某个完整的类

    • 示例:友元深入分析

      • Demo

        #include <stdio.h>
        
        class ClassC
        {
            const char* n;
        public:
            ClassC(const char* n)
            {
                this->n = n;
            }
            
            friend class ClassB;  //类B是类C的友元
        };
        
        class ClassB
        {
            const char* n;
        public:
            ClassB(const char* n)
            {
                this->n = n;
            }
            
            void getClassCName(ClassC& c)
            {
                printf("c.n = %s
        ", c.n);
            }
            
            friend class ClassA;  //类A是类B的友元
        };
        
        class ClassA
        {
            const char* n;
        public:
            ClassA(const char* n)
            {
                this->n = n;
            }
            
            void getClassBName(ClassB& b)
            {
                printf("b.n = %s
        ", b.n);
            }
            /*
            void getClassCName(ClassC& c)  //类A中不能直接访问类C的成员,不具备友元关系
            {
                printf("c.n = %s
        ", c.n);
            }
            */
        };
        
        int main()
        {
            ClassA A("A");
            ClassB B("B");
            ClassC C("C");
            
            A.getClassBName(B);
            B.getClassCName(C);
            
            return 0;
        }
        
      • 编译运行

        b.n = B
        c.n = C
        
  • 相关阅读:
    《MySQL必知必会》第二十三章:使用存储过程
    《MySQL必知必会》第二十四章:使用游标
    《MySQL必知必会》第二十五章:使用触发器
    《MySQL必知必会》第二十章:更新和删除数据
    《MySQL必知必会》第二十一章:创建和操纵表
    《MySQL必知必会》第二十二章:使用视图
    《MySQL必知必会》第十七章:组合查询
    《MySQL必知必会》第十八章:全文本搜索
    [LeetCode] 930. Binary Subarrays With Sum
    [LeetCode] 676. Implement Magic Dictionary
  • 原文地址:https://www.cnblogs.com/bky-hbq/p/13722969.html
Copyright © 2011-2022 走看看