3 函数提高
3.1 函数默认参数
在C++中,函数的形参列表中的形参是可以有默认值的。
语法:返回值类型 函数名 (参数=默认值){}
注意事项:
1、如果函数的参数列表中某个参数已经有了默认参数,那么从这个参数开始往后的所有参数(从这个已经有默认值的参数开始,从左往右的参数都必须有默认值)
2、如果函数声明有默认参数,函数实现就不能有默认参数
函数声明和函数实现 只能有一个有默认参数,否则会出现二义性。
int func2(int a,int b);//函数声明
int func2(int a,int b)//函数实现
{
return a + b;
}
3.2 函数占位参数
C++中函数的形参列表里可以有占位参数,用来做占位,调用函数时必须填补该位置。
语法:返回值类型 函数名(数据类型){}
3.3 函数重载
3.3.1 函数重载概述
作用:函数名可以相同,提高复用性。
函数重载满足条件:
- 同一个作用域下
- 函数名称相同
- 函数参数类型不同 或者 个数不同 或者 顺序不同。
注意:函数的返回值不可以作为函数重载的条件
Java中一个类的函数重载可以在本类中的函数和来自父类中的函数之间进行,而C++类中的函数重载只能是本类中的(即不包括来自父类的函数),这是它们一个非常重要的区别。在其他方面的要求都是一致的,即要求函数名称一致,参数不同。只有返回值类型不同的函数,不能构成重载(会有编译错误,提示函数定义重复)。
3.3.2 函数重载注意事项
- 引用作为重载条件
- 函数重载碰到函数默认参数
当函数重载碰到默认参数,会出现二义性,报错,尽量避免这种情况。
4 类和对象
C++面向对象的三大特性为:封装、继承、多态。
对象有属性和行为
具有相同性质的对象,我们可以抽象为类,人属于人类,车属于车类。
4.1 封装
4.1.1 封装的意义
封装是C++面向对象三大特性之一
封装的意义:
- 将属性和行为作为一个整体,表现生活中的事物
- 将属性和行为加以权限控制
类中的属性和行为 我们统一称为 成员。
属性 又称作 成员属性或成员变量。
行为 又称作 成员函数或成员方法。
封装意义二:
类在设计时,可以把属性和行为放在不同的权限下,加以控制
访问权限有三种:
1.public 公共权限 成员在类内可以访问 类外也可以访问
2.protected 保护权限 成员在类内可以访问 类外不可以访问 子类也可以访问父类中的保护内容
3.private 私有权限 成员在类内可以访问 类外不可以访问 子类不可以访问父类中的私有内容
以下是一个使用数据封装的示例:
#include<iostream>
using namespace std;
class Circle {
private:
double radius;
public:
void setRadius(double r) {
radius = r;
}
double getRadius() {
return radius;
}
double getArea() {
return 3.14*radius*radius;
}
};
int main() {
Circle c;
c.setRadius(5.0);
cout << "Area of Circle with radius " << c.getRadius() << " is " << c.getArea() << endl;
return 0;
}
在这个例子中,我们创建了一个名为Circle的类,并提供了三个接口:setRadius、getRadius和getArea。 setRadius用于设置圆的半径,而getArea用于获取圆的面积。
注意,在类的实现中,我们使用了getter函数来获取私有成员变量的值,这样避免了外部用户直接访问圆的半径。此外,setter函数可用于设置私有数据成员的值,从而实现对数据的封装。
4.1.2 struct和class的区别
在C++中stuct和class唯一的区别就在于 默认的访问控制权限不同
区别:
- struct 默认权限为公共
- class 默认权限为私有
4.1.3 成员属性设置为私有
优点1:将所有成员属性设置为私有,可以自己控制读写权限。
优点2:对于写权限,我们可以检测数据的有效性。
Note:
1.再类中可以让另一个类作为本类中的成员;
2.如何把一个类拆到不同的文件中;
4.2 对象的初始化和清理
4.2.1 构造函数和析构函数
构造函数做初始化操作,析构函数做清理操作。
对象的初始化和清理也是两个非常重要的安全问题
一个对象或者变量没有初始状态,对其使用后果是未知
同样的使用完一个对象或变量,没有及时清理,也会造成一定的安全问题
C++利用了构造函数和析构函数解决上述问题,这两个函数将会被编译器自动调用,完成对象初始化和清理工作。
对象的初始化和清理工作是编译器强制要我们做的事情,因此如果我们不提供构造和析构,编译器会提供。
编译器提供的构造函数和析构函数是空实现(空实现:构造函数和析构函数的里面一行代码都没有)
- 构造函数:主要作用在于创建对象时为对象的成员属性赋值,构造函数由编译器自动调用,无须手动调用。
- 析构函数: 主要作用在于对象销毁前(释放前)系统自动调用,执行一些清理工作。
4.2.2 构造函数的分类及调用
两种分类方式:
按参数分为: 有参构造和无参构造
按类型分为:普通构造和拷贝构造
三种调用方式:
括号法
显示法
隐式转换法
注意事项1:调用无参构造不能加括号,如果加了括号编译器会认为这是一个函数声明。
匿名对象 的特点:当前行执行完后,系统会立即回收掉匿名对象。
注意事项2:不要利用拷贝构造函数 初始化匿名对象。
4.2.3 拷贝构造函数调用时机
C++中拷贝构造函数调用时机通常有三种情况
- 使用一个已经创建完毕的对象来初始化一个新对象。
- 值传递的方式给函数参数传值
- 以值方式返回局部对象
4.2.4 构造函数调用规则
默认情况下,c++编译器至少给一个类添加3个函数
1.默认构造函数(无参,函数体为空)
2.默认析构函数(无参,函数体为空)
3.默认拷贝构造函数,对属性进行值拷贝
构造函数调用规则如下:
- 如果用户定义有参构造函数,c++不再提供默认无参构造,但是会提供默认拷贝构造
- 如果用户定义拷贝构造函数,c++不会再提供其他构造函数