一、转换构造函数:支持发生隐式类型转换的函数
如果构造函数的参数只有一个且非当前类对象,可以把它当成当前类型使用。
CTest(int a):m_a(a){
}
CTest(int a,int b=30):m_a(a){
}
CTest(int a=20,int b=30):m_a(a){
}
int main()
{
Ctest tst;
tst=60;//隐式类型转换
}
以上三种情况支持隐式类型转换
但是可以使用关键字explicit禁止发生隐式类型转换
二、拷贝构造
拷贝构造函数,是编译器默认给提供的一种构造函数,函数原型是CTest(const CTest &tst),重点是一定要加&,不然会产生重复调用的问题(如果值传递,给形参赋值时依旧会调用拷贝构造,产生自己调用自己的情况)
函数体代码不能为空,形参中的对象给this指针指向的对象依次初始化,
一旦我们手动重构,编译器就不会再提供了
#include<iostream>
using namespace std;
class CTest{
public:
int m_a;
CTest()
{
m_a=10;
}
CTest(const CTest &tst):m_a(tst.m_a)
{
}
~CTest()
{
}
};
int main()
{
CTest tst;
CTest tst2(tst);
return 0;
}
二、浅拷贝问题
但是当类中出现指针时,默认的拷贝构造会出现浅拷贝问题
(两个指针指向同一块内存,当一个指针回收内存后,另一个指针再次回收就会崩;通过其中一个指针修改空间内的值,另一个指针读取空间的值,值也会改变)
解决浅拷贝问题使用深拷贝(手动重构拷贝构造函数,并为拷贝的对象开辟属于自己的空间)
CTest(const CTest &tst):m_a(tst.m_a)
{
if(tst.m_p)
{
this->m_p=new int(*tst.m_p);
}else
{
this->m_p=nullptr;
}
}
函数的参数是结构体或类时,应当尽量避免值传递,尽量使用指针或者引用(避免浅拷贝问题)
四、默认的operator=
空类中也会默认给提供一个operator=,函数体代码不能为空,形参中的对象依次给this对象赋值
一旦手动重构,编译器就不提供默认的了,
CTest& operator=(const CTest& tst)
{
this->m_a=tst.m_a;
this->m_p=tst.m_p;
}
但是默认的operator也存在浅拷贝问题,需要深拷贝来解决
CTest& operator=(const CTest &tst)
{
if(this!=tst)
{
this->m_a=tst.m_a;
if(tst.m_p)
{
if(this->m_p)
{
*this->m_p=*tst->m_p;
}else
{
this->m_p=new int(*tst->m_p)
}
}else
{
if(this->m_p)
{
delete this->m_p;
}
this->m_p=nullptr;
}
}
}
五、总结:
类中默认提供的函数
默认无参构造
默认拷贝构造
默认operator=
默认析构函数