派生的概念
继承:在定义一个新的类B时,如果该类与某个已有的类A相似(指的是B拥有A的全部特点), 那么就可以把A作为一个基类,而把B作为基类的一个派生类(也称子类)
继承和派生的概念 :
- 派生类是通过对基类进行修改和扩充得到 的。
- 在派生类中,可以扩充新的成员变量 和成员函数。
- 派生类一经定义后,可以独立使用,不依赖于基类。
- 派生类拥有基类的全部成员函数和成员变量,不论是private、protected、public 。
- 在派生类的各个成员函数中,不能访问基类中的private成员。
派生类对象的体积
派生类对象的体积,等于基类对象的体积,再加上派生类对象自己的成员变量的体积。在派生类对象中,包含着基类对象,而且基类对象的存储位置位于派生类对 象新增的成员变量之前。
实例程序:学籍管理
#include <iostream
>
#include <string>
using namespace std;
class CStudent
{
private:
string name;
string id; //学号
char gender; //性别,'F'代表女,'M'代表男
int age;
public:
void PrintInfo();
void SetInfo( const string & name_,const string & id_,
int age_, char gender_ );
string GetName() { return name; }
};
19
class CUndergraduateStudent:public CStudent
{//本科生类,继承了CStudent类
private:
string department; //学生所属的系的名称
public:
void QualifiedForBaoyan() { //给予保研资格
cout << “qualified for baoyan” << endl;
}
void PrintInfo() {
CStudent::PrintInfo(); //调用基类的PrintInfo
cout << “Department:” << department <<endl;
}
void SetInfo( const string & name_,const string & id_,
int age_,char gender_ ,const string & department_) {
CStudent::SetInfo(name_,id_,age_,gender_); //调用基类的SetInfo
department = department_;
}
};
20
void CStudent::PrintInfo()
{
cout << "Name:" << name << endl;
cout << "ID:" << id << endl;
cout << "Age:" << age << endl;
cout << "Gender:" << gender << endl;
}
void CStudent::SetInfo( const string & name_,const string & id_,
int age_,char gender_ )
{
name = name_;
id = id_;
age = age_;
gender = gender_;
}
21
int main()
{
CUndergraduateStudent s2;
s2.SetInfo(“Harry Potter ”, “118829212”,19,‘M’,“Computer Science”);
cout << s2.GetName() << “ ” ;
s2.QualifiedForBaoyan ();
s2.PrintInfo ();
return 0;
}
22
输出结果:
Harry Potter qualified for baoyan
Name:Harry Potter
ID:118829212
Age:19
Gender:M
Department:Computer Science
类之间的两种关系:
• 继承:“是”关系。
– 基类 A,B是基类A的派生类。 – 逻辑上要求:“一个B对象也是一个A对象”(中学生也是学生)。
• 复合:“有”关系。 (详见2继承关系和复合关系)
– 类C中“有”成员变量k,k是类D的对象,则C和D是复合关系 – 一般逻辑上要求:“D对象是C对象的固有属性或组成部分”。
覆盖
派生类可以定义一个和基类成员同名的成员,这叫 覆盖。
在派生类中访问这类成员时,缺省的情况是访问派生类中定义的成员。要在派生类中访问由基 类定义的同名成员时,要使用作用域符号::。
真实编程中一般不会定义同名成员变量,只会定义同名成员函数。
类的保护成员(Protected)
在创建派生类的对象时,需要调用基类的构造函数:初始化派 生类对象中从基类继承的成员。在执行一个派生类的构造函数 之前,总是先执行基类的构造函数。
• 调用基类构造函数的两种方式
– 显式方式:在派生类的构造函数中,为基类的构造函数提供 参数. derived::derived(arg_derived-list):base(arg_base-list)
– 隐式方式:在派生类的构造函数中,省略基类构造函数时, 派生类的构造函数则自动调用基类的默认构造函数派生类的析构函数被执行时,执行完派生类的析构函数后,自动调用基类的析构函数。
在创建派生类的对象时:
- 先执行基类的构造函数,用以初始化派生类对象中从基类继承的成员;
- 再执行成员对象类的构造函数,用以初始化派生类对象中 成员对象。
- 最后执行派生类自己的构造函数。
在派生类对象消亡时:
- 先执行基类的构造函数,用以初始化派生类对象中从基类 继承的成员;
- 再执行成员对象类的构造函数,用以初始化派生类对象中 成员对象。
- 最后执行派生类自己的构造函数
public继承的赋值兼容规则:
class base { };
class derived : public base { };
base b; derived d;
- 派生类的对象可以赋值给基类对象 b = d;(把d中的base复制给b,d=b则错误)
- 派生类对象可以初始化基类引用 base & br = d; (引用d中的base)
- 派生类对象的地址可以赋值给基类指针 base * pb = & d; (pb引用d中的base)
如果派生方式是 private或protected,则上述三条不可行。