2、委派构造函数的异常处理
当目标构造函数抛出异常时,该异常会被委派构造函数中的 try 模块抓取到。并且在这种情况下,委派构造函数自己函数体内的代码就不会被执行了。
下面我们也通过例子来看看,构造函数 A(int i, int j)抛出一个异常,该异常依次被委派构造函数 A(int i)和 A()抓取到,且 A(int i)和 A()的函数体没有被执行。
程序源代码 (exception1.cpp)
#include <iostream> using namespace std; class A{ public: A(); A(int i); A(int i, int j); private: int num1; int num2; int average; }; A:: A()try: A(0) { // A()函数体不会被执行到 cout << "A() body"<< endl; } catch(...) { cout << "A() catch"<< endl; } A::A(int i) try : A(i, 0){ // A(int i)函数体不会被执行到 cout << "A(int i) body"<< endl; } catch(...) { cout << "A(int i) catch"<< endl; } A::A(int i, int j) try { num1=i; num2=j; average=(num1+num2)/2; cout << "A(int i, int j) body"<< endl; // 抛出异常 throw 1; } catch(...) { cout << "A(int i, int j) catch"<< endl; } int main(){ try{ A a; cout << "main body"<< endl; } catch(...){ cout << "main catch"<< endl; } return 0; } |
该例的输出为:
A(int i, int j) body
A(int i, int j) catch
A(int i) catch
A() catch
main catch
当委派构造函数抛出异常时,系统会自动调用目标构造函数内已经构造完成的对象的析构函数。在下面的例子中,目标构造函数 A(int i, int j)完成了对象 a 的构造。它的委派构造函数 A(int i)在执行时抛出了一个异常,此时对象 a 马上被析构,且 A(int i)的委派构造函数 A()的函数体不再被编译器执行,这和上例中所描述的原则是一致的。
程序源代码 (exception2.cpp)
#include <iostream> using namespace std; class A{ public: A(); A(int i); A(int i, int j); ~A(); private: int num1; int num2; int average; }; A::A(): A(0){ // A()函数体不会被执行到 cout << "A()body" << endl; } A::A(int i) try : A(i, 0){ cout << "A(int i) body"<< endl; // 抛出异常,对象 a 将被析构 throw 1; } catch(...) { cout << "A(int i) catch"<< endl; } A::A(int i, int j){ num1=i; num2=j; average=(num1+num2)/2; cout << "A(int i, int j) body"<< endl; } A::~A(){ cout << "~A() body"<< endl; } int main(){ A a; return 0; } |
该例的输出为:
A(int i, int j) body
A(int i) body
~A() body
A(int i) catch
3、委派构造函数和泛型编程
其实,委派构造函数除了可以使程序员规避构造函数里重复的代码外,还可使构造函数的泛型编程变得更加容易,比如下面这个例子:
程序源代码 (generic.cpp)
#include <iostream> using namespace std; template<typename T> class A{ public: A(int i): A(i, 0){} A(double d): A(d, 0.0){} // 函数模板 A(T i, T j) { num1=i; num2=j; average=(num1+num2)/2; cout << "average=" << average << endl; } private: T num1; T num2; T average; }; int main(){ A<int> a_int(1); A<double> a_double(1.0); } |
该例的输出为:
average=0
average=0.5
上面这段代码中,目标构造函数为函数模板,它在被委派构造函数调用的时候才被实例化,非常方便,无需开发人员再写同类型的目标构造函数。
总结
通过上面的例子,相信大家对C++11委派构造函数具体使用都有了一定的了解和认识。利用C++11 的这个特性可以提高程序的可读性和可维护性,提高开发人员的开发效率。虽然委派构造函数的调用是可能会需要一些系统开销,但是大家还是可以尝试使用。