一、C++类初始化顺序:基类,成员变量,构造函数。
二、成员变量初始化顺序按照定义顺序进行,而不是按照构造函数中初始化列表的顺序进行。定义某个变量时,会在初始化列表当中寻找是否为该变量该变量指定了初始值。
三、如果类定义存在虚基类,那么首先会初始化虚基类,且直接调用该虚基类的默认构造函数,即使虚继承该基类的子类构的造函数的初始化列表当中定义了初始化值,也不会初始化为该值。初始化虚基类后,才会初始化其他非虚继承的类。如下面这个例子:
#include <iostream>
using namespace std;
class A {
public:
A(int x=0) {
cout<<"A vir "<<x<<endl;
}
};
class B :public A{
public:
B():A(1) {
cout<<"B"<<endl;
}
};
class C :virtual public A{
public:
C():A(2) {
cout<<"C"<<endl;
}
};
class D :public B, public C {
public:
D() {
cout<<"D"<<endl;
}
};
int main() {
D d;
return 0;
}
上例运行结果为:
类B常规继承了A,类C虚继承了A,类D继承了B、C,运行结果显示虚继承的A被直接调用默认,而不是设置默认参数为2时的结果。初始化完虚基类后,继续将其他类初始化完毕。
虚继承中,只有当类B、C当中的A都为虚继承时,类A才会只初始化一次,上面的情况下,A仍然初始化了两次。
四、C++与C中不同的地方
1. 对于带空参数表的函数,如int func(),C语言中表示为“一个可带任意数目,任意类型的函数”,C++中表示“不带参数的函数”
2.C++仍然可以用从C继承下来的带有“.h”扩展名的头文件,也可以使用C++风格的写法,如“#include <stdio.h>”可写为"#include <cstdio>",这样就为读者提供了一个区分标志,说明是C库还是C++库。
3.名字空间和包含头文件的方法之间存在相互关系。现在头文件都标准化了(不带.h),过去典型包含头文件方式是带上.h,那时名字空间不是语言一部分。由于对已经存在的代码要向后兼容,如果给出
#include <iostream.h>
相当于
#include <iostream>
using namespace std;
使用不带.h的标准方式包含头文件,就必须加入using命令。
4.定义变量C只能在作用域开头定义,C++可以在作用域任意地方定义,即C++可以在要使用变量时才去定义,而不需要将定义写在最前面。
五、人们经常会把标准C++库的“容器”与“算法”和被称为STL的东西混淆。STL(标准模版类库)是1994年Alex Stepanov在加州San Diego的会议上把他的C++库提交给C++标准委员会时使用的名称,这个名称一直沿用下来。C++标准委员会对STL作了大量修改,将他整合进标准C++类库。SGI的STL与标准C++库在许多细节上是不同的。虽然人们常常产生误解,但实际上C++标准是不包括STL。标准C++库的“容器”和“算法”与SGI的STL有相同来源,因此容易引起误会。正确的称呼C++中vector、string的方法是“标准C++库”或“标准容器库”。
六、类一旦有了构造函数,创建类对象时就必须调用该构造函数。也就是说,如果一个类没有默认构造函数但有必须传递参数的构造函数,而创建这个类的对象时没有指定构造函数的参数值时,是无法通过编译器编译的,因为编译器会认为与构造函数参数列表不匹配。
七、类没有任何构造函数时编译器会自动生成一个构造函数,但生成函数的运行效果如何是无法保证的,所以对于任何一个类最好的方法是创建一个默认的构造函数。