1. 概念引入
在说明构造函数和析构函数的概念之前, 首先看一个例子
下面这段代码是栈经典的应用场景括号匹配
如图, 栈必须先初始化,然后在每一个return false之前都需要销毁栈, 不然就会内存泄漏
这样很繁琐, 而且有些时候很容易忘记写, 所以在C++中添加默认的成员函数,构造函数和析构函数来自动进行初始化和清理工作
2. 6个默认的成员函数
这6个默认的成员函数都是编译器自动生成的, 它们自动进行不同的工作, 如下
本章详细说明其中的两个, 构造函数和析构函数
3. 构造函数
概念及特性
构造函数是特殊的成员函数,需要注意的是,构造函数虽然名称叫构造,但是构造函数的主要任务并不是开空间创建对象,而是初始化对象
其特征如下:
- 函数名与类名相同
- 无返回值
- 对象实例化时编译器自动调用对应的构造函数
- 构造函数可以重载
- 如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显式定义编译器将不再生成
特性解析
下面用栈来解析特性:
1. 函数名与类名相同
2. 无返回值
3. 对象实例化时编译器自动调用对应的构造函数
stack.cpp
#include <iostream>
using namespace std;
typedef int DataType;
class Stack
{
public:
// 函数名与类名相同, 无返回值
Stack()
{
_array = (DataType*)malloc(sizeof(DataType) * 4);
if (NULL == _array)
{
perror("malloc申请空间失败!!!");
return;
}
_capacity = 4;
_size = 0;
}
/*void Init()
{
_array = (DataType*)malloc(sizeof(DataType) * 4);
if (NULL == _array)
{
perror("malloc申请空间失败!!!");
return;
}
_capacity = 4;
_size = 0;
}*/
void Push(DataType data)
{
CheckCapacity();
_array[_size] = data;
_size++;
}
void Pop()
{
if (Empty())
return;
_size--;
}
DataType Top() { return _array[_size - 1]; }
int Empty() { return 0 == _size; }
int Size() { return _size; }
void Destroy()
{
if (_array)
{
free(_array);
_array = NULL;
_capacity = 0;
_size = 0;
}
}
private:
void CheckCapacity()
{
if (_size == _capacity)
{
int newcapacity = _capacity * 2;
DataType* temp = (DataType*)realloc(_array, newcapacity * sizeof(DataType));
if (temp == NULL)
{
perror("realloc申请空间失败!!!");
return;
}
_array = temp;
_capacity = newcapacity;
}
}
private:
DataType* _array;
int _capacity;
int _size;
};
int main()
{
Stack s; // 自动调用构造函数
//s.Init();
s.Push(1);
s.Push(2);
s.Push(3);
s.Push(4);
}
4. 构造函数可以重载
构造函数支持重载是因为可能会有多种初始化的场景
5. 如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显式定义编译器将不再生成
#include <iostream>
using namespace std;
class Date
{
public:
void Init(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
void Print() // 3. void Print(Date* this)
{
cout << this->_year << "-" << this->_month << "-" << this->_day << endl;
}
private:
int _year; // 年
int _month; // 月
int _day; // 日
};
int main()
{
Date d1, d2;
//d1.Init(2022, 1, 11);
//d2.Init(2023, 4, 28);
d1.Print();
//d1.Print(&d1);
//d2.Print();
//d2.print(&d2);
}
从图中, 发现编译器默认生成的构造函数好像并没有进行初始化, 依旧是随机值
这是因为C++标准规定内置类型(char, int...)不做处理(置0), 但是自定义类型(class, struct)会去调用它的默认构造函数处理初始化, 如下图
test.cpp
#include <iostream>
using namespace std;
typedef int DataType;
class Stack
{
public:
/*Stack(DataType* a, int n)
{
cout << "Stack(DataType* a, int n)" << endl;
_array = (DataType*)malloc(sizeof(DataType) * n);
if (NULL == _array)
{
perror("malloc申请空间失败!!!");
return;
}
memcpy(_array, a, sizeof(DataType) * n);
_capacity = n;
_size = n;
}*/
Stack(int capacity = 4)
{
cout << "Stack(int capacity = 4)" << endl;
_array = (DataType*)malloc(sizeof(DataType) * capacity);
if (NULL == _array)
{
perror("malloc申请空间失败!!!");
return;
}
_capacity = capacity;
_size = 0;
}
/*void Init()
{
_array = (DataType*)malloc(sizeof(DataType) * 4);
if (NULL == _array)
{
perror("malloc申请空间失败!!!");
return;
}
_capacity = 4;
_size = 0;
}*/
void Push(DataType data)
{
CheckCapacity();
_array[_size] = data;
_size++;
}
void Pop()
{
if (Empty())
return;
_size--;
}
DataType Top() { return _array[_size - 1]; }
int Empty() { return 0 == _size; }
int Size() { return _size; }
/*void Destroy()
{
if (_array)
{
free(_array);
_array = NULL;
_capacity = 0;
_size = 0;
}
}*/
~Stack()
{
cout << "~Stack()" << endl;
if (_array)
{
free(_array);
_array = NULL;
_capacity = 0;
_size = 0;
}
}
private:
void CheckCapacity()
{
if (_size == _capacity)
{
int newcapacity = _capacity * 2;
DataType* temp = (DataType*)realloc(_array, newcapacity * sizeof(DataType));
if (temp == NULL)
{
perror("realloc申请空间失败!!!");
return;
}
_array = temp;
_capacity = newcapacity;
}
}
private:
DataType* _array;
int _capacity;
int _size;
};
class Date
{
public:
void Init(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
void Print() // 3. void Print(Date* this)
{
cout << this->_year << "-" << this->_month << "-" << this->_day << endl;
}
private:
// 内置类型
int _year; // 年
int _month; // 月
int _day; // 日
// 自定义类型
Stack st;
};
int main()
{
Date d1, d2;
//d1.Init(2022, 1, 11);
//d2.Init(2023, 4, 28);
d1.Print();
//d1.Print(&d1);
//d2.Print();
//d2.print(&d2);
}
在C++11中, 为了弥补内置类型成员不初始化的缺陷,打了补丁 (内置类型成员变量在类中声明时可以给默认值)
class Date
{
public:
void Init(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
void Print() // 3. void Print(Date* this)
{
cout << this->_year << "-" << this->_month << "-" << this->_day << endl;
}
private:
// 不是初始化, 而是默认的缺省值
int _year = 1;
int _month = 1;
int _day = 1;
};
int main()
{
Date d1, d2;
d1.Print();
}
构造函数的调用
构造函数的调用与普通函数不同, 如下例
class Date
{
public:
Date()
{
_year = 1;
_month = 1;
_day = 1;
}
Date(int year = 1, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
void Init(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
void Print() // 3. void Print(Date* this)
{
cout << this->_year << "-" << this->_month << "-" << this->_day << endl;
}
private:
// 不是初始化, 而是缺省值(默认值)
int _year = 1;
int _month = 1;
int _day = 1;
};
int main()
{
Date d1(2222,2,2); // 构造函数的调用
d1.Print();
}
默认的构造函数
编译器默认生成的构造函数,无参的构造函数和全缺省的构造函数都称为默认构造函数,且默认构造函数只能有一个
类实例化对象时会自动调用构造函数, 但是由于有两个默认的构造函数, 所以报错
4. 析构函数
概念及特性
析构函数与构造函数功能相反, 完成对象中资源的清理工作
注意: 析构函数不是完成对对象本身的销毁而是对象中的资源, 局部对象本身的销毁工作是由编译器完成的
特性如下:
- 析构函数名是在类名前加上字符 ~
- 无参数无返回值类型
- 对象生命周期结束时,C++编译系统系统自动调用析构函数
- 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构函数不能重载
- 关于编译器自动生成的析构函数,是否会完成一些事情呢?下面的程序我们会看到,编译器生成的默认析构函数,对自定类型成员调用它的析构函数
解析特性
下面还是用栈来解析这些特性:
析构函数名是在类名前加上字符 ~
无参数无返回值类型
对象生命周期结束时,C++编译系统系统自动调用析构函数
stack.cpp
#include <iostream>
using namespace std;
typedef int DataType;
class Stack
{
public:
// 函数名与类名相同, 无返回值
Stack()
{
_array = (DataType*)malloc(sizeof(DataType) * 4);
if (NULL == _array)
{
perror("malloc申请空间失败!!!");
return;
}
_capacity = 4;
_size = 0;
}
/*void Init()
{
_array = (DataType*)malloc(sizeof(DataType) * 4);
if (NULL == _array)
{
perror("malloc申请空间失败!!!");
return;
}
_capacity = 4;
_size = 0;
}*/
void Push(DataType data)
{
CheckCapacity();
_array[_size] = data;
_size++;
}
void Pop()
{
if (Empty())
return;
_size--;
}
DataType Top() { return _array[_size - 1]; }
int Empty() { return 0 == _size; }
int Size() { return _size; }
// 析构函数
~Stack()
{
if (_array)
{
free(_array);
_array = NULL;
_capacity = 0;
_size = 0;
}
}
/*void Destroy()
{
if (_array)
{
free(_array);
_array = NULL;
_capacity = 0;
_size = 0;
}
}*/
private:
void CheckCapacity()
{
if (_size == _capacity)
{
int newcapacity = _capacity * 2;
DataType* temp = (DataType*)realloc(_array, newcapacity * sizeof(DataType));
if (temp == NULL)
{
perror("realloc申请空间失败!!!");
return;
}
_array = temp;
_capacity = newcapacity;
}
}
private:
DataType* _array;
int _capacity;
int _size;
};
int main()
{
Stack s; // 对象实例化时编译器自动调用对应的构造函数
//s.Init();
s.Push(1);
s.Push(2);
s.Push(3);
s.Push(4);
//s.Destroy();
}
标签:size,函数,int,void,DataType,array,和析构,构造函数 From: https://www.cnblogs.com/xumu11291/p/17362198.html