// PaiShengAndDerive.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <string.h> class Teacher { public: Teacher(const char *s,int x,int n) { strcpy(MathTeaName,s); ClassRoom = x; TeaYear = n; printf("基类构造函数!\n"); } void display(); protected: char MathTeaName[20]; //数学老师名字 int TeaYear; private: int ClassRoom; //教室 }; void Teacher::display() { printf("%d\n",ClassRoom); printf("%s\n",MathTeaName); printf("%d\n",TeaYear); } /*派生类*/ class Student:public Teacher { public: /*派生类构造函数名(总参数表列): 基类构造函数名(参数表列),子对象名(参数表列)*/ /*Student(const char *s,int m,int n):Teacher("Li",50),Wang("Wang",45) 派生类的构造函数*/ Student(const char *s,int m,int n,int x,int years):Teacher(s,x,years),Wang(s,x,years) { strcpy(name,s); Math = m; Chinese = n; printf("派生类构造函数!\n"); } void std_display(); private: char name[20]; int Math; int Chinese; Teacher Wang;//子对象 }; void Student::std_display() { printf("%d\n",TeaYear); //派生类访问基类受保护的成员 // printf("%d\n",ClassRoom); // “Teacher::ClassRoom”: 无法访问 private 成员(在“Teacher”类中声明) //派生类无法访问基类的私有成员 } int _tmain(int argc, _TCHAR* argv[]) { Student std1("Li",100,100,1,50); std1.std_display(); getchar(); return 0; }
继承方式包括: public(公用的),private(私有的)和protected(受保护的),此项是可选的,如果不写此项,则默认为private(私有的)。所谓公用的,是说所定义的变量或函数在类外可以引用,而私有的,则说明定义的变量或函数只能在类内使用,受保护的意为不能被外界引用,但可以被派生类的成员引用。
Student(const char *s,int m,int n,int x,int years):Teacher(s,x,years),Wang(s,x,years)
1)执行派生类构造函数的顺序是:
① 调用基类构造函数,对基类数据成员初始化;
② 调用子对象构造函数,对子对象数据成员初始化;
③ 再执行派生类构造函数本身,对派生类数据成员初始化。
2)派生类的析构函数
在派生时,派生类不能继承基类的析构函数,需要通过派生类的析构函数去调用基类的析构函数。在派生类中可以根据需要定义自己的析构函数,用来对派生类中所增加的成员进行清理。在执行派生类的析构函数时,系统会自动调用基类的析构函数和子对象的析构函数,对基类和子对象进行清理。调用的顺序与构造函数相反: 先执行派生类自己的析构函数,对派生类新增加的成员进行清理,然后调用子对象的析构函数,最后调用基类的析构函数。
3)虚基类
从上面的学习中,我们发现如果一个派生类有多个直接基类,而这些直接基类又有一个共同的基类,则在最终的派生类中会保留该间接共同基类数据成员的多份同名成员。C++提供虚基类(virtual base class)的方法,使得在继承间接共同基类时只保留一份成员。
class A//声明基类A
{…};
class B :virtual public A //声明类B是类A的公用派生类,A是B的虚基类
{…};
class C :virtual public A //声明类C是类A的公用派生类,A是C的虚基类
{…};
注意: 虚基类并不是在声明基类时声明的,而是在声明派生类时,指定继承方式时声明的。因为一个基类可以在生成一个派生类时作为虚基类,而在生成另一个派生类时不作为虚基类。
声明虚基类的一般形式为
class 派生类名: virtual 继承方式 基类名
经过这样的声明后,当基类通过多条派生路径被一个派生类继承时,该派生类只继承该基类一次。为了保证虚基类在派生类中只继承一次,应当在该基类的所有直接派生类中声明为虚基类。
如果在虚基类中定义了带参数的构造函数,而且没有定义默认构造函数,则在其所有派生类(包括直接派生或间接派生的派生类)中,通过构造函数的初始化表对虚基类进行初始化。
在最后的派生类中不仅要负责对其直接基类进行初始化,还要负责对虚基类初始化。C++编译系统只执行最后的派生类对虚基类的构造函数的调用,而忽略虚基类的其他派生类(如类B和类C) 对虚基类的构造函数的调用,这就保证了虚基类的数据成员不会被多次初始化。