类和对象不是一两句话就能说清楚的,笔者决定用上篇和下篇来总结给自己和朋友们。
目录
1、类和对象的初步认识
类是抽象出很多相似的实体共同拥有的特征,将它们放在一个类当中,对象就是通过类实例化出来的,拥有类的成员变量和成员函数。比如日期类,就会包含年、月、日、这样的变量可以通过类的成员函数区操作。
2、类的定义
class className
{
// 类体:由成员函数和成员变量组成
}; // 一定要注意后面的分号
class为定义类的关键字,ClassName为类的名字,{}中为类的主体,注意类定义结束时后面分号。
类中的元素称为类的成员:类中的数据称为类的属性或者成员变量; 类中的函数称为类的方法或者成员函数。
3、访问限定符和封装
3.1、访问限定符
C++实现封装的方式:用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选择性的将其
接口提供给外部的用户使用。
分别是 public、private、和public。新定义一个类如果不声明访问限定符那么默认就是private,而且作用域标识符的作用范围是从
出现开始到下一个标识符出现为止。
【访问限定符特点】
1. public修饰的成员在类外可以直接被访问
2. protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的)
3. 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
4、如何计算类对象的大小
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
/* 左操作数省略的情况下,运算符重载应该在类的内部 */
bool operator==(const Date& d2)/*左操作数是this,指向的调用函数的对象 */
{
return _year == d2._year&&_month == d2._month&&_day == d2._day;
}
private:
int _year;
int _month;
int _day;
};
类的大小计算和结构体的内存对齐相似,只是有几个注意点
1.一个空类占一个字节的空间大小
2.类的成员函数存在在类空间的的公共区域,为所有类的对象共享,不占用单个类的空间,所以不计算入类的大小中
在类当中声明的友元函数也不会占用类的空间。
3.纯虚函数空间大小为0
计算方式和结构体内存对齐相似
https://blog.csdn.net/weixin_43447989/article/details/90733534
5、this指针
前面说过了类的成员函数存在在类的公共区域,那么用类去初始化好多个一个对象,这些对象如何去找到属于自己的成员对象呢,这就需要this出场了。
什么是this指针,用自己的话说就是,系统隐藏的给类的每个成员函数都有一个隐含的参数,当某一个对象调用函数的时候,this指针就会指向对象,那么就是对这个对象操作。这个过程是自动的,编译器自己会完成。
5.1this指针的特性
1. this指针的类型:类类型* const
2. 只能在“成员函数”的内部使用
3. this指针本质上其实是一个成员函数的形参,是对象调用成员函数时,将对象地址作为实参传递给this形参。所以对象中不存储this指针。
4. this指针是成员函数第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递
5.类的每一个成员函数都有一个this指针,作为函数隐含的默认第一个形参。
至此为止,类的基本概念已经都说清楚了,在这里强调一个注意点,对象必须要有存储空间然后才能对对象进行一系列的操作
不能定义一个对象指针让它指向空,那么接下来所有的操作编译器都是通不过的。
6、类的6个默认成员函数
6个默认成员函数分别是:构造函数、析构函数、拷贝构造函数、赋值操作符重载、const成员,顾名思义他们是一个类默认一定存在的成员函数,他们有一个特点就是当用户自己定义出他们当中的任意一个的时候,类将不再使用默认成员函数,转而使用用户定义的成员函数。
6.1、构造函数
构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用,保证每个数据成员
都有 一个合适的初始值,并且在对象的生命周期内只调用一次。
6.1.1、特性
1. 函数名与类名相同。
2. 无返回值。
3. 对象实例化时编译器自动调用对应的构造函数。
4. 构造函数可以重载。
class Date
{
public :
// 1.无参构造函数
Date ()
{}
// 2.带参构造函数
Date (int year, int month , int day )
{
_year = year ;
_month = month ;
_day = day ;
}
private :
int _year ;
int _month ;
int _day ;
};
void TestDate()
{
Date d1; // 调用无参构造函数
Date d2 (2015, 1, 1); // 调用带参的构造函数
// 注意:如果通过无参构造函数创建对象时,对象后面不用跟括号,否则就成了函数声明
// 以下代码的函数:声明了d3函数,该函数无参,返回一个日期类型的对象
Date d3();
}
在这里强调一下注意点:无参构造函数在定义时不要括号,否则就成了函数声明。而且当new一个对象的时候,编译器会自己调用构造函数完成初始化。
7、析构函数
析构函数:与构造函数功能相反,析构函数不是完成对象的销毁,局部对象销毁工作是由编译器完成的。而
对象在销毁时会自动调用析构函数,完成类的一些资源清理工作。
7.1、特性
析构函数是特殊的成员函数。
其特征如下:
1. 析构函数名是在类名前加上字符 ~。
2. 无参数无返回值。
3. 一个类有且只有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。
4. 对象生命周期结束时,C++编译系统系统自动调用析构函数。
5、在堆上new空间的时候要释放这段空间,使用delete的时候会调用析构函数。
typedef int DataType;
class SeqList
{
public :
SeqList (int capacity = 10)
{
_pData = (DataType*)malloc(capacity * sizeof(DataType));
assert(_pData);
_size = 0;
_capacity = capacity;
}
~SeqList()
{
if (_pData)
{
free(_pData ); // 释放堆上的空间
_pData = NULL; // 将指针置为空
_capacity = 0;
_size = 0;
}
}
private :
int* _pData ;
size_t _size;
size_t _capacity;
};