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 = 10;
int &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;
}