C++构造函数
构造函数是特殊的成员函数,只要创建类类型的新对象,都要执行构造函数,定义对象指针不会调用构造函数。
创建类类型的新对象时,编译器为对象分配内存空间,完成后自动调用构造函数初始化对象的数据成员。
构造函数的主要工作是初始化对象的数据成员。
0、构造函数的特点
(1)、构造函数与类同名
(2)、构造函数没有返回类型
(3)、构造函数可以重载,一个类声明的构造函数的数量没有限制
(4)、构造函数由系统自动调用,不允许显示调用
(5)、构造函数必须声明为类的公有成员(否则会编译出错,VS提示构造函数不可访问,g++提示构造函数是私有的)
(6)、构造函数像其他任何函数一样,可以没有形参,也可以定义多个形参
(7)、构造函数不能声明为常成员函数(fun(...)const{}),可以声明为inline(内联)函数
1、无参构造函数
1.1、默认构造函数
只有当一个类没有定义构造函数时,编译器才会自动生成一个默认构造函数。
这条规则的根据是,如果一个类在某种情况下需要控制对象初始化,则该类很可能在所有情况下都需要控制。
1.2、所有参数都有默认值的构造函数
如果显式定义了无参数的构造函数,又定义了所有参数都有默认值的构造函数,那么定义对象时会产生二义性, 导致编译错误。
#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;
Example exarr[2];
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)
指定类的数据成员的初始值。在构造函数体现执行前,用初始化列表中指定的值初始化成员。
没有在初始化列表中初始化的类成员,使用它们的默认构造函数隐式初始化。静态成员变量不能使用初始化列表初始化,也不能在构造函数中赋值.
必须用到初始化成员列表的四种情况:
1) 初始化一个引用成员
2) 初始化一个const成员
3) 基类没有默认构造函数和无参构造函数
4) 类中有一个类对象数据成员,并且对象的类没有默认构造函数和无参构造函数.
#include <iostream> using namespace std; class Base { public: Base(int n):num(n){cout<<"Base Constructor("<<n<<")"<<endl;} private: int num; static int stn;//cannot initialize static class data via constructor }; int Base::stn = 0; class Derived:public Base//④基类(没有默认构造函数和无参构造函数) { public: Derived(int i, int n, Base& bref, int& ire, int ibs):ival(i),bs(n),bsref(bref),iref(ire),Base(ibs) {cout<<"Derived Constructor"<<endl;} private: const int ival; //①const数据成员 Base bs; //②类成员对象(没有默认构造函数和无参构造函数) Base& bsref; //③引用(对象的引用) int& iref; //③引用(普通数据类型引用) }; int main() { int i = 10; Base bs(1); Derived(1,2, bs, i, 3); return 0; }
5、构造函数的调用顺序
http://www.cnblogs.com/LubinLew/p/Cpp-CallOrderOfConstructorAndDeconstructor.html