类
类似与c语言中的结构体,但是在C语言中结构体只能定义变量,C++中结构体不但可以定义变量,也可以定义函数,但是在C++当中人们更喜欢称之为类。同时在C++当中用class代替结构体中的struct。
类的定义
class为定义类的关键字,ClassName为类的名字,{}中为类的主体,注意类定义结束时后面分号。
类中的元素为类的成员,类中数据称为类的属性或者称之为成员变量;类中的函数称为类的方法或者称为类的成员函数。
类的定义方式
- 声明和定义都放在类中
- 类的声明和定义分两个文件
定义存放在.cpp文件中,声明存放在.h文件中,但在定义是需要在定义前面加上类名与作用域分辨符。
访问限定符
C++实现封装的方式:用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用。
- public修饰的成员可以在类外直接进行访问
- private和protected修饰的成员都不可以在类外进行直接访问
- 访问权限作用域从访问限定符开始出现的位置到下一个访问限定符出现时为止
- class默认的访问权限为private,struct默认的权限为public
类的实例化
用类进行创造对象的过程,称为类的实例化。
- 类相当于一个模型一样,定义类时并没有对类进行分配空间
- 类实例出来的对象占有物理空间
- 类相当于图纸,对象相当于通过图纸建造的房子
- 一个类可以实例化多个对象,例如:一个图纸可以建造多个房间
类的大小
类的大小为成员变量大小之和(但需要进行字节对齐),成员函数不计算在类大小中,如果类中没有成员变量,编译器会为类分配一定的空间,vs 、gcc为其分配1个字节,不同的编译器,会分配不同的大小。
类的字节对齐类似与C语言中结构体字节对齐
this指针
提出问题:
className类创建两个对象,当c1调用set函数时,如何知道设置c1的对象。
C++中提供this指针解决这类问题:
即:C++编译器给每个“成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有成员变量的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。
this指针的特性
- 指针类型 :类类型 *const
- 只能在“成员函数”中使用
- 本质上为一个成员指针,所以this指针存在栈区
- 由编译器自动完成,不需要用户进行调用
构造函数
构造函数为一个特殊的成员函数,名字与类名相同,编译器自动调用,在每个对象的生命周期里面只调用一次。构造函数主要负责对对象进行初始化。
构造函数特性
- 无返回类型,void都不用写
- 函数名与类名相同
- 当用户没有写构造函数时,会由编译器调用默认的构造函数
- 构造函数可以进行重载 (所以一个类中至少有一个构造函数)
- 如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显式定义,编译器将不会自动生成
Date () //默认构造函数也称为无参的构造函数
{
}
如果通过无参构造函数创建对象时,对象后面不用跟括号,否则就成了函数声明
析构函数
析构函数的功能刚好与构造函数功能相反,析构函数不是完成对象的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成类资源的一些清理工作。
析构函数时一个特殊的成员函数
特征
- 在类名前面加上 ~
- 无参数无返回值
- 一个类只有一个析构函数,如果用户没定义,编译器将自动调用默认析构函数
拷贝构造函数
拷贝构造函数是用已经存在类类型对象创建新对象。
- 拷贝构造函数也是特殊的成员函数
- 拷贝构造函数是对构造函数的一种重载形式
- 拷贝构造函数的参数只有一个必须是引用类型,(不使用引用类型会造成无限递归),如果确保函数的值与类类型参数的值相同可以加const
如果拷贝构造函数没有传引用
- 如果用户没有自己定义拷贝构造函数,编译器会自动调用默认的拷贝构造函数,
这种拷贝被称为浅拷贝,如果一个类里卖弄没有申请资源(从堆上面动态开辟空间),则不会造成危害,如果开辟空间,会在程序生命周期结束时调用析构函数,出现内存释放(回收)错误。
运算符的重载
在数学结构中,我们知道有+ - * /几种简单的运算符,在C++当中,为了方便运算,也会将数学运算符进行重载。
如果不进行运算符重载就直接对其进行操作,一般情况下会直接错误。
- 运算符是具有特殊函数名的函数
- 函数名字: 关键字(operator)后面加上你想重载的符号
注意 - 不能重载C++中没有的运算符 例如: @
- 重载操作符必须有一个类类型或者枚举类型的操作数
- 不能改变其含义 例如:你重载 + 操作,但是在函数内部实现的却是 - 操作,尽管编译器不会产生语法 错误,但是不符合逻辑
- 形参比操作数少1个成员 例如:+ 操作为双目运算符,但在重载时只需要传一个参数,因为重载函数操作时,会有一个默认的形参 this
- .* (点星) 、 ::(作用域限定符) 、sizeof 、?: (三目运算符) 、. (点)这5个运算符不能进重载
赋值运算符重载
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
Date(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
Date& operator=(const Date& d)
{
if (this != &d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
}
private:
int _year;
int _month;
int _day;
};
- 参数类型
- 返回值
const成员
const修饰类的成员函数
将const修饰的类成员函数称之为const成员函数,const修饰类成员函数,实际修饰该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员做出修改