类的4个函数总结联系
举个栗子
// 构造函数 析构函数 赋值函数 拷贝构造函数练习
#include <iostream>
namespace Hades
{
using namespace std;
class ClassExam
{
private:
int _iNum = -1;
public:
ClassExam()
{
cout << "ClassExam 的无参(默认)构造函数. 此时 _iNum 值为:[" << _iNum << "]" << endl << endl;
}
ClassExam(int iNum) : _iNum(iNum)
{
cout << "ClassExam 的int参数构造函数. 此时 _iNum 值为:[" << _iNum << "]" << endl << endl;
}
explicit ClassExam(char cNum) : _iNum(static_cast<int>(cNum))
{
cout << "ClassExam 的char参数构造函数. 此时 _iNum 值为:[" << _iNum << "]" << endl << endl;
}
ClassExam(const ClassExam& other)
{
cout << "ClassExam 的 (默认)拷贝构造函数. 此时 _iNum 值为:[" << _iNum << "]" << endl << endl;
if (this != &other)
_iNum = other._iNum;
}
ClassExam& operator=(const ClassExam& other)
{
cout << "ClassExam 的 ClassExam&(默认)赋值函数 operator=. 此时 _iNum 值为:[" << _iNum << "]" << endl << endl;
if (this != &other)
_iNum = other._iNum;
return *this;
}
//ClassExam& operator=(const int iNum)
//{
// cout << "ClassExam 的 int赋值函数 operator=. 此时 _iNum 值为:[" << _iNum << "]" << endl << endl;
// _iNum = iNum;
// return *this;
//}
//ClassExam& operator=(const char cNum)
//{
// cout << "ClassExam 的 char赋值函数 operator=. 此时 _iNum 值为:[" << _iNum << "]" << endl << endl;
// _iNum = static_cast<int>(cNum);
// return *this;
//}
ClassExam& operator=(const char* szVal)
{
cout << "ClassExam 的 char*赋值函数 operator=. 此时 _iNum 值为:[" << _iNum << "]" << endl << endl;
_iNum = static_cast<int>(szVal[0]);
return *this;
}
~ClassExam()
{
cout << "ClassExam 的无参(默认)析构函数. 此时 _iNum 值为:[" << _iNum << "]" << endl << endl;
}
};
}
int main(int argc, char* argv[])
{
using namespace std;
using namespace Hades;
// 写出下列函数的调用顺序
ClassExam ex00;
ClassExam ex01 = 10;
ClassExam ex02(20);
ClassExam ex03 = ex01;
ClassExam ex04 = 40;
ex04 = ex00;
ex00 = 'H';
ex01 = 66;
ClassExam ex05 = 'L';
ex02 = ex05;
ex05 = ex01;
return 0;
}上诉结果看的不是特别清晰, 我重新整理一下.
<!--
| 写出下列函数的调用顺序 | ||||||
|---|---|---|---|---|---|---|
| 语句 | 存在 <span style="color:red">无参构造函数, int构造函数, char构造函数, 析构函数, 默认拷贝构造函数, 默认赋值函数</span> | 给<span style="color:red">char构造函数加上了<span style="color:blue">explicit</span>关键字</span> | 去掉<span style="color:red">int赋值函数</span> | <span style="color:red">新增增加char赋值函数</span> | 去掉<span style="color:red">char赋值函数,增加char*赋值函数</span> | |
| <span style="color:blue">ClassExam ex00;</span> | 无参构造 | 无参构造 | ||||
| <span style="color:blue">ClassExam ex01 = 10;</span> | int构造(转换构造函数) | int构造 (转换构造函数) | ||||
| <span style="color:blue">ClassExam ex02(20);</span> | int构造 | int构造 | ||||
| <span style="color:blue">ClassExam ex03 = ex01;</span> | 拷贝构造 | 拷贝构造 | ||||
| <span style="color:blue">ClassExam ex04 = 40;</span> | int构造(转换构造函数) | int构造 (转换构造函数) | ||||
| <span style="color:blue">ex04 = ex00;</span> | 默认赋值函数 | 默认赋值函数 | ||||
| <span style="color:blue">ex00 = 'H';</span> | int构造,int赋值函数,析构函数 <span style="color:red">写错了!!!!! int赋值函数</span> | int赋值函数 | 默认赋值 <span style="color:red">写错了!!!!! int构造, 默认赋值, 析构</span> | char赋值 | char*赋值 <span style="color:red">写错了!!! int构造, 默认赋值, 析构</span> | |
| <span style="color:blue">ex01 = 66;</span> | int赋值函数 | int赋值函数 | int构造, 默认赋值, 析构 | int构造, 默认赋值, 析构 | ||
| <span style="color:blue">ClassExam ex05 = 'L';</span> | char构造(转换构造函数) | int构造 (转换构造函数) | int构造 (转换构造函数) | int构造 (转换构造函数) | ||
| <span style="color:blue">ex02 = ex05;</span> | 默认赋值函数 | 默认赋值函数 | ||||
| <span style="color:blue">ex05 = ex01;</span> | 默认赋值函数 | 默认赋值函数 | ||||
-->
| 写出下列函数的调用顺序 | |||||
|---|---|---|---|---|---|
| 语句 | 存在 <span style="color:red">无参构造函数, int构造函数, char构造函数, 析构函数, 默认拷贝构造函数, 默认赋值函数 int赋值函数</span> |
给<span style="color:red"><br/>char构造函数加上了<br/><span style="color:blue">explicit</span>关键字</span> | 去掉<span style="color:red"><br/>int赋值函数</span> | 新增<span style="color:red"><br/>char赋值函数</span> | 去掉<span style="color:red"><br/>char赋值函数,<br/>增加char*赋值函数</span> |
| <span style="color:blue">ClassExam ex00;</span> | 无参构造 | 无参构造 | 无参构造 | 无参构造 | 无参构造 |
| <span style="color:blue">ClassExam ex01 = 10;</span> | int构造<br/>(转换构造函数) | int构造<br/>(转换构造函数) | int构造<br/>(转换构造函数) | int构造<br/>(转换构造函数) | int构造<br/>(转换构造函数) |
| <span style="color:blue">ClassExam ex02(20);</span> | int构造 | int构造 | int构造 | int构造 | int构造 |
| <span style="color:blue">ClassExam ex03 = ex01;</span> | 拷贝构造 | 拷贝构造 | 拷贝构造 | 拷贝构造 | 拷贝构造 |
| <span style="color:blue">ClassExam ex04 = 40;</span> | int构造<br/>(转换构造函数) | int构造<br/>(转换构造函数) | int构造<br/>(转换构造函数) | int构造<br/>(转换构造函数) | int构造<br/>(转换构造函数) |
| <span style="color:blue">ex04 = ex00;</span> | 默认赋值函数 | 默认赋值函数 | 默认赋值函数 | 默认赋值函数 | 默认赋值函数 |
| <span style="color:blue">ex00 = 'H';</span> | int赋值函数</span> | int赋值函数 | int构造, 默认赋值, 析构</span> | char赋值 | int构造, 默认赋值, 析构</span> |
| <span style="color:blue">ex01 = 66;</span> | int赋值函数 | int赋值函数 | int构造, 默认赋值, 析构 | char赋值 | int构造, 默认赋值, 析构 |
| <span style="color:blue">ClassExam ex05 = 'L';</span> | char构造<br/>(转换构造函数) | int构造 <br/>(转换构造函数) | int构造 <br/>(转换构造函数) | int构造 <br/>(转换构造函数) | int构造 <br/>(转换构造函数) |
| <span style="color:blue">ex02 = ex05;</span> | 默认赋值函数 | 默认赋值函数 | 默认赋值函数 | 默认赋值函数 | 默认赋值函数 |
| <span style="color:blue">ex05 = ex01;</span> | 默认赋值函数 | 默认赋值函数 | 默认赋值函数 | 默认赋值函数 | 默认赋值函数 |
个人总结
- 在有新对象产生的时候, 必定会调用构造函数.
- 在给
不存在的新对象进行=操作的时候,必定不是赋值操作. 在给
已存对象进行=操作的时候,必定会调用赋值函数.赋值函数匹配原则:
先进行精确匹配.
- 比如例子中, 存在int的赋值函数时, 会直接调用.
不能进行精准匹配时, 进行提升匹配.
- 比如例子中, 存在int的赋值函数时, ex00 = 'H'; 会将'H'进行提升转换, 然后调用int的赋值函数.
提升匹配失败后, 进行强制转换(隐式转换)匹配
- 比如例子中, 存在char的赋值函数并不存在int的赋值函数时, 进行 ex1 = 66; 会将 66 隐式转换为char然后调用char的赋值函数.
匹配都失败后, 将尝试进行
默认赋值函数调用.- 比如例子中, 只有char* 的赋值函数存在时, ex00 = 'H' 就没有任何匹配项.
- 所以编译器会去调用
默认赋值函数. - 默认赋值函数需要有一个该类的对象, 又因为给定了char参数, 所以会调用该类的char构造函数.
- 但是char的构造被限制不能隐式转换, 那么它又被提升转换到int后在去调用int的构造函数.
- 然后将产生的新对象传递进入
默认赋值函数中, 进行赋值操作.
结论
在对象产生时, 必定会调用构造函数.
在类对象的 = 操作中, 都是进行函数的调用.
- 在有新对象产生时, 调用的是
拷贝构造函数. - 在没有新对象产生是, 调用的是
赋值函数.
在对象销毁时, 必定会调用析构函数.
如有错误,请提出指正!谢谢.
本文由 花心胡萝卜 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: 2017-01-04 at 01:51 am