一.类的六个默认函数
构造函数:构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用,保证每个数据成员都有 一个合适的初始值,并且在对象的生命周期内只调用一次。
构造函数的特性:构造函数是特殊的成员函数,需要注意的是,构造函数的虽然名称叫构造,但是需要注意的是构造函数的主要任务并不是开空间创建对象,而是初始化对象。如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显式定义编译器将不再生成。 无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。
1.函数名与类名相同。
2.无返回值。
3.对象实例化时编译器自动调用对应的构造函数。
4.构造函数可以重载。
析构函数:与构造函数功能相反,析构函数不是完成对象的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成类的资源清理工作。
析构函数的特性:析构函数是特殊的成员函数。
1.析构函数名是在类名前加上字符 ~。
2.无参数无返回值。
3.一个类有且只有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。
4.对象生命周期结束时,C++编译系统系统自动调用析构函数
拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。
**拷贝构造函数特性:**拷贝构造函数也是特殊的成员函数
1. 拷贝构造函数是构造函数的一个重载形式。
2. 拷贝构造函数的参数只有一个且必须使用引用传参,使用传值方式会引发无穷递归调用。
3. 若未显示定义,系统生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝我们叫做浅拷贝,或者值拷贝。
深拷贝:
class String
{
public:
String(const char* string = "")
{
int len = strlen(string) + 1;
m_data = (char*)malloc(strlen(string) + 1);
strcpy(m_data, string);
}
String(const String& s) //深拷贝
{
m_data = (char*)malloc(strlen(s.m_data) + 1);
strcpy(m_data, s.m_data);
}
//申请空间之前 把当前空间所管的释放掉
//这个也属于异常不安全的代码
String& operator=(const String& s)
{
if (this != &s)
{
free(m_data); //释放当前所管的空间
m_data = (char*)malloc(strlen(s.m_data) + 1);
strcpy(m_data, s.m_data);
}
return *this;
}
~String()
{
free(m_data);
m_data = nullptr;
}
public :
void Show()const
{
cout << m_data << endl;
}
private:
char* m_data; //如果类是指针成员 一定要用深拷贝和深赋值 函数都要重写
};
void main()
{
char str[] = "abcxyz";
cout << strlen(str) << endl;
cout << sizeof(str) << endl;
String s("abcef");
s.Show();
String s1 = s;
String s2;
s2 = s1; //相当于 s2 operator=(s1)
}
赋值运算符重载:C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。
函数名字为:关键字operator后面接重载运算符符号。
函数原型:返回值类型 operator操作符(参数列表)
注意:
1.不能通过连接其他符号来创建新的操作符:比如operator@
2.重载操作符必须有一个类类型或者枚举类型的操作数
3..* 、:: 、sizeof 、?: 、. 注意以上5个运算符不能重载。这个经常在笔试选择题中出现。
class Complex
{
public:
Complex(int real=0,int imag=0):m_real(real),m_imag(imag)
{}
~Complex()
{}
public:
friend Complex operator+(int value, const Complex& x); //友元必须真真实实给出参数
friend ostream& operator<<(ostream& out, const Complex& x);
public:
Complex operator+(const Complex& c)
{
return Complex(m_real + c.m_real, m_imag + c.m_imag);
}
Complex operator-(const Complex& c)
{
return Complex(m_real - c.m_real, m_imag + c.m_imag);
}
public:
Complex operator+(int value)
{
return Complex(m_real + value, m_imag );
}
private:
int m_real;
int m_imag;
};
Complex operator+(int value, const Complex& x)
{
return Complex(value + x.m_real, x.m_imag);
}
ostream& operator<<(ostream& out, const Complex& x)
{
out << "(" << x.m_real << "," << x.m_imag << ")";
return out;
}
void main()
{
Complex c1(1, 2);
Complex c2(3, 4);
Complex x = c1 + c2;
Complex y = c1 + 10;
cout << c1 << endl;
}
const成员:将const修饰的类成员函数称之为const成员函数,const修饰类成员函数,修饰该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改。
class test
{
public:
//构造函数
test(int data = 0)
{
m_data = data;
}
//拷贝函数
test(const test& t)
{
m_data = t.m_data;
}
//赋值
test& operator=(const test& t)
{
if (this != &t)
{
m_data = t.m_data;
}
return *this;
}
//析构函数
~test()
{}
```public:
void SetData(int data)
{
m_data = data;
}
//int GetData(const Test * const this) 加了const就变成了常量 不允许修改
int GetData() const // 常方法
{
return m_data;
}
//int GetData(Test *const this) 这两种方法是可以同时存在的 发生了重载
int GetData()
{
return m_data;
}
private:
int m_data;
};
void main()
{
Test t; //常方法普通对象是可以调用的 常对象只能调用常方法
cout << "t=" << t.GetData() << endl;
t.SetData(100);
cout << "t=" << t.GetData() << endl;
}