版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
1.构造函数的回顾
- 类的构造函数用于对象的初始化
- 构造函数与类同名并且没有返回值
- 构造函数在对象定义时自动被调用
2.面试题
- 1. 如何判断构造函数的执行结果?
- 没有办法直接判断构造函数的执行结果。
- 2. 在构造函数中执行return语句会发生什么?
- return语句执行后,构造函数立即返回(return前面初始化成功,后面为随机值)。
- 3. 构造函数执行结束是否意味着对象构造成功?
- 构造函数执行结束,且并不意味着对象构造成功。
-
#include<stdio.h>
-
-
class Test
-
{
-
int mi;
-
int mj;
-
bool mStatus;
-
-
public:
-
Test(
int i,
int j) :mStatus(
false)
-
{
-
mi = i;
-
return;
-
mj = j;
-
mStatus =
true;
-
}
-
int getI()
-
{
-
return mi;
-
}
-
-
int getJ()
-
{
-
return mj;
-
}
-
-
int status()
-
{
-
return mStatus;
-
}
-
};
-
-
int main()
-
{
-
Test t1(1, 2);
-
-
if (t1.status())
-
{
-
printf(
"t1.mi = %d\n", t1.getI());
-
printf(
"t1.mi = %d\n", t1.getJ());
-
}
-
-
getchar();
-
-
return
0;
-
}
- 打印结果为空,说明main函数中if判断为false。说明构造函数包含return之后会中止执行。
3.你该知道的真相
- 构造函数
- 只提供自动初始化成员变量的机会
- 不能保证初始化逻辑—定成功
- 执行return语句后构造函数立即结束
- 真相的意义:构造函数能决定的只是对象的初始状态,而不是对象的诞生!!
4.半成品对象的概念
- 初始化操作不能按照预期完成而得到的对象,半成品对象是合法的C++对象,也是Bug的重要来源
5.构造中的异常
- 如果构造函数中抛出异常会发生什么情况?
- 构造过程立即停止
- 当前对象无法生成
- 析构函数不会被调用
- 对象所占用的空间立即收回
- 工程项目中的建议
- 不要在构造函数中抛出异常
- 当构造函数可能产生异常时,使用二阶构造模式
-
#include <iostream>
-
-
using
namespace
std;
-
-
class Test
-
{
-
public:
-
Test()
-
{
-
cout <<
"Test()" <<
endl;
-
-
throw
0;
-
}
-
-
virtual ~Test()
-
{
-
cout <<
"~Test()" <<
endl;
-
}
-
};
-
-
int main(int argc, char *argv[])
-
{
-
Test *p =
reinterpret_cast<Test*>(
1);
-
-
try
-
{
-
p =
new Test();
-
}
-
-
catch (...)
-
{
-
cout <<
"Exception..." <<
endl;
-
}
-
-
cout <<
"p=" << p <<
endl;
-
-
getchar();
-
-
return
0;
-
}
- 运行结果:
6.析构中的异常
- 避免在析构函数中抛出异常!!
- 析构函数的异常将导致: 对象所使用的资源无法完全释放。
7.二阶构造
- 工程开发中的构造过程可分为
- 资源无关的初始化操作 :不可能出现异常情况的操作
- 需要使用系统资源的操作 :可能出现异常情况,如:内存申请,访问文件
- 二阶构造示例—
-
class
TwoPhaseCons
-
{
-
private:
-
TwoPhaseCons()
-
{
-
//第一阶段构造函数,资源无关操作
-
}
-
-
bool construct()
-
{
-
//第二阶段构造函数,使用系统资源操作
-
return
true;
-
}
-
public:
-
static TwoPhaseCons* New工nstance () ;
//对象创建函数
-
} ;
- 二阶构造示例
-
TwoPhaseCons* TwoPhaseCons::NewInstance()
-
{
-
TwoPhaseCons* ret =
new TwoPhaseCons();
-
-
//若第二阶段构造失败,返回NULL
-
if(! (ret && ret->construct()))
-
{
-
delete ret;
-
ret =
NULL;
-
}
-
-
return ret;
-
}
8.编程实例
-
#include<stdio.h>
-
-
class TwoPhaseCons
-
{
-
private:
-
TwoPhaseCons()
-
{
-
-
}
-
-
bool construct()
-
{
-
return
true;
-
}
-
-
public:
-
static TwoPhaseCons* NewInstance();
// 对象创建函数
-
};
-
-
TwoPhaseCons* TwoPhaseCons::NewInstance()
-
{
-
TwoPhaseCons *ret =
new TwoPhaseCons();
-
//若第二阶段构造失败,返回NULL
-
if (!(ret && ret->construct()))
-
{
-
delete ret;
-
ret =
NULL;
-
}
-
-
return ret;
-
}
-
-
int main()
-
{
-
TwoPhaseCons *obj = TwoPhaseCons::NewInstance();
-
-
printf(
"obj = %p\n", obj);
-
-
delete obj;
-
-
getchar();
-
-
return
0;
-
}
- 打印结果为任意地址
9.小结
- 构造函数只能决定对象的初始化状态
- 构造函数中初始化操作的失败不影响对象的诞生
- 初始化不完全的半成品对象是Bug的重要来源
- 二阶构造人为的将初始化过程分为两部分
- 二阶构造能够确保创建的对象都是完整初始化的
- 构造函数和析构函数中不要抛出异常