在构造函数中调用另一个构造函数如果一不注意就会有无限递归的危险,而且构造函数的参数的不同也决定了调用的不同,所以特意总结了一下哪些形式的调用时允许的:
首先假设构造函数调用时参数都是外部的变量,而不是一个常量。
第一种,也是C++11支持的一种调用方式。在函数的初始化列表中调用另一个构造函数:
int b = 2;class Test{public:Test() : Test(b) {} //在初始化列表调用Test(int a)Test(int a) : p(a) {}~Test() {}int get() { return p; }private:int p;};
第二种,用this指针显示调用构造函数:
int b = 2;class Test{public:Test(){this->Test::Test(b);//通过this指针显式调用Test(int a)}Test(int a) : p(a) {}~Test() {}int get() { return p; }private:int p;};
这种方法一定不能忘记加上作用域,不然编译无法通过!
第三种,在原始内存覆盖:
int b = 2;class Test{public:Test(){new (this) Test(b);}Test(int a) : p(a) {}~Test() {}int get() { return p; }private:int p;};
使用new (void*p) Type(...),这种语句的意思是不重新分配内存,而是直接覆盖在原内存上。就本例而言,定义一个Test类型的变量覆盖在this地址指向的内存上。
上述三种都在对this指向的对象进行操作,如果是想在构造函数中定义一个同类型的变量,需要使用花括号而不是圆括号传参:
int b = 2;class Test{public:Test(){Test{ b };//使用花括号{}}Test(int a) : p(a) {}~Test() {}int get() { return p; }private:int p;};
另一种方法是显式指出类型:
int b = 2;class Test{public:Test(){Test((int)b);//显式指出类型}Test(int a) : p(a) {}~Test() {}int get() { return p; }private:int p;};
这两种都不会无限递归,但是只是创建了一个局部变量,构造函数结束的时候这个局部变量会被销毁。
另外需要注意的是,如果把变量b换成常量2,使用Test(2)不用造成无限递归,会正确执行。
如果编译器支持C++11,那么比较推荐的方法是使用初始化列表来调用其它构造函数。