前言对一个类而言,构造函数恐怕是最重要的一个成员函数了。关于构造函数的细节繁多,并且随着新标准的提出,构造函数有了新的特性。本文来集中探讨下构造函数的那些鲜为人知的一面。
构造函数构造函数的作用众所周知:在类的对象被创建时,控制对象的初始化和赋值。
构造函数的一般形式:类名(arg_list);其中arg_list是用逗号隔开的参数列表。特点:无返回值类型,且不可加const限制。
默认构造函数需要特别指出,无参的构造函数是默认的,有参但都有默认参数的构造函数也是默认构造。------------------------------分割线------------------------------
C++ Primer Plus 第6版 中文版 清晰有书签PDF+源代码 http://www.linuxidc.com/Linux/2014-05/101227.htm读C++ Primer 之构造函数陷阱 http://www.linuxidc.com/Linux/2011-08/40176.htm读C++ Primer 之智能指针 http://www.linuxidc.com/Linux/2011-08/40177.htm读C++ Primer 之句柄类 http://www.linuxidc.com/Linux/2011-08/40175.htm
将C语言梳理一下,分布在以下10个章节中:- Linux-C成长之路(一):Linux下C编程概要 http://www.linuxidc.com/Linux/2014-05/101242.htm
- Linux-C成长之路(二):基本数据类型 http://www.linuxidc.com/Linux/2014-05/101242p2.htm
- Linux-C成长之路(三):基本IO函数操作 http://www.linuxidc.com/Linux/2014-05/101242p3.htm
- Linux-C成长之路(四):运算符 http://www.linuxidc.com/Linux/2014-05/101242p4.htm
- Linux-C成长之路(五):控制流 http://www.linuxidc.com/Linux/2014-05/101242p5.htm
- Linux-C成长之路(六):函数要义 http://www.linuxidc.com/Linux/2014-05/101242p6.htm
- Linux-C成长之路(七):数组与指针 http://www.linuxidc.com/Linux/2014-05/101242p7.htm
- Linux-C成长之路(八):存储类,动态内存 http://www.linuxidc.com/Linux/2014-05/101242p8.htm
- Linux-C成长之路(九):复合数据类型 http://www.linuxidc.com/Linux/2014-05/101242p9.htm
- Linux-C成长之路(十):其他高级议题
举例证明:#include <iostream>
using namespace std;class MyClass
{
protected:
int a = 0;
int b{1};
public:
MyClass(int a = 0, int b = 0):a(a), b(b) //有默认实参的构造方法就是默认构造
{
cout << "MyClass(int a = 0, int b = 0)" << endl;
} int getA()const
{
return a;
}
int getB()const
{
return b;
}
};
int main()
{
MyClass my; //调用默认构造
cout << "a = " << my.getA() << ends << "b = " << my.getB() << endl;
cin.get();
return 0;
}运行从运行结果,即可验证结论。有参但都有默认参数的构造函数也是默认构造,这一点恐怕是很多人都容易忽略的、默认构造初始化类的数据成员的规则:如果存在类内的初始值,用它来初始化成员。否则,默认初始化。(这个规则虽是标准,但大多数编译器还做不到)几个概念1.类内初始值。在上例代码中,int a = 0; int b{1};这种形式就是类内初始值。后面会说明何时使用类内初始值。2.默认初始化。内置类型,如int,double类型等。int->0,double->0.0。就是默认初始化。类类型,使用该类的默认构造初始化,就是默认初始化。默认构造并不是总是存在的,若有另一个构造函数(非默认构造)存在,则编译器并不会提供一个无参的默认构造。新标准提出了一种方式:如 MyClass() = default; 关键字 default 的这种使用,表明要求编译器生成一个默认的构造函数。3.初始值列表构造函数 MyClass(int a = 0, int b = 0):a(a), b(b){...} 其中 a(a), b(b)就是初始值列表。4.什么是初始化?什么是赋值?对象在内存中创建(有了内存实体),第一次有的值,叫做初始化。把原先的值覆盖掉,叫做赋值。一般情况下,构造函数在初始值列表中完成初始化,在函数体中完成赋值。这个结论并不好证明,但还是有办法的,办法就是借助:const类型和引用类型。如下代码:#include <iostream>
using namespace std;class MyClass
{
protected:
int a = 0;
const int ca = 0;
int& ra;
public:
MyClass(int a) :a(a), ca(a), ra(this->a){}
int getA()const
{
return a;
}
void printCa()const
{
cout << "ca = " << ca << endl;
}
void printRa()const
{
cout << "ra = " << ra << endl;
}
};
int main()
{
MyClass my(1);
cout << my.getA() << endl;
my.printCa();
my.printRa();
cin.get();
return 0;
}运行const类型和引用类型,在创建时,必须进行初始化。若是把 ca = a; ra = this->a; 移到构造函数体内部,则无法通过编译。也就是说,一旦进入构造函数体,初始化就已经完成了。需要指出,初始值列表的顺序并不代表着实际初始变量的顺序,而成员的声明顺序才是。
更多详情见请继续阅读下一页的精彩内容: http://www.linuxidc.com/Linux/2015-02/113672p2.htm