特点:自己不提供时,由系统提供,所有系统提供的函数都是共有的、内联的;系统提供的函数调用是无参数列表的,且自动调用。自己提供时、系统不再提供。
1、构造函数
2、析构函数
3、拷贝构造函数
4、赋值运算符的重载函数
5、取地址操作符的重载函数
6、const修饰的取地址的操作符的重载函数
对象的生成步骤:1、开辟内存 2、内存空间的初始化
1、构造函数:构造函数和类名相同
(1)作用:给类的实例化对象赋资源
(2)初始化对象的内存空间(必须现有对象然后初始化)
(3)构造函数可重载
(4)构造函数不可手动调用、由系统调用,调用系统提供的CGoods good;
(5)构造函数为顺序构造
CGoods(char* name, float price, int amount) //构造函数
{
std::cout << this << " :CGoods::CGoods(char*,float,int)" << std::endl;
mname = new char[strlen(name) + 1]();
strcpy(mname, name);
mprice = price;
mamount = amount;
}
CGoods() //系统默认构造函数
{}
2、析构函数: 析构函数和类名相同并在函数名前加‘~’
(1)作用:释放对象所占的其他资源(堆内存),然后释放它本身所占的内存空间
(2)析构函数原型只有一个
(3)析构函数不可重载
(4)析构函数可手动调用、退化成普通函数的调用
(5)先构造的函数后进行析构(遵循栈的先进后出原则)
~CGoods() //析构函数
{
std::cout << this << " :CGoods::~CGoods()" << std::endl;
delete[] mname;
}
~CGoods() //系统默认析构函数(什么都不做)
{}
3、拷贝构造函数:拷贝构造函数和类名相同
(1)作用:用一个已存在的对象生成一个新的相同的对象
(2)拷贝构造函数默认使用浅拷贝
(3)拷贝构造函数对于指针类型只将新指针指向与原指针相同的内存单元并不创建新的内存单元,这将在内存释放时调用两次析构造成程序崩溃。所以对于指针类型我们建议实现深拷贝,创建新的内存单元,这样保证两次析构的正常进行。
(4)拷贝构造函数的形参用&接收、防止递归构造形参对象(所引用的对象)导致栈溢出
CGoods(const CGoods& rhs) //拷贝构造函数
{
std::cout << this << " :CGoods::CGoods(const CGoods&)" << std::endl;
mname = new char[strlen(rhs.mname) + 1]();
strcpy(mname, rhs.mname);
mprice = rhs.mprice;
mamount = rhs.mamount;
}
4、赋值运算符的重载函数:需要进行的运算符前加 "operator" 返回值类型为函数本身类型
(1)作用:把一个已存在的对象赋值给相同类型的已存在对象实现
(2)重载函数默认使用浅拷贝
(3)当拷贝构造函数的this指针所指向的地址与参数rhs指针所指向地址相同时直接进行赋值------------自赋值
(4)当拷贝构造函数的this指针所指向的地址与参数rhs指针所指向地址不相同时:1、释放旧资源 2、开辟新资源 3、赋值
CGoods& operator=(const CGoods& rhs) //赋值运算符的重载函数
{
std::cout << this << " :CGoods::operator=(const CGoods&)" << std::endl;
if (this != &rhs)
{
delete[] mname;
mname = new char[strlen(rhs.mname) + 1]();
strcpy(mname, rhs.mname);
mprice = rhs.mprice;
mamount = rhs.mamount;
}
return *this;
}