c++中入门到入狱之引用

110 阅读1分钟

c++中入门到入狱之引用

引用的基本使用

作用:给变量起别名,可以通过别名来操作内存

语法:数据类型 &别名 = 原名

int a= 10;
int &b = a;
b = 1000;
cout<<"a = "<<a<<endl;
cout<<"b = "<<b<<endl;

引用的注意事项

引用必须初始化

int a= 10
int &b;//错误别名必须要初始化

引用在初始化后,不可以改变

int a = 10;
int c= 20;
int &b = a;
b = c//这个是赋值操作,不是更改别名操作

引用必须要引用一块合法的内存空间

int &b = 15;//这样是不允许的

引用做函数的参数

作用:函数传参时,可以利用引用的技术让形参修饰实参

优点:可以简化简化指针修改实参

#include<iostream>
using namespace std;
void printf1(int &a,int &b) {
	int temp = a;
	a = b;
	b = temp;
	cout << "a = " << a << endl;//20
	cout << "b = " << b << endl;//10
}
int main()
{
	int a = 10, b = 20;
	printf1(a, b);
	cout << "a = " << a << endl;//20,引用作为参数也可以修饰实参
	cout << "b = " << b << endl;//10
	system("pause");
	return 0;
}

引用做函数的返回值

作用:引用是可以作为函数的返回值存在的

注意:不要返回局部变量的引用

#include<iostream>
using namespace std;
int& printf1() {
	int a = 10;
	return a;
}
int main()
{
	int &ref = printf1();
	cout << "ref = " << ref << endl;//vs编译器中在不同的系统下打印都不相同x86下,第一次打印为10,第二次直接非法操作
	//在x64系统下,都是非法操作
	cout << "ref = " << ref << endl;
	system("pause");
	return 0;
}

用法:函数调用作为左值

#include<iostream>
using namespace std;
int& printf1() {
	static int a = 10;//加上static关键字,使这个局部变量存放在全局区,而全局区由系统控制,当程序执行完毕后,才会清除全局区存放的变量
	return a;
}
int main()
{
	int &ref = printf1();
	cout << "ref = " << ref << endl;//10
	printf1() = 1000;
	cout << "ref = " << ref << endl;//1000
	cout << "ref = " << ref << endl;//1000
	cout << "ref = " << ref << endl;//1000
	system("pause");
	return 0;
}

引用的本质

本质:引用的本质在C++内部实现是一个指针常量

int a = 10;
int &b = a;//相当于int * const b = &a;每次使用b,c++内部都会自动给你解引用

常量引用

作用:常量引用主要用于修饰形参,防止误操作

在函数形参列表中,可以加const修饰形参,防止形参改变实参

const int &b = 10;这样是允许的,它不像
int &b = 10;这样是不允许的,他直接引用一个字面量,而引用必须要一块合法的内存空间,
而const int &b = 10,相当于
int temp = 10int &b = temp;

函数的提高

函数默认参数

在c++中,函数的形参列表中的形参是可以有默认值的

语法:返回值类型 函数名 (参数 = 默认值){}

如果我们传入数据则用我们传入数据,没有传入,则用默认值

注意事项:1.如果某个位置已经有了默认参数,那么从这个位置往后,从左到右都必须有默认值

2.如果函数声明有默认参数,函数实现就不能有默认参数

#include<iostream>
using namespace std;
int printf1(int a = 10,int b = 20) 
{
	return a + b;
}
//int printf2(int a = 10, int b)//有默认值参数后面必须紧跟默认值,如果没有则会报错
//{
//	return a + b;
//}
int printf3(int a,int b);
int main()
{
	cout << "printf1:" << printf1(50,50) << endl;//如果没有传入参数,用默认,传入时用传入参数
	system("pause");
	return 0;
}

int printf3(int a = 10, int b = 20)//如果声明函数时,传入默认值了,后面定义函数时就不能在传入默认值,反之,不能声明和定义函数时都传入默认值
{
	return a + b;
}

函数的占位参数

c++中函数的形参列表中可以有占位参数,用于做占位,调用函数时必须填补该位置

语法:返回值类型 函数名(数据类型){}

#include<iostream>
using namespace std;
void printf1(int a,int) 
{
	cout << a << endl;
}
int main()
{
	printf1(10,0);//必须要传入占位时参数类型的值,要不然报错
	system("pause");
	return 0;
}

占位参数还可以有默认参数

#include<iostream>
using namespace std;
void printf1(int a,int = 10) //占位默认参数
{
	cout << a << endl;
}
int main()
{
	printf1(10);//有默认值就不需要传入占位参数
	system("pause");
	return 0;
}

函数重载

作用:函数名可以相同,提高复用性

函数重载满足条件

同一作用域下

函数名称相同

函数参数类型不同或者个数不同或者顺序不同

注意:函数的返回值不可以作为函数重载的条件

#include<iostream>
using namespace std;
void fn1()
{
	cout << "fn" << endl;
}
void fn1(int res)//第一个函数重载和第二个函数重载参数个数不同
{
	cout << "(int a)fn" << endl;
}
void fn1(double a)//第三个和第二个函数重载不同于参数类型不同
{
	cout << "(double a)" << endl;
}
void fn1(double a,int b)//第4个和第5个函数重载不同于参数顺序不同
{
	cout << "(double a,int b)" << endl;
}
void fn1(int a, double b)//第4个和第5个函数重载不同于参数顺序不同
{
	cout << "(int a, double b)" << endl;
}
//int fn1()//函数返回类型不能作为函数重载的条件
//{
//	cout << "(fn1)" << endl;
//}
int main()
{
	fn1(10);//输出(int a)fn//函数重载必须满足一下条件:作用域相同,函数名相同,参数类型或者参数个数,参数顺序不同。
	fn1(30.45); //输出(double a)	
	fn1(10,3.14);//输出(int a, double b)
	fn1(10.1, 3);//输出(double a,int b)
	system("pause");
	return 0;
}

函数重载注意事项

引用作为重载条件

函数重载碰到函数默认参数

#include<iostream>
using namespace std;
//引用作为重载函数的参数
void fn(int &a)
{
	cout << "fn(int &a)" << endl;
}
void fn(const int &a)
{
	cout << "fn(const int &a)" << endl;
}
void fn1(int a, int b = 10)
{
	cout << "fn(const int &a)" << endl;
}

//函数重载碰到函数默认参数
void fn1(int a)
{
	cout << "fn(const int &a)" << endl;
}
int main()
{
	int a = 10;
	fn(a);//输出fn(int &a),原因引用是一个合法的内存空间地址。
	fn(10);//输出fn(const int &a),10为字面量,不是一个合法的内存空间地址,而const int &a在引用时就讲过,10会被一个临时变量接受,然后在赋给int &a
	//fn1(10);//如果有一个默认值参数不同,其他参数类型,个数,顺序,相同,这样会出现二义性,编译器不知道该执行谁,因此要避免这种情况
	system("pause");
	return 0;
}

类和对象

c++面向对象的三大特性:封装,继承,多态

c++认为万事万物都是对象,每个对象都有自己的方法和属性

封装

封装的意义:

封装是c++面向对象三大特征之一

封装的意义:

将属性和行为作为一个整体,表现生活中的事物

将属性和行为加以权限控制

封装意义一:

在设计类的时候,属性和行为写在一起,表现事物

类中的属性和方法我们统一称他为成员

属性又可以叫成员属性和成员变量

行为又可以叫成员函数和成员方法

语法:class 类名 {访问权限:属性/方法}

案例:

#include<iostream>
using namespace std;
const double PI = 3.14;
class Cla { //类名Cla
public:
	int r;//属性
	int printZc()//方法
	{
		return 2 * PI * r;
	}
};
int main()
{
	Cla c;//实例化一个c实例出来
	c.r = 20;
	cout << "周长为:" << c.printZc() << endl;
	system("pause");
	return 0;
}

访问权限

类在设计时,可以把属性和行为放在不同的权限下,加以控制

访问权限有三种

1.public 公共权限:类内可以访问,类外可以访问

2.protected 保护权限 类内可以访问,类外不可以访问

3.private 私有权限 类内可以访问,类外不可以访问

struct和class的区别

在c++中struct和class唯一的区别就在于默认的访问权限不同

struct默认权限为公共

class默认权限为私有

#include<iostream>
using namespace std;
struct C1 
{
	int m_a;
};
class C2 
{
	int m_a;
};
int main()
{
	C1 c; //struct默认为公共
	c.m_a = 100;
	cout << "C1:" << c.m_a << endl;
	C2 c2;
	//c2.m_a=100;class默认为私有,不能访问
	system("pause");
	return 0;
}