您的位置:首页 > 编程语言 > C语言/C++

C++ 类构造函数初始化列表的异常机制 function-try block

2009-08-17 22:27 274 查看
上篇文章提到了 C++ 类构造函数对成员变量初始化赋值时使用“初始化列表”的方式带来的好处。这篇文章将介绍另一个大大的好处——由初始化列表异常块机制带来的构造函数的安全性机制。

听起来有些拗口。直接上代码:

class Fck
{
int* sbArray;
public:
Fck ( int sbNum );
~Fck ();
};
Fck :: Fck ( int sbNum )
try: sbArray ( new int[sbNum] )
{
cout << " Fck Constructing " << sbNum << endl;
}
catch ( bad_alloc& err )
{
cout << err.what() << endl;
cout << " Fck Failed " << endl;
};
Fck :: ~Fck ()
{
delete this->sbArray;
cout << " Fck Destructing " << endl;
}
int _tmain(int argc, _TCHAR* argv[])
{
Fck fck ( 5 );
//Fck fck_1 ( -1 );
try
{
Fck fck_1 ( -1 );
}
catch ( bad_alloc& err )
{
cout << err.what() << endl;
cout << " Main Failed " << endl;
}
catch ( ... ) { }
system ( "pause" );
return 0;
}


《C++ 异常机制 32 点》这篇文章里第 20 点谈到了这种用法。Fck 类的构造函数中需要对类成员变量 int* 型的 sbArray 指定一块新开辟出来的堆内存空间。这里有一个问题,若传递进去的 sbNum 是负值当如何?当然会报异常。注意到构造函数后紧跟着一个 catch 块用于捕获初始化列表 try 块生成的异常。完了么?没有,尽管原代码没有写,但是,在执行完这段 catch 块之后,会紧跟着再将此异常“外抛”出去!这个通过查看汇编码就知道了,在该 catch 块完成后,系统会自动再调一次 throw,在此就不展开细说了,读者可自行验证。这有点像 JAVA 里面的“上抛机制”。抛给谁呢?当然是给主函数了,于是,主函数必须还得有一个 try – catch 块去处理异常。

这么麻烦?这样做是有很大的好处的。试想,若成员构造时发生了异常,此时这个类对像是构造失败的,一个构造失败的类对像是不可以使用的。构造函数必须通知主函数自己是否正常。这一机制保证了这一过程的安全。

你当然也可以这么来写构造函数,即不使用初始化列表的方式:

Fck :: Fck ( int sbNum )
{
try
{
sbArray = new int[sbNum];
}
catch ( ... ) {}
cout << " Fck Constructing " << sbNum << endl;
}


这样,异常在构造函数内处理完了,不会再“上抛”,主函数根本就不知道这个类对像是构造失败的,使用中必然会出现不可预知的错误!

若有读者对此仍存疑,或者想了解更多,请参阅《续:为何说 C++ 构造函数初始化列表异常机制是必要的》

参考:

《C++ 0x(C++ 09)新标准全部革新提案文档列表》
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: