C++构造函数

C++中构造函数是特殊的成员函数,只要定义类的新对象就会执行构造函数,构造函数是保证每个对象的数据成员具有合适的初始值。

构造函数特点:

1)构造函数与类同名,不能指定返回类型,且不能声明为const函数,详见你所不知道的 const

2)构造函数可以重载,所以可以有多个构造函数

	sales_item(void) /*const*/;
	sales_item(istream &is /*= cin */);
	sales_item(const string & book ); //must const 	
	sales_item(const sales_item &org);

3)调用构造函数,使用不同的实参就会调用不同的构造函数,如下

	sales_item sales0;
	sales_item sales1("hello world");  
	sales_item("hello world"); //也可以
	sales_item sales2 = sales_item("123456"); //定义
	sales_item sales3(cin);

构造函数的初始化式:

函数后面可以包含一个初始化列表,原型为形参后紧跟一个冒号,然后就是以逗号分开的数据成员列表,初始化值放在圆括号内,如下

sales_item::sales_item(void)
	: isbn(1,'0'), units_sold(0), revenue(0.0), a(0), b(a){}
初始化注意之处:

1)构造函数分两阶段进行,初始化阶段和普通的计算阶段(计算阶段就是函数体中的语句或者称为赋值阶段)

2)未提供显式初始化的变量使用与初始化变量相同的规则进行初始化,内置或者复合类型依赖于对象的作用域,局部不初始化全局初始化为0,类类型使用默认的构造函数

3)必须提供初始化列表的情况,如下

screen::screen(void)//contents由string默认构造函数初始化
	: nConstVar(0)/*contents("")*/,cursor(0),height(0),width(0),access_ctr(0){}
const int nConstVar; //必须在直接初始化列表进行初始化,如果在函数体中就会出错,还有就是引用的初始化,如下
sales_item::sales_item(void)
	: isbn(1,'0'), units_sold(0), revenue(0.0), a(0), b(a){}
int &b; b一定要显式初始化

4)成员初始化的次序

class x {
	int i;
	int j;
public:
	x(int val):j(val), i(j){};
};
这里我在vs2012编译下通过了,显式初始化次序对这个没有影响,在gcc version 4.4.1使用g++编译同样通过。但是在vs2012调试后发现,i=-858993460,j=1 也就是说其实i并没有提供的j的值初始化,所以最好严格按照初始化顺序初始化,尽可能避免使用成员来初始化,最好统一使用形参来进行初始化。

5)类类型的初始化可以使用该类型的任意构造函数,也可以使用默认的构造函数。

6)类成员的显示初始化,直接初始化成员也是可以的,但是必须满足一下几点

a. 类的全体成员必须是public

b. 没有定义构造函数

如下:

	struct init
	{
		int ival;
		char * ptr;
	};
	init initval = {1, NULL};

默认实参:

1)可以为构造函数提供默认的实参,但是这个形参后面的所有形参必须提供默认值,所以需要合理调整形参的位置。

2)另外默认值只能提供在类声明的位置处,不能在定义处提供,否则编译会出错。如下

class y
{
public:
	y(ifstream &ifs, const string &str = ""):strVal(str), nVal(0), dVal(NULL), ifsVal(ifs){};
	~y(){};

private:
	const string strVal;
	int nVal;
	double* dVal;
	ifstream& ifsVal;
};
3)可以有默认值,但是提供默认值后有些需要合并的函数就需要删除,不能出现调用时出现歧义,如下

	sales_item(void) /*const*/;
	~sales_item(void);
	sales_item(istream &is = cin );
	sales_item(const string & book = "" ); //must const 	

这里就会发现,如果调用sale_item默认不带形参的构造函数就会出现歧义,不知该调用哪个

默认构造函数:

1)合成的默认构造函数,一个类哪怕只定义一个构造函数,编译器就不会生成合成默认构造函数

2)合成的默认构造函数使用与变量初始化相同的规则来初始化成员,如果类包含内置类型或者复合类型的成员,则该类不应该依赖于合成的默认构造函数。

3)类通常应该定义一个默认构造函数,只要定义了其他构造函数,提供默认构造函数总是对的

4)使用默认构造函数时,切记不可写成如下的形式

sales_item item();

这种写法是错误的,因为这里其实声明的item是函数,返回类型是sales_item,但是下面是允许的

    sales_item item1 = sales_item(); //定义
或者

   sales_item* item2 = new sales_item();

隐式转转:

当调用构造函数的时候,如果对形参没有特别说明,就有可能发生隐式转换,如下

	const string book = "9-99-9999";
	item.same_ishn(book);
这里就将string转换为sales_item类类型,但是有时候却需要抑制这种转化,如下

	explicit sales_item(void); // 防止隐式转换

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章