说不完的构造函数,呵呵。构造函数一个特殊的成员函数,只要对于一个类,实例化一个对象,那么就必须执行构造函数。构造函数的目的很简单,就是保证 类的对象的每个数据成员,都具有一个合适的初始化值。
构造函数可以是被重载的,而实例化对象的时候,这个对象的实参决定调用哪个构造函数。只要实例化一个对象,此对象的构造函数就自动的开始执行。
构造函数不能够声明为const,因为这个是不必要的。无论对象是否为const,都是用一个构造函数来初始化对象。
构造函数初始化式与构造体内赋值的对比和区别:
譬如一个类:
class Tree
{
public:
Tree(string node,int i,int j){this->node=node;this->i=i;this->j=j;}
//Tree(int i,int j):node(node),i(i),j(j){}
private:
string node;
int i;
int j;
......
};
下面我们详细的分析一下,构造体赋值的构造函数执行过程:
1)不管有没有显示初始化,在执行构造函数之前,系统都要调用string 对象node的默认构造函数(系统自动合成一个默认构造函数给node对象),对node进行初始化。然后,这个node对象才会在函数体内被赋值所替代。
2)以上过程可以被简要概括为:数据成员初始化,执行被调用构造体内的赋值操作
如果是用构造函数初始化式,直接调用string类的复制构造函数对node对象进行显示初始化操作。
可见,这样节约了时间和效率。
另外,都什么情况下,必须需要构造函数初始化式呢?
A如果函数定义了构造函数,那么,系统将不会自动合成一个默认的构造函数,编译器尝试是用默认的构造函数失败,这样情况下,必须使用初始化式。
例如:
class Tree
{
public:
//Tree(string node,int i,int j){this->node=node;this->i=i;this->j=j;}
Tree(int i,int j):node(node),i(i),j(j){}
private:
string node;
int i;
int j;
......
};
Tree tree; 如果没有构造函数初始化式,这样就会初始化失败。
B。引用和const成员变量必须采用构造函数初始化式
如此而已。
class Tree
{
public:
//Tree(string node,int i,int j){this->node=node;this->i=i;this->j=j;}
Tree(int i,int j):i(i),j(i),k(j){}
private:
//string node;
int i;
int &j;
const int k;
......
};
C。什么情况下构造函数初始化列表和构造体内赋值效率一样呢?
答:内置变量类型
构造函数初始化列表的初始化次序:
一般说来,初始化次序可以随意,但是如果用一个成员根据另外一个成员初始化,那么就容易出现以下问题了:
class X{
int i,j;
public:
X(int k,int t):j(k),i(j){}
};
i先被初始化,用未初始化的j来初始化i,会出现难以预料的错误。
一定要记住:
1)一个类哪怕只定义了一个构造函数,系统也不会再给他合成一个默认构造函数。
2)具有类类型的成员通过默认构造函数初始化。而内置和复合类型,如指针和数组,
则只对定义在全局作用域中的对象才初始化,局部作用域中不进行初始化。
类如果不定义默认构造函数,会出现一定的问题:
1)不能用作动态分配数组的元素类型。
2)静态分配数组必须显示初始化
3)vector不能使用接受容器大小而没有同时提供一个元素初始化式的构造函数。