• 14_C++_面向对象_类和对象_封装


    01.引用的使用场景(重点)

    1.引用作为函数参数

    //1.引用作为函数参数
    void func(int &a, int &b)
    {
    	int sum = a + b;
    	cout << "sum=" << sum << endl;
    }
    
    void test01()
    {
    	int a = 10;
    	int b = 20;
    	func(a, b);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    2.引用作为函数的返回值

    //2.引用作为函数的返回值
    int& func2()
    {
    	int b = 10;//注意1:不要返回局部变量的引用
    	int &p = b;
    	return p;
    }
    int &func3()
    {
    	static int b = 10;
    	return b;
    }
    void test02()
    {
    	int &q = func2();
    	q = 100;
    	cout << q << endl;
    
    	func2() = 200;
    	cout << q << endl;
    ---------上面的代码是错误,只是编译器没有检测出来
    	cout << "func2="<<func2() << endl;
    
    	func3() = 100;
    	//注意2:如果要函数当左值,那么该函数必须返回引用
    	cout << "func3()=" << func3() << endl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    02.常量引用(了解)

    int &ref=10;//err
    const int &ref2=10;//ok
    //原理是:
    int tmp=10;
    const int &ref=tmp;
    
    • 1
    • 2
    • 3
    • 4
    • 5

    03.内联函数(了解)

    1.宏函数的缺陷

    #define ADD(x,y) x+y
    //在普通函数前面加上inline是向编译器申请成为内联函数
    //注意:加inline可能成为内联函数,可能不成为内联函数
    inline int Add(int x, int y)
    {
    	return x + y;
    }
    
    void test()
    {
    	//10+20*2
    	int ref = ADD(10, 20) * 2;
    	cout << "ref=" << ref << endl;
    
    	int ref2 = Add(10, 20) * 2;
    	cout << "ref2=" << ref2 << endl;
    }
    
    #define COMAPD(x,y) ((x)<(y)?(x):(y))
    inline int func(int x, int y)
    {
    	return x < y ? x : y;
    }
    void test02()
    {
    	int a = 1;
    	int b = 3;
    	//                        ((++a)<(b)?(++a):(b))      
    	//cout << "COMAPD(x,y)=" << COMAPD(++a, b) << endl;//3
    	cout << "func=" << func(++a, b) << endl;//2
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    2.什么情况不会成为内联函数

    ​ 1.存在过多的条件判断语句

    ​ 2.函数体过大

    ​ 3.对函数进行取址操作

    ​ 4.存在任何形式的循环语句

    3.内联函数的好处

    ​ 1.有宏函数的效率,没有宏函数的缺点

    ​ 2.类的成员函数默认加上inline

    4.在普通函数前面加上inline是申请成为内联函数

    04.函数的默认参数(重点)

    1.函数的默认参数就是给函数的形参赋值

    int myFunc(int a, int b = 0)//int b=0;这就是函数的默认参数,不一定是0
    {
    	return a + b;
    }
    void test01()
    {
    	//函数的默认参数的作用
    	//当函数内常要用到形参的某个值,但偶尔要使用其他值
    	//增加函数的灵活性
    	cout << myFunc(10, 20) << endl;
    	cout << myFunc(10)<< endl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    2.函数的默认参数的注意事项

    //注意1:函数的默认参数后面的参数必须都是默认参数
    int myFunc2(int a, int b = 0, int c=2,int d=3)
    {
    	return a + b + c + d;
    }
    //注意2:函数的声明和实现不能同时有函数的默认参数
    void myFunc3(int a, int b);
    void myFunc3(int a, int b = 0)
    {
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    05.函数的占位参数(了解)

    //函数的占位参数,占位参数在后面运算符重载时区分前加加或后加加
    void func(int a,int=10)//占位参数也有默认值
    {
    
    }
    
    void test02()
    {
    	func(10);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    函数的默认参数和占位参数的混搭

    //占位参数和默认参数混搭
    void func2(int=10, int a=20)
    {
    
    }
    void test03()
    {
    	func2();
    	func2(10);
    	func2(10,30);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    06.函数重载(重点)

    1.函数重载是:允许函数名相同,这种现象叫函数重载

    2.函数重载的作用:是为了方便使用函数名

    3.函数重载的条件:同一个作用域,参数的个数不同,参数的顺序不同,参数的类型不同

    //参数的个数不同
    void func()
    {
    	cout << "func()" << endl;
    }
    
    void func(int a)
    {
    	cout << "func(int a)" << endl;
    }
    
    //参数的类型不同
    void func(char c)
    {
    	cout << "func(char c)" << endl;
    }
    //参数的顺序不同
    void func(int a, double b)
    {
    	cout << "func(int a, double b)" << endl;
    }
    void func(double b, int a)
    {
    	cout << "func(double b, int a)" << endl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    4.调用重载函数的注意

    严格的类型匹配,如果类型不匹配,那么尝试转换,转换成功就掉用,失败就报错

    void test01()
    {
    	int a = 10;
    	double b = 3.14;
    
    	func();
    	//func(b);// err double转换不了成为int或char
    	func(a, b);
    	func(b, a);
    	char c = 'c';
    	func(c);//char转换int成功,调用int参数的函数
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    5.函数重载和函数的默认参数一起使用,需要注意二义性问题

    //函数重载和函的默认参数一起使用
    void myfunc(int a, int b = 0)
    {
    	cout << "myfunc(int a, int b = 0)" << endl;
    }
    
    void myfunc(int a)
    {
    	cout << "myfunc(int a)" << endl;
    }
    
    void test02()
    {
    	//myfunc(10); err,二义性问题,不知道调用哪个函数
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    6.函数的返回值不作为函数重载的条件

    编译器是通过你调用函数时,传入的参数来判断调用重载的哪个函数,我们调研函数时不需要写返回值,所以返回值不能成为函数重载的条件

    07.函数重载的原理(重点)

    1.函数重载的原理是在汇编时,给各个函数取别名,C语言不能重载的原因是没有取别名

    2.生成汇编文件:gcc -S test.c -o test.s g++ -S test.cpp -o test2.s

    3.查看内容:type 文件名

    08.C++调用C语言的函数(重点)

    1.C++的函数在汇编时,会给函数取别名,C语言的不会,这时,如果C++来调用C语言的函数,C++会去找取了别名的函数,但是C语言没有取别名,这时会出错

    test.h文件中
    
    //这是告诉C++编译器,找下面的函数,要以C语言的方式去寻找
    #ifdef __cplusplus
    extern "C"
    {
    #endif
    	void func();//C语言的函数声明
    
    
    #ifdef __cplusplus
    }
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    09.类和对象的概念(重点)

    1.类是自定义数据类型,是C语言的结构体进化而成的

    2.对象是类实例化出的,用数据类型定义一个变量

    class Maker//这个是类
    {
    public:
    	int a;//成员属性(成员变量)
    	void func()//成员方法(成员函数)
    	{
    		cout << "func" << endl;
    	}
    };
    
    int main()
    {
    	Maker m;//m就是对象
    
    	system("pause");
    	return EXIT_SUCCESS;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    10.类的封装(重点)

    1.封装是把属性(变量)和方法(函数)封装到类内,然后给这些数据赋予权限

    2.为什么要有封装

    ​ 1.防止乱调用函数和变量,出现错误

    ​ 2.维护代码更方便

    3.权限

    //封装:1,把属性和方法放到类中,2.给这些数据赋予权限
    class Maker
    {
    public://公有权限
    	void set(string Name,int Id)
    	{
    		id = Id;
    		name = Name;
    	}
    	void printMaker()
    	{
    		cout << "id=" << id << " name=" << name << endl;
    	}
    private://私有
    	int id;
    	string name;
    
    protected://保护
    	int a;
    };
    //继承
    class Son :public Maker
    {
    	void func()
    	{
    		a = 20;//子类的类内可以方法父类的保护权限的成员
    		
    	}
    };
    //类外不能访问私有权限的成员
    //类外可以访问公有权限的成员
    //类外不能访问保护权限的成员
    //子类的类内可以方法父类的保护权限的成员
    //类内是没有权限之分
    
    void test()
    {
    	Maker m;
    	m.set("小花",1);
    	m.printMaker();
    	
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    4.尽量把属性设置为私有权限

    1.可以控制属性的读写权限

    2.可赋予客户端访问数据的一致性

    3.可以保护属性的合法性

    11.类和结构体的区别(了解)

    结构体的默认权限是公有的,类的默认权限是私有的

  • 相关阅读:
    Python的张量运算
    Java运算符
    第二节:Git 远程仓库
    SpringBoot前后端分离整合cas(客户端)
    验证码:EasyDL 机器学习识别与云码平台一站式识别
    牛客网——verilog练习题思路汇总
    空调开28度,一晚上会消耗多少电?空调耗电量与什么有关?
    正则表达式-常见字符使用方法
    Linux C : select简介和epoll 实现
    定制密钥管理系统的好处 安当加密
  • 原文地址:https://blog.csdn.net/m0_48948682/article/details/126151781