题目要求
将例5.3的程序片段补充和改写成一个完整、正确的程序,用保护继承方式。在程序中应包括输入数据的函数。
——谭浩强的《C++面向对象程序设计》第5章习题第3小题
例5.3的程序片段:
#include <iostream> #include <string> using namespace std; class Student // 声明基类 { public: // 基类无公用成员 protected: // 基类保护成员 int num; string name; char sex; }; class Student1 : protected Student // 以 protected 方式声明派生类 Student1 { public: // 派生类公用成员 void get_value1(); // 输入派生类数据 void display1(); // 输出两个数据成员的值 private: // 派生类私有成员 int age; string addr; }; void get_value1() // 输入派生类数据 { cin >> num >> name >> sex; // 输入保护基类数据成员 cin >> age >> addr; // 输入派生类数据成员 } void Student1::display1() // 输出两个数据成员的值 { cout << "num: " << num << endl; // 引用基类的保护成员 cout << "name: " << name << endl; // 引用基类的保护成员 cout << "sex: " << sex << endl; // 引用基类的保护成员 cout << "age: " << age << endl; // 引用派生类的私有成员 cout << "address: " << addr << endl; // 引用派生类的私有成员 } int main() { Student1 stud1; // 定义派生类 Student1 的对象 stud1 stud1.get_value1(); // 调用派生类的公用成员函数,输入派生类两个数据成员的值 stud1.display1(); // 调用派生类的公用成员函数,输出派生类中两个数据成员的值 system("pause"); return 0; }
保护继承
在基类的访问属性 |
继承方式 |
在派生类中的访问属性 |
private(私有) |
protected(保护) |
不可访问 |
public(公用) |
protected(保护) |
protected(保护) |
protected(保护) |
protected(保护) |
protected(保护) |
当派生类的继承方式为 protected 继承属性时,在派生类中,基类的公有成员和保护成员均作为派生类的保护成员,派生类的成员可以直接访问它们,而派生类的成员无法访问基类的私有成员。
如例5-3中:
void Student1::display1() // 输出两个数据成员的值 { cout << "num: " << num << endl; // 引用基类的保护成员 cout << "name: " << name << endl; // 引用基类的保护成员 cout << "sex: " << sex << endl; // 引用基类的保护成员 ... }
num、name、sex 均为基类的保护成员,派生类 Student1 的成员函数 display1 可以访问直接它们。
如果把 num、name、sex 改为私有成员,即:
protected: // 基类保护成员 int num; string name; char sex;
改为
private: // 基类保护成员 int num; string name; char sex; };
则程序报错如下:
“Student::num”: 无法访问 private 成员(在“Student”类中声明) “Student::name”: 无法访问 private 成员(在“Student”类中声明) “Student::sex”: 无法访问 private 成员(在“Student”类中声明)
因为当派生类的继承方式为 protected 时,派生类的成员不能访问基类的私有成员。
在派生类的外部,派生类的对象无法访问基类的全部成员。
例如在 main 函数内修改 num 的值:
int main() { Student1 stud1; // 定义派生类 Student1 的对象 stud1 stud1.num = 5; // 错误。类外访问基类的保护成员 stud1.get_value1(); // 调用派生类的公用成员函数,输入派生类两个数据成员的值 stud1.display1(); // 调用派生类的公用成员函数,输出派生类中两个数据成员的值 system("pause"); return 0; }
会出现报错:
“Student::num”: 无法访问 protected 成员(在“Student”类中声明)
因为 num 是基类 student 的保护成员,由于派生类是保护继承,在派生类中仍受保护,但外界不能用 stud1.num 形式访问它。
对比公用继承,保护继承在类外不能访问基类所有成员,而公用继承在类外可以访问基类的公用成员。
如果基类只进行了一次派生,则保护继承和私有继承的功能完全相同,但保护继承可以进一步派生,而私有继承则不可以,两者具有实质性差别。
三种继承方式比较
在基类的访问属性 |
继承方式 |
在派生类的访问属性 |
private |
public |
不可访问 |
private |
private |
不可访问 |
private |
protected |
不可访问 |
public |
public |
public |
public |
private |
private |
public |
protected |
protected |
protected |
public |
protected |
protected |
private |
private |
protected |
protected |
protected |
补充改写后的程序
/* ************************************************************************* @file: main.cpp @date: 2020.11.29 @author: Xiaoxiao @brief: 保护继承方式输入和输出 num,name,sex,age,addr @blog: https://blog.csdn.net/weixin_43470383/article/details/110204364 ************************************************************************* */ #include #include using namespace std; class Student // 声明基类 { public: // 基类无公用成员 protected: // 基类保护成员 int num; string name; char sex; }; class Student1 : protected Student // 以 protected 方式声明派生类 Student1 { public: // 派生类公用成员 void get_value1(); // 输入派生类数据 void display1(); // 输出两个数据成员的值 private: // 派生类私有成员 int age; string addr; }; // 其实要改的只有这里,get_value1() 前面加上 Student1:: // 原因是在类外声明成员函数,需要在函数名前面加类名限定,具体参考我之前的博客: // https://editor.csdn.net/md/?articleId=109298731 void Student1::get_value1() // 输入派生类数据 { cin >> num >> name >> sex; // 输入保护基类数据成员 cin >> age >> addr; // 输入派生类数据成员 } void Student1::display1() // 输出两个数据成员的值 { cout << "num: " << num << endl; // 引用基类的保护成员 cout << "name: " << name << endl; // 引用基类的保护成员 cout << "sex: " << sex << endl; // 引用基类的保护成员 cout << "age: " << age << endl; // 引用派生类的私有成员 cout << "address: " << addr << endl; // 引用派生类的私有成员 } int main() { Student1 stud1; // 定义派生类 Student1 的对象 stud1 stud1.get_value1(); // 调用派生类的公用成员函数,输入派生类两个数据成员的值 stud1.display1(); // 调用派生类的公用成员函数,输出派生类中两个数据成员的值 system("pause"); return 0; }
运行结果
输入:
8 Xiaoxiao m 20 Guangzhou
输出:
num: 8
name: Xiaoxiao
sex: m
age: 20
address: Guangzhou
结果和上两篇博客相同。