类的继承与派生概述
- 继承与派生是同一过程从不同的角度看
保持已有类的特性而构造新类的过程称为继承
在已有类的基础上新增自己的特性而产生新类的过程称为派生。 - 被继承的已有类称为基类(或父类)
- 派生出的新类称为派生类(或子类)
- 直接参与派生出某类的基类称为直接基类
- 基类的基类甚至更高层的基类称为间接基类
继承与派生的目的
- 继承的目的:实现设计与代码的重用。
- 派生的目的:当新的问题出现,原有程序无法解决(或不能完全解决)时,需要对原有程序进行改造。
派生类的定义
单继承
class 派生类名:继承方式 基类名
{
成员声明;
}
// 例如:
class Derived: public Base
{
public:
Derived ();
~Derived ();
};
多继承
class 派生类名:继承方式1 基类名1,继承方式2 基类名2,...
{
成员声明;
}
// 注意:每一个“继承方式”,只用于限制对紧随其后之基类的继承。
// 例如:
class Derived: public Base1, private Base2
{
public:
Derived ();
~Derived ();
};
派生类的构成
- 吸收基类成员
吸收基类成员之后,派生类实际上就包含了它的全部基类中除构造和析构函数之外的所有成员。 - 改造基类成员
如果派生类声明了一个和某基类成员同名的新成员,派生的新成员就隐藏或覆盖了外层同名成员 - 添加新的成员
派生类增加新成员使派生类在功能上有所发展
继承方式
不同继承方式下类成员的访问控制
派生类成员对基类成员的访问权限
通过派生类对象对基类成员的访问权限
三种继承方式
公有继承
私有继承
保护继承
公有继承(public)
- 基类的public和protected成员的访问属性在派生类中保持不变,但基类的private成员不可直接访问。
- 派生类中的成员函数可以直接访问基类中的public和protected成员,但不能直接访问基类的private成员。
- 通过派生类的对象访问从基类继承的成员,只能访问public成员。
示例1
#include <iostream>
#include <string>
using namespace std;
class Student{ // 声明基类
public:
int num;
Student(int numN=004, string nameN="gg", char sexN='m'){ // 构造函数
num = numN;
name = nameN;
sex = sexN;
cout << "base Init" << endl;
}
void display(){
cout << "num: " << num << endl;
cout << "name: " << name << endl;
cout << "sex: " << sex << endl;
}
private: // 基类私有成员
string name;
char sex;
};
class Student_cn: public Student{ // 以public方式声明派生类Student_cn
public:
int age;
Student_cn(int ageN=12, string addrN="hust"){
age = ageN;
addr = addrN;
cout << "Derived Init" << endl;
}
void display_cn(){
cout << "age: " << age << endl; // 引用派生类的公有成员
cout << "address: " << addr << endl; // 引用派生类的是有成员
}
private:
string addr;
};
int main(int argc, char** argv) {
Student_cn stud_cn; // 定义派生类Stud_cn
cout << "Base Num: " << stud_cn.num << endl; // 派生类可以调用基类的public的数据成员
stud_cn.display(); // 调用基类的公用成员函数,输出基类中的3个数据成员的值
stud_cn.display_cn(); // 调用派生类的公用成员函数,输出派生类中两个数据成员的值
return 0;
}
私有继承(private)
- 基类的public和protected成员都以private身份出现在派生类中,但基类的private成员不可直接访问。
- 派生类中的成员函数可以直接访问基类中的public和protected成员,但不能直接访问基类的private成员。
- 通过派生类的对象不能直接访问从基类继承的任何成员。
示例2
#include <iostream>
#include <string>
using namespace std;
class Student{ // 声明基类
public:
int num;
Student(int numN=004, string nameN="gg", char sexN='m'){ // 构造函数
num = numN;
name = nameN;
sex = sexN;
cout << "base Init" << endl;
}
void display(){
cout << "num: " << num << endl;
cout << "name: " << name << endl;
cout << "sex: " << sex << endl;
}
private: // 基类私有成员
string name;
char sex;
};
class Student_cn: private Student{ // 以private方式声明派生类Student_cn
public:
int age;
Student_cn(int ageN=12, string addrN="hust"){
age = ageN;
addr = addrN;
cout << "Derived Init" << endl;
}
void display_cn(){
display(); // 派生类的成员函数不能访问私有基类的私有成员,但可以访问私有基类的公用成员
cout << "age: " << age << endl; // 引用派生类的公有成员
cout << "address: " << addr << endl; // 引用派生类的是有成员
}
private:
string addr;
};
int main(int argc, char** argv) {
Student_cn stud_cn; // 定义派生类Stud_cn
// cout << "Base Num: " << stud_cn.num << endl; // 派生类不可以调用基类的public的数据成员
// stud_cn.display(); // 不可以调用基类的公用成员函数,输出基类中的3个数据成员的值
stud_cn.display_cn(); // 调用派生类的公用成员函数,输出派生类中两个数据成员的值
return 0;
}
保护继承(protected)
- 基类的public和protected成员都以protected身份出现在派生类中,但基类的private成员不可直接访问。
- 派生类中的成员函数可以直接访问基类中的public和protected成员,但不能直接访问基类的private成员。
- 通过派生类的对象不能直接访问从基类继承的任何成员。
示例3
#include <iostream>
#include <string>
using namespace std;
class Student{ // 声明基类
public:
int num;
Student(int numN=004, string nameN="gg", char sexN='m'){ // 构造函数
num = numN;
name = nameN;
sex = sexN;
cout << "base Init" << endl;
}
void display(){
cout << "num: " << num << endl;
cout << "name: " << name << endl;
cout << "sex: " << sex << endl;
}
private: // 基类私有成员
string name;
char sex;
};
class Student_cn: protected Student{ // 以protected方式声明派生类Student_cn
public:
int age;
Student_cn(int ageN=12, string addrN="hust"){
age = ageN;
addr = addrN;
cout << "Derived Init" << endl;
}
void display_cn(){
display(); // 派生类的成员函数不能访问私有基类的私有成员,但可以访问私有基类的公用成员
cout << "age: " << age << endl; // 引用派生类的公有成员
cout << "address: " << addr << endl; // 引用派生类的是有成员
}
private:
string addr;
};
int main(int argc, char** argv) {
Student_cn stud_cn; // 定义派生类Stud_cn
// cout << "Base Num: " << stud_cn.num << endl; // 派生类不可以调用基类的public的数据成员
// stud_cn.display(); // 不可以调用基类的公用成员函数,输出基类中的3个数据成员的值
stud_cn.display_cn(); // 调用派生类的公用成员函数,输出派生类中两个数据成员的值
return 0;
}