系列文章目录
C++学习笔记
- C++学习笔记(1)——C++的诞生
- C++学习笔记(3)——缺省函数与函数重载
- C++学习笔记(4)——引用
- C++学习笔记(5)——inline内联
- C++学习笔记(6)——auto关键字
- C++学习笔记(7)——类与对象(上)
- C++学习笔记(8)——类与对象(中)
文章目录
前言
如果一个类中什么成员都没有,简称为空类。但空类并非是完全空,编译器会在类的内部为空时自动生成6个默认成员函数。(默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员数。)
一、6个默认成员函数
初始化和清理
1、构造函数
2、析构函数
拷贝复制
3、拷贝构造
4、赋值重载
取地址重载
5、普通对象和connst对象取地址
6、_____
二、构造函数——自动生成对象
1、定义
构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用,以保证每个数据成员都有 一个合适的初始值,并且在对象整个生命周期内只调用一次。\
即,它的作用是自动给对象一个默认设置。
2、特性
构造函数是特殊的成员函数,需要注意的是,构造函数虽然名称叫构造,但是构造函数的主要任务并不是开空间创建对象,而是初始化对象。
其特征如下:
- 函数名与类名相同。
- 无返回值。
- 对象实例化时编译器自动调用对应的构造函数。
- 构造函数可以重载。
- 如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦
用户显式定义编译器将不再生成。
不传参就可以调用的构造就是默认构造。
- 关于编译器生成的默认成员函数的作用是:
解答:C++把类型分成内置类型(基本类型)和自定义类型。内置类型就是语言提供的数据类型,如:int/char…,自定义类型就是我们使用class/struct/union等自己定义的类型。编译器生成默认的构造函数会对自定类型成员调用的它的默认构造函数。
构造函数会自动调用它的成员函数。如下代码所示,对象man用到了World对象,而我们并没有在main()内建立World类的对象,此时编译器生成了一个构造函数,该构造函数调用了它的成员函数,成员变量赋予随机值。
#include<iostream>
using namespace std;
class World
{
public:
int a;
int b;
World()
{
cout << "The World" << endl;
cout << a <<" " << b << endl;
}
};
class Person
{
public:
World _Dio; //自定义类型
};
int main()
{
Person man;
return 0;
}
PS:C++11 中针对内置类型成员不初始化的缺陷,又打了补丁,即:内置类型成员变量在
类中声明时可以给默认值。
#include<iostream>
using namespace std;
class World
{
public:
int a=1; //默认值给予
int b=2;
World()
{
cout << a <<" " << b << endl;
}
};
class Time
{
World Dio;
};
int main()
{
Time man;
return 0;
}
- 无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。
注意:无参构造函数、全缺省构造函数和编译器默认生成的构造函数,都可以认为是默认构造函数。
三、析构函数——对象销毁时自动调用的函数
1、概念
析构函数:与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成内存资源的清理工作。
2、特性
析构函数是特殊的成员函数,其特征如下:
- 析构函数名是在类名前加上字符 ~。
- 无参数无返回值类型。
- 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构函数不能重载
- 对象生命周期结束时,C++编译系统系统自动调用析构函数。
如下代码所示,C++编译器在TestStack()函数生命周期结束时会自动调用析构函数。
#include<iostream>
using namespace std;
typedef int DataType;
class Stack
{
public:
Stack(size_t capacity = 3)
{
_array = (DataType*)malloc(sizeof(DataType) * capacity);
if (NULL == _array)
{
perror("malloc申请空间失败!!!");
return;
}
_capacity = capacity;
_size = 0;
}
void Push(DataType data)
{
// CheckCapacity();
_array[_size] = data;
_size++;
}
// 其他方法...
~Stack()
{
if (_array)
{
free(_array);
_array = NULL;
_capacity = 0;
_size = 0;
cout << "内存空间已经释放" << endl;
}
}
private:
DataType* _array;
int _capacity;
int _size;
};
void TestStack()
{
Stack s;
s.Push(1);
cout << 1 << endl;
s.Push(2);
cout << 2 << endl;
}
int main()
{
TestStack();
return 0;
}
- 编译器生成的默认析构函数会对自定类型成员起作用。
PS:创建一个类的对象则调用该类的构建函数,销毁一个类的对象则调用该类的析构函数。
#include<iostream>
using namespace std;
class Time
{
public:
~Time()
{
cout << "~Time()" << endl;
}
};
class Date
{
// 自定义类型
Time _t;
};
int main()
{
Date d;
return 0;
}
- 如果类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数,比如
Date类;有资源申请时,一定要写,否则会造成资源泄漏,比如Stack类。