zoukankan      html  css  js  c++  java
  • C++解析(16):友元与类中的函数重载

    0.目录

    1.友元的尴尬能力

    2.类中的函数重载

    3.小结

    1.友元的尴尬能力

    什么是友元

    • 友元是C++中的一种关系
    • 友元关系发生在函数与类之间或者类与类之间
    • 友元关系是单项的不能传递

    友元的用法:

    • 在类中以friend关键字声明友元
    • 类的友元可以是其它类或者具体函数
    • 友元不是类的一部分
    • 友元不受类中访问级别的限制
    • 友元可以直接访问具体类的所有成员

    友元的语法——在类中用friend关键字对函数进行声明:

    示例一:

    #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;
    }
    

    运行结果为:

    [root@bogon Desktop]# g++ test.cpp
    [root@bogon Desktop]# ./a.out 
    p1(1.000000, 2.000000)
    p2(10.000000, 20.000000)
    |(p1, p2)| = 20.124612
    

    友元的尴尬:

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

    注意事项:

    • 友元关系不具备传递性
    • 类的友元可以是其它类的成员函数
    • 类的友元可以是某个完整的类
      1. 所有的成员函数都是友元

    示例二:

    #include <stdio.h>
    
    class ClassC
    {
        const char* n;
    public:
        ClassC(const char* n)
        {
            this->n = n;
        }
        
        friend class ClassB;
    };
    
    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;
    };
    
    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)
        {
            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;
    }
    

    运行结果为:

    [root@bogon Desktop]# g++ test.cpp
    [root@bogon Desktop]# ./a.out 
    b.n = B
    c.n = C
    

    2.类中的函数重载

    函数重载回顾:

    • 函数重载的本质为相互独立的不同函数
    • C++中通过函数名函数参数确定函数调用
    • 无法直接通过函数名得到重载函数的入口地址
    • 函数重载必然发生在同一个作用域中

    类中的重载——类中的成员函数可以进行重载

    • 构造函数的重载
    • 普通成员函数的重载
    • 静态成员函数的重载

    问题:
    全局函数,普通成员函数以及静态成员函数之间是否可以构成重载?

    万变不离其宗:

    1. 重载函数的本质为多个不同的函数
    2. 函数名参数列表是唯一的标识
    3. 函数重载必须发生在同一个作用域中

    示例:

    #include <stdio.h>
    
    class Test
    {
        int i;
    public:
        Test()
        {
            printf("Test::Test()
    ");
            this->i = 0;
        }
        
        Test(int i)
        {
            printf("Test::Test(int i)
    ");
            this->i = i;
        }
        
        Test(const Test& obj)
        {
            printf("Test(const Test& obj)
    ");
            this->i = obj.i;
        }
        
        static void func()
        {
            printf("void Test::func()
    ");
        }
        
        void func(int i)
        {
            printf("void Test::func(int i), i = %d
    ", i);
        }
        
        int getI()
        {
            return i;
        }
    };
    
    void func()
    {
        printf("void func()
    ");
    }
    
    void func(int i)
    {
        printf("void func(int i), i = %d
    ", i);
    }
    
    int main()
    {
        func();
        func(1);
        
        printf("
    ");
        
        Test t;        // Test::Test()
        Test t1(1);    // Test::Test(int i)
        Test t2(t1);   // Test(const Test& obj)
        
        printf("
    ");
        
        func();        // void func()
        Test::func();  // void Test::func()
        
        printf("
    ");
        
        func(2);       // void func(int i), i = 2;
        t1.func(2);    // void Test::func(int i), i = 2
        t1.func();     // void Test::func()
        
        return 0;
    }
    

    运行结果为:

    [root@bogon Desktop]# g++ test.cpp
    [root@bogon Desktop]# ./a.out 
    void func()
    void func(int i), i = 1
    
    Test::Test()
    Test::Test(int i)
    Test(const Test& obj)
    
    void func()
    void Test::func()
    
    void func(int i), i = 2
    void Test::func(int i), i = 2
    void Test::func()
    

    全局函数与类中的成员函数不可以构成重载。

    重载的意义

    • 通过函数名对函数功能进行提示
    • 通过参数列表对函数用法进行提示
    • 扩展系统中已经存在的函数功能

    原有的字符串拷贝功能:

    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
        const char* s = "Hello World!";
        char buf[16] = {0};
        
        strcpy(buf, s);
        
        printf("%s
    ", buf);
        
        return 0;
    }
    

    但是若是buf的长度不够,就会出错!
    因此采用函数重载进行修改:

    #include <stdio.h>
    #include <string.h>
    
    char* strcpy(char* buf, const char* str, unsigned int n)
    {
        return strncpy(buf, str, n);
    }
    
    int main()
    {
        const char* s = "Hello World!";
        char buf[8] = {0};
        
        //strcpy(buf, s);
        strcpy(buf, s, sizeof(buf)-1);
        
        printf("%s
    ", buf);
        
        return 0;
    }
    

    运行结果为:

    [root@bogon Desktop]# g++ test.cpp
    [root@bogon Desktop]# ./a.out 
    Hello W
    

    重载能够扩展系统中已经存在的函数功能!那么重载是否也能够扩展其它更多的功能?(更多内容下节分解......)

    3.小结

    • 友元是为了兼顾C语言的高效而诞生的
    • 友元直接破坏了面向对象的封装性
    • 友元关系不具备传递性
    • 类的友元可以是其它类的成员函数
    • 类的友元可以是某个完整的类
    • 类的成员函数之间可以进行重载
    • 重载必须发生在同一个作用域中
    • 全局函数成员函数不能构成重载关系
    • 重载的意义在于扩展已经存在的功能
  • 相关阅读:
    Qt5.3.2(VS2010)_调试_进入Qt源码
    Qt5.3.2(VS2010)_调试_遇到的问题
    Qt_QString::split测试
    Qt_QString.indesOf和mid测试
    激活_目标窗口
    DrawDibDraw__ZC测试
    【转】DrawDibDraw
    数学运算_基本_01
    get和post请求及进程和线程及cookie和session的区别
    Redis性能优化之redis.cnf配置文件
  • 原文地址:https://www.cnblogs.com/PyLearn/p/10083328.html
Copyright © 2011-2022 走看看