1.构造函数:
构造函数 ,是一种特殊的方法。主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中。
如果创建一个类你没有写任何构造函数,则系统会自动生成默认的无参构造函数,函数为空,什么都不做只要写了一个其他的某一种构造函数,系统就不会再自动生成这样一个默认的构造函数,如果希望有一个这样的无参构造函数,则需要自己显示地写出来。
一般构造函数可以有各种参数形式,一个类可以有多个一般构造函数,前提是参数的个数或者类型不同(基于c++的重载函数原理),创建对象时根据传入的参数不同调用不同的构造函数。
复制构造函数(也称为拷贝构造函数),复制构造函数参数为类对象本身的引用,用于根据一个已存在的对象复制出一个新的该类的对象,一般在函数中会将已存在对象的数据成员的值复制一份到新创建的对象中,若没有显示的写复制构造函数,则系统会默认创建一个复制构造函数,但当类中有指针成员时,由系统默认创建该复制构造函数会存在风险,具体原因请查询 有关 “浅拷贝” 、“深拷贝”的文章论述。
类型转换构造函数,根据一个指定的类型的对象创建一个本类的对象,需要注意的一点是,这个其实就是一般的构造函数,但是对于出现这种单参数的构造函数,C++会默认将参数对应的类型转换为该类类型,有时候这种隐私的转换是我们所不想要的,所以需要使用explicit来限制这种转换。
赋值构造函数,注意这个类似复制构造函数,将=右边的本类对象的值复制给等号左边的对象,它不属于构造函数,等号左右两边的对象必须已经被创建,若没有显示的写=运算符重载,则系统也会创建一个默认的=运算符重载,只做一些基本的拷贝工作。
2.析构函数:
析构函数(destructor) 与构造函数相反,当对象结束其生命周期,如对象所在的函数已调用完毕时,系统自动执行析构函数。析构函数往往用来做“清理善后” 的工作(例如在建立对象时用new开辟了一片内存空间,delete会自动调用析构函数后释放内存)。
手写String类实现基本的构造函数和析构函数:
String.h
#include "pch.h"
#include <iostream>
class String
{
public:
String(const char *str);//通用构造函数
String(const String &str);//拷贝构造函数,第一个参数为该类对象的一个引用,其余参数要有默认值
String& operator=(const String &str);//赋值构造,重载=运算符
~String();//析构函数
friend ostream& operator<<(ostream &os, String &str);
char *data;//字符串
size_t length;//字符串长度;
};
String .cpp
#include "pch.h"
#include "String.h"
#include <string.h>
using namespace std;
String::String(const char *str)
{
if (str)
{
length = 0;
data = new char[1];
data[0] = '\0';
}
else
{
length = strlen(str);
data = new char[length + 1];
strcpy(data, str);
}
}
//拷贝构造函数要进行深赋拷贝操作;
String::String(const String & str)
{
length = str.length;
data = new char[length + 1];
strcpy(data, str.data);
}
//重载=运算符,会改变原有的字符串,为避免内存泄漏,先释放原先的内存;
String & String::operator=(const String & str)
{
if (this == &str) return *this;
delete[]data;
length = str.length;
data = new char[length + 1];
strcpy(data, str.data);
return *this;
}
//析构函数需要释放空间,及长度归零
String::~String()
{
delete[]data;
length = 0;
}