多层派生:
有一个基类A,派生出派生类B,然后再将派生类B派生出派生类C,.....,形成派生的层次结构。下面通过一个例子,讲一下对基类和两个派生类构造函数的写法:
例1.
#include <iostream>
#include <string>
using namespace std;
class Student
{
public:
Student(int n,string nam) //基类构造函数
{
num=n;
name=nam;
}
~Student(){}
void display()
{
cout<<"num:"<<num<<endl;
cout<<"name:"<<name<<endl;
}
protected:
int num;
string name;
};
class Student1:public Student
{
public:
Student1(int n,string nam,int a):Student(n,nam) //派生类构造函数名:基类构造函数名
{
age=a;
}
~Student1(){}
//void dispaly() //多层派生中,注意函数名
void show()
{
display();
cout<<"age:"<<age<<endl;
}
private:
int age;
};
class Student2:public Student1
{
public:
Student2(int n,string nam,int a,int s):Student1(n,nam,a) //派生类构造函数:上一层派生类(直接基类)构造函数名
{
score=s;
}
~Student2(){}
void show_all()
{
//display(); //多层派生中,注意函数名,如果都写一样的函数名,调用display函数时,会直接跳到基类,而不是上一层派生类
show();
cout<<"score:"<<score<<endl;
}
private:
int score;
};
int main()
{
Student2 stu(10010,"wang_li",19,100);
stu.show_all();
return 0;
}
注意基类和两个派生类的写法:
基类构造函数的首部:
Student(int n,string nam)
派生类Student1的构造函数的首部:
Student1(int n,string nam,int a):Student(n,nam)
派生类Student1的构造函数的首部:
Student2(int n,string nam,int a,int s):Student1(n,nam,a)
注意不要写成:
Student2(int n,string nam,int a,int s):Student(n,nam),Student1(n,nam,a)
不要列出每一层的派生类的构造函数,只需写出其上一层派生类(即它的直接基类)的构造函数即可。
因为在声明Student2类对象时,调用Student2构造函数;在执行Student2构造函数时,先调用Student1构造函数;在执行Student1构造函数时,先调用基类Student构造函数。
所以初始化顺序是:
num->name->age->score.
虚基类:
如果在多重继承中,一个派生类有多个直接基类,而这些直接基类又有一个共同的基类,则在最终的派生类中会保留该间接共同基类数据成员的多份同名成员。为了解决这个问题,C++提供了虚基类的方法,使得在继承间接共同基类时,只保留一份成员。
声明虚基类的一般形式:
class 派生类:virtual 继承方式 基类名
例2.虚基类的简单应用举例
#include <iostream>
#include <string>
using namespace std;
class Person
{
public:
Person(string nam,char s,int a)
{
name=nam;
sex=s;
age=a;
}
protected:
string name;
char sex;
int age;
};
class Teacher:virtual public Person //声明Person为公用继承的虚基类
{
public:
Teacher(string nam,char s,int a,string t):Person(nam,s,a) //构造函数
{
title=t;
}
protected:
string title;
};
class Student:virtual public Person //声明Person为公用继承的虚基类
{
public:
Student(string nam,char s,int a,float sco): //构造函数
Person(nam,s,a),score(sco){}; //初始化表
protected:
float score;
};
//声明多重继承的派生类Graduate
class Graduate:public Teacher,public Student //Teacher和Student为直接基类
{
public:
Graduate(string nam,char s,int a,string t,float sco,float w): //构造函数:对直接基类和虚基类都要初始化
Person(nam,s,a),Teacher(nam,s,a,t),Student(nam,s,a,sco),wage(w){}
void show()
{
cout<<"name:"<<name<<endl; //与非基类虚继承的区别
cout<<"age:"<<age<<endl;
cout<<"sex:"<<sex<<endl;
cout<<"score"<<score<<endl;
cout<<"title:"<<title<<endl;
cout<<"wage:"<<wage<<endl;
}
private:
float wage;
};
int main()
{
Graduate grad1("wang_li",'f',24,"assistant",89.5,1234.5);
grad1.show();
return 0;
}
注意:在虚基类中定义了带参的构造函数,而且没有定义默认构造函数,则在其所有派生类(包括直接派生类或间接派生类的派生类中)中,通过构造函数初始化表对虚基类进行初始化,例1中,派生类构造函数只需负责对其直接基类初始化,再由其直接基类负责对间接基类初始化。而例2中,由于虚基类在派生类中只有一份数据成员,所以这份数据成员的初始化必须由派生类直接给出。所以最后的派生类中不仅要负责对其直接基类进行初始化,还要负责对虚基类初始化。