构造函数是特殊的成员函数,只要创建类类型的新对象,都要执行构造函数,定义对象指针不会调用构造函数。
创建类类型的新对象时,编译器为对象分配内存空间,完成后自动调用构造函数初始化对象的数据成员。
构造函数的主要工作是初始化对象的数据成员。
0、构造函数的特点
(1)、构造函数与类同名
(2)、构造函数没有返回类型
(3)、构造函数可以重载,一个类声明的构造函数的数量没有限制
(4)、构造函数由系统自动调用,不允许显示调用
(5)、构造函数应声明为类的公有成员
(6)、构造函数像其他任何函数一样,可以没有形参,也可以定义多个形参
(7)、构造函数不能声明为常成员函数(fun(...)const{}),可以声明为inline(内联)函数
1、无参构造函数
1.1、默认构造函数
只有当一个类没有定义构造函数时,编译器才会自动生成一个默认构造函数。
这条规则的根据是,如果一个类在某种情况下需要控制对象初始化,则该类很可能在所有情况下都需要控制。
1.2、所有参数都有默认值的构造函数
如果显式定义了无参数的构造函数,又定义了所有参数都有默认值的构造函数,那么定义对象时会产生二义性,
也不可以定义定义对象数组(VC6.0下可以定义对象数组,调用的是无参构造函数)。
#include <iostream>
using namespace std;
class Example
{
public:
Example(){cout<<"The Constructor without parameter"<< endl;}
Example(int nu = 0){num = nu; cout << "The Constructor with default all value default parameter" << endl;}
private:
int num;
};
int main(void)
{
Example ex; //error : call of overloaded ‘Example()’ is ambiguous
Example exarr[2]; //error : call of overloaded ‘Example()’ is ambiguous
return 0;
}
2、带参数的构造函数
构造函数可以重载,所以构造函数的行参多种多样。注意下例中注释掉的2个函数 和 第二个函数不能形成重载关系。
class Example
{
public:
Example(int im){m = im;}
Example(int im, int in){m = im; n = in;}
// Example(int im, int in = 0){m = im; n = in;}
// Example(int im = 0, int in = 0){m = im; n = in;}
private:
int m;
int n;
};
缺省参数的规则见:http://www.cnblogs.com/LubinLew/p/DefaultParameters.html
3、拷贝构造函数
3.1、调用拷贝构造函数的情形
class X{...};
//1
X obj1,
X obj2(obj1); //一个对象用于另一个对象的初始化
X obj3(obj2); //一个对象用于另一个对象的初始化
//2
X func1(...){} //函数返回对象,linux下可能不掉用拷贝构造函数
//3
... func2(X obj...){...} //函数有对象参数
//4
X func3(X obj){...} //调用2次拷贝构造函数
3.2、定义拷贝构造函数的原则
3.3、举例
注意:在linux下,函数返回类的对象时,不调用拷贝构造函数
#include <iostream>
using namespace std;
class Example
{
public:
Example(){m = 0; cout << "Default Constructor" << endl;}
Example(const Example& ref){m = ref.m;cout << "Copy Constructor"<<endl;}
Example& operator=(const Example& ref){m = ref.m; cout << "Overload Operator =" << endl;return (*this);}
void SetData(int n){m = n;}
void display(void){cout << m << endl;}
private:
int m;
};
Example Func1(void)
{
Example ex; //Default Constructor
ex.SetData(5);
return ex;
}
void Func2(Example ex){}
Example Func3(Example ex)
{
return ex;
}
int main(void)
{
Example ex1; //Default Constructor
cout << ">>>Init" << endl;
Example ex2(ex1); //Copy Constructor
Example ex3 = ex1; //Copy Constructor
cout << ">>>Func1 <1>" << endl;
Func1();
cout << ">>>Func1 <2>" << endl;
Example ex4 = Func1();
ex4.display();
cout << ">>>Func2" << endl;
Func2(ex3); //Copy Constructor
cout << ">>>Func3" << endl;
Func3(ex4); //Copy Constructor
cout << ">>> = " << endl;
ex3 = ex1;
return 0;
}
4、初始化列表(constructor initializer list)
指定类的数据成员的初始值。在构造函数体现执行前,用初始化列表中指定的值初始化成员。
没有在初始化列表中初始化的类成员,使用它们的默认构造函数隐式初始化。
#include <iostream>
using namespace std;
class Base
{
public:
Base(int x){m = x;cout << "Base::Constructor" <<endl;}
void display(void)const{cout << "m = " << m << endl;}
private:
int m;
};
class Example
{
public:
Example(char c, int i, int x):ch(c), ival(i), bs(x)
{cout << "Example::Constructor" <<endl;}
const Base& GetBase(void){return bs;}
private:
char ch;
int ival;
Base bs;
};
int main(void)
{
Example ex(‘A‘, 1, 2);
ex.GetBase().display();
return 0;
}
5、构造函数的调用顺序
http://www.cnblogs.com/LubinLew/p/Cpp-CallOrderOfConstructorAndDeconstructor.html