分类: C/C++
2016-06-12 11:13:58
原文地址:【总结】C++类的继承与派生 作者:zollty
1. 一个包含多级派生/构造、析构函数的综合实例:
#include
using namespace std;
class A
{
public:
A(int ai, int aj, int ak) //3个参数的构造函数
{
i=ai;
j=aj;
k=ak;
};
~A(){cout<<"destructing A\n";} //析构函数,关于析构函数只做简单介绍
void f1()
{
cout<<"hello f1\n";
}
int i;
protected:
void f2()
{
cout<<"hello f2\n";
}
int j;
private:
int k;
};
class B: public A //定义公用派生类B
{
public:
B(int ai, int aj, int ak, int bm, int bn):A(ai, aj, ak) //多级派生类的构造函数的定义方式
{
m=bm; //也可以用参数表的形式A(ai, aj, ak), m(bm), n(bn){}
n=bn;
};
~B(){cout<<"destructing B\n";}
void f3()
{
cout<<"hello f3\n";
}
protected:
int m;
private:
int n;
};
class C: public B
{
public:
C(int ai, int aj, int ak, int bm, int bn, int cp):B(ai, aj, ak, bm, bn)
{
p=cp;
};
~C(){cout<<"destructing C\n";}
void f4()
{
f3();
cout<<"hello f4\n";
}
private:
int p;
};
int main()
{
A a1(0,0,0); //初始化
B b1(1,1,1,0,0);
C c1(2,2,2,1,1,0);
c1.f3(); //注意分析派生类继承的成员函数的调用权限
//cout<
return 0;
}
多级派生的权限总结:
public:public公用继承后仍是public权限,保护继承后变为protected权限,私有继承后是private权限。
protected:protected公用继、保护承后仍是protected权限。以此类推…
特别说明:protected的意思是在class内部才能使用,不能外部调用,比如class A一个protected数据j,不能用a1.j去调用,要使用j必须在class A内定义一个成员函数去调用。
另外对于派生类对象的释放,先执行派生类的析构函数,在执行其基类的析构函数。本例中执行析构函数依次为:
C, B, A //释放c1空间
B, A //释放b1空间
A //释放a1空间
2. 上例中没有包含类子对象,派生类函数子对象的构造函数写法如下:
Student1(int num, string name, int num1, string name1 ):Student(num, name), monitor(num1, name1){} //monitor为Student类类型,构造函数初始化时传入参数即可
3. 多重继承派生的构造函数,写法如下:
class Graduate: public Teacher, public Student //一名研究生既是教师又是学生,引进两个基
{
public:
Graduate(string nam, int a, char s, string t, float sco, float w):
Teacher(nam, a, t), Student(nam, s, sco), wage(w){ } //一些参数是共用的
……
};
4. 虚基类
如果一个派生类有多个直接基类,而这些直接基类又有一个共同的基类,则在最终的派生类中会保留该间接共同基类数据成员的多份同名成员。如下图所示。引用这些同名成员时,必须在派生类对象名后增加直接基类名,以避免产生二义性,使其唯一地标识一个成员,如c1.A::display()。
C++提供虚基类(virtual base class)的方法,使得在继承间接共同基类时只保留一份成员。例如:
class Person //共同基类
{
public:
Person(string nam, char s, int a)
{…}
……
};
class Teacher: virtual public Person //将Person引入为虚基类
{
public:
Teacher(string nam, char s, int a, string t): Person(nam, s, a), title(t){}
……
};
class Student: virtual public Person //将Person引入为虚基类
{
public:
Student (string nam, char s, int a, float sco): Person(nam, s, a), score(sco){}
……
};
class Graduate: public Teacher, public Student //引入两个直接基类
{
public:
Graduate(string nam, int a, char s, string t, float sco, float w):
Person(nam, s, a), Teacher(nam, s, a, t), Student(nam, s, a, sco), wage(w){} //注意此时还要包含Person,与小节3的例子不同
……
};
5. 基类与派生类的转换
派生类可以直接赋值给基类,反过来不行。例如
Student a1(…);
Graduate b1(…);
Student &a2 = a1; //定义基类对象的引用a2,并用a1对其初始化
a2 = b1; //可以直接将b1赋值给a2
6. 继承与组合
在一个类中以另外一个类的对象作为数据成员,称为类的组合。例如:
class Teacher
{…}
class BirthDate
{…}
class Professor: public Teacher
{
public:
…
private:
BirthDate birthday; //BirthDate类的对象作为数据成员
}
可见通过继承Teacher引进成员和通过组合引进成员,都能有效地利用已有类的资源。不同的是,继承是包含关系,而组合是属性关系。