作者:gnuhpc
出处:http://www.cnblogs.com/gnuhpc/
1.在子类构造时完成父类(没有默认构造函数)的初始化参数传入:
#include <iostream>class Foo
{public:
Foo( int x )
{std::cout << "Foo's constructor "
<< "called with "
<< x<< std::endl;}};class Bar : public Foo{public:
Bar() : Foo( 10 ) // construct the Foo part of Bar
{std::cout << "Bar's constructor" << std::endl;
}};int main()
{Bar stool;}
2.初始化const成员和reference成员
#include <iostream>using namespace std;class const_field
{public:
const_field(int ii) : _constant( 1 ),ref( i ) { i=ii; }
int geti(){return i;}int getref(){return ref;}private:
const int _constant;int &ref;
int i;
};int main()
{const_field cos(100);cout << cos.geti() <<" " << cos.getref()<<endl;
}
注:初始化列表在构造函数函数体运行之前完成,在构造函数函数体运行中,数据成员的设置是赋值,而不是初始化。初始化阶段可以是显式或隐式的,这要取决于类成员的类型,对于built-in成员其实都一样,但是对于类成员,是否存在成员初始化表则有所不同:若不存在则是隐式初始化,按照声明的顺序依次调用所有类成员函数所属基类的默认构造函数(见后边的练习),在函数体内有赋值动作调用赋值构造函数。若存在则属于显式初始化,类成员使用复制构造函数完成初始化,这也就是我们有时会说在初始化列表中初始化开销会小些的原因(因为若在函数体内再赋值,那么类成员函数的默认构造函数执行所做的工作都是无用功),例如:
Account(){
_name = “”:
_balance=0.0;
}
这里面的string型的_name在赋值前已经被初始化阶段隐式初始为空串(调用了string的默认构造函数),所以在函数体中的赋值是完全没有意义的。
总之,建议使用初始化列表(注意是按照成员声明顺序,而不是列表顺序)来做对象创建时初始化工作。
初始化顺序为:
- 基类
- 成员数据成员(初始化列表)
- 构造函数函数体
附:练习
#include <iostream>using namespace std;class Test{public:Test(){ctor_count++;cout<<"ctor "<<ctor_count<<endl;
}Test(const Test & r){ctor_count++;cout<<"copy ctor "<<ctor_count<<endl;
}Test & operator= (const Test& r){ctor_count++;cout<<"assignment op "<<ctor_count<<endl;
return *this;}private:static int ctor_count; //only a declaration
};int Test::ctor_count=0; // definition + initialization
class Task{private:int pid;Test name; // type changed from string to Test
public:Task (int num, const Test & n) {pid=num; name=n;}};int main(void){Test t;Task task(1, t);return 0;}
运行结果:
[root@localhost ~]# ./a.outctor 1ctor 2assignment op 3
解释:static int是为了更好的说明问题,不要被这个类型所迷惑。第一行表示程序在构造t。第二行表示默认初始化时调用默认构造函数,第三行是构造task时的赋值。
将程序的初始化修改:
Task (int num, const Test & n):pid(num),name(n) {}
运行结果是:
ctor 1
copy ctor 2
下边的这个程序也可以说明问题,如果还不理解上例的话:
#include <iostream>using namespace std;class Bar
{public:
Bar();Bar(int x);
Bar & operator=(const Bar& bar){cout <<"Assignment Bar constructed." <<endl;
}Bar(const Bar &bar)
{cout <<"Copy Bar constructed." <<endl;
}private:
int x;
};Bar::Bar(){std::cout << "Bar default-constructed." << std::endl;
}Bar::Bar(int x) : x(x)
{std::cout << "Bar constructed." << std::endl;
}class Foo
{public:
Foo(Bar bar);private:
Bar bar;};Foo::Foo(Bar bar){this->bar = bar;
}//Foo::Foo(Bar bar):bar(bar){}
int main()
{Foo foo(Bar(3));return 0;
}