一、简单派生类的构造函数
1.所谓简单派生类,就是指派生类中不包含基类的内嵌对象的派生类。
2.一般来说,这样的派生类的构造函数的形式是:
student( int i, string nam, int sid) : person( i, nam) { stuid = sid; }
person(是基类的初始化列表)
3.构造函数的初始化列表的使用
3.1所有的构造函数都可以拿参数的初始化表来构造完全属于自己的数据成员(其实本质上参数的初始化列表里只能出现两种东西,下文会总结),比如:
#include <iostream>
using namespace std;
class A
{
public:
A(int a) :dataA(a){ cout << "调用A的构造函数" << endl; }
private:
int dataA;
};
void main()
{
A a();
}
3.2但是一定要注意派生类在构造基类成分的时候不能直接使用参数的初始化表(其实本质上参数的初始化列表里只能出现两种东西,下文总结)
B(int b, int a) :dataA(a), dataB(b){ cout << "调用B的构造函数" << endl; }//错误!!
这里一定要再次补充一点,之所以这里不能使用dataA(a)作为初始化的语句,而一定要强制使用基类的构造函数,其原因是基类的数据成员dataA在派生类里是无法访问的,而要使派生类中的基类成分赋值,就必须使用基类的构造函数。但是,倘若基类中的成员dataA我不使用private类型,我使用protected类型的数据,这样B公有继承A之后,dataA就仍然是protected类型,就可以在B类型中访问了,但是这个时候访问dataA的方式任然不能在初始化列表里进行。
捣弄dataA的过程中也是要遵守一些规则的:
#include <iostream>
using namespace std;
class A
{
protected:
int dataA;
int dataA2;
public:
A(int a) :dataA(a) { cout << "调用A的构造函数" << endl; }
};
class B :public A
{
int dataB;
public:
B(int a, int b) : dataB(b){ dataA = a; }
};
void main()
{
cout << "***************************" << endl;
cout << "CRAZY_HENRY的演示:" << endl<< endl;
B b(, );
}
上边的代码编译的时候会报错,在执行 B(int a, int b) : dataB(b){ dataA = a; }这句代码的时候,初始化列表中一定会调用一个基类A的无参构造函数,但是A类中没有定义无参构造函数,所以这句话一定会报错!
把代码改成这样:(加上第9句)
#include <iostream>
using namespace std;
class A
{
protected:
int dataA;
int dataA2;
public:
A(){}
A(int a) :dataA(a) { cout << "调用A的构造函数" << endl; }
};
class B :public A
{
int dataB;
public:
B(int a, int b) : dataB(b){ dataA = a; }
};
void main()
{
cout << "***************************" << endl;
cout << "CRAZY_HENRY的演示:" << endl<< endl;
B b(, );
}
上边这句话写成这样就又错了:
B(int a, int b) : dataB(b) ,dataA(a){}//错误!!!
很明显,放在初始化列表里的数据类型只能是(1)该类新增的数据成员(不包括基类的成员)和(2)基类的构造函数。
然后,再看看改了的代码:
#include <iostream>
using namespace std;
class A
{
private:
int dataA4;
protected:
int dataA;
int dataA2;
public:
A(){}
int dataA3;
A(int a) :dataA(a) { cout << "调用A的构造函数" << endl; }
};
class B :public A
{
private:
int dataB;
protected:
int dataB2;
public:
B(int a, int b, int c,int d,int e,int f) : dataA4(f),dataA3(e),dataA2(d),dataB(b), dataB2(c){ dataA = a; }//错误代码!!
};
void main()
{
cout << "***************************" << endl;
cout << "CRAZY_HENRY的演示:" << endl << endl;
B b(, , ,,,);
}
这里的错误有两个,一个是dataA4是基类的私有成员,无法在B中访问,自然不能写在B的初始化列表里;二是dataA3和dataA2虽然在B中访问权限一个是公有,一个是保护,但是他们并不是B的新增数据成员,所以不能在B的初始化列表里出现,但是可以在B的构造函数的函数体里出现!
所以,把代码改成这样:
B(int a, int b, int c, int d, int e) :dataB(b), dataB2(c){ dataA = a; dataA2 = d; dataA3 = e; }
3.3也不能把其他语句如输出语句写出来:
B(int b, int a) :A(a), dataB(b), cout << "调用B的构造函数" << endl{}//错误!!!!
3.4同时调用基类的构造函数和数据成员的初始化表是可以的
#include <iostream>
using namespace std;
class A
{
public:
A(int a) :dataA(a){ cout << "调用A的构造函数" << endl; }
private:
int dataA;
};
class B:public A
{
int dataB;
public:
B(int b, int a) :A(a), dataB(b) { cout << "调用B的构造函数" << endl; }
};
void main()
{
B b(, );
}
B(int b, int a) :A(a), dataB(b) { cout << "调用B的构造函数" << endl; }
这一行代码就是这样,dataB(b)提到初始化列表中去写,A(a)是基类的构造函数,这样显得很简洁。
而且代码的调用顺序和dataB(b)的位置无关,都是先初始化A(a),然后初始化dataB,最后执行函数体。
3.5然而这样写成这样是不可以的:
B(int b, int a) :A(a) {dataB(b);cout << "调用B的构造函数" << endl; }//错误!!
函数体中要用dataB=b;
B(int b, int a) :A(a), dataB = b { cout << "调用B的构造函数" << endl; }//错误!!
外边要用dataB(b);
这样才是正确的写法:
B(int b, int a) :A(a){ dataB=b; cout << "调用B的构造函数" << endl; }