当前位置: 首页 > article >正文

【C++面向对象——继承与派生】派生类的应用(头歌实践教学平台习题)【合集】

目录😋

实验目的

相关知识

一、类的继承关系基础概念

二、不同继承方式下对基类成员的访问控制

三、利用虚基类解决二义性问题

实验任务

实验步骤

编程要求

测试说明

通关代码

测试结果


实验目的

  1. 学习声明和使用类的继承关系,声明派生类
  2. 熟悉不同继承方式下对基类成员的访问控制
  3. 学习利用虚基类解决二义性问题

相关知识

为了完成本关任务,你需要掌握:

  1. 类的继承关系基础概念
  2. 不同继承方式下对基类成员的访问控制
  3. 利用虚基类解决二义性问题

一、类的继承关系基础概念

  • 继承的定义:继承是面向对象编程中的一个重要特性,它允许创建一个新类(派生类)从一个现有类(基类)派生而来。派生类继承了基类的成员变量和成员函数,就好像孩子继承了父母的某些特征一样。这样可以实现代码的复用,减少重复代码的编写。
  • 声明派生类的语法(以 C++ 为例)

基本语法是在派生类的定义中,在类名后面加上冒号和继承方式,再跟基类名。例如:

class DerivedClass : public BaseClass {
    // 派生类的成员
};

这里DerivedClass是派生类,BaseClass是基类,public是继承方式。除了public,还有privateprotected这两种继承方式。

二、不同继承方式下对基类成员的访问控制

  • public 继承
    • 基类的public成员在派生类中仍然是public,可以在派生类对象以及外部代码(通过派生类对象)中访问。基类的protected成员在派生类中仍然是protected,可以在派生类内部访问,但不能在外部代码(通过派生类对象)中访问。基类的private成员在派生类中不可直接访问,就好像被隐藏起来了。

例如,如果BaseClass有一个public函数publicFunction(),在DerivedClass(通过public继承自BaseClass)中可以像这样调用:

class BaseClass {
public:
    void publicFunction() {
        // 函数实现
    }
};
class DerivedClass : public BaseClass {
public:
    void callBaseFunction() {
        publicFunction();  // 可以在派生类中调用基类的public函数
    }
};
  • private 继承
    • 基类的publicprotected成员在派生类中都变为private。这意味着它们只能在派生类内部访问,外部代码(通过派生类对象)无法访问这些从基类继承来的成员。

例如,对于private继承:

class DerivedClass : private BaseClass {
public:
    void callBaseFunction() {
        publicFunction();  // 可以在派生类内部调用基类的public函数
    }
};
// 但是在外部,以下代码是错误的
DerivedClass derivedObj;
derivedObj.publicFunction();  // 无法访问,因为通过private继承,该函数在派生类中变为private
  • protected 继承
    • 基类的public成员在派生类中变为protectedprotected成员在派生类中仍然是protected。这意味着这些成员可以在派生类内部以及派生类的派生类(下一层派生类)中访问,但不能被外部代码(通过派生类对象)访问。

三、利用虚基类解决二义性问题

  • 二义性问题的产生
    • 当一个派生类有多个基类,并且这些基类又有共同的基类(间接基类)时,就可能产生二义性。例如,有一个类Base,类Derived1Derived2都继承自Base,然后有一个类MultiDerived同时继承自Derived1Derived2。如果Base中有一个成员函数func(),当在MultiDerived中访问func()时,编译器不知道应该从Derived1还是Derived2路径来访问这个func(),就产生了二义性。
  • 虚基类的概念和作用
    • 虚基类是为了解决这种多继承中的二义性问题而引入的。在继承时将共同的基类声明为虚基类,这样在派生类中就只有一份共同基类的副本。

声明虚基类的语法(以 C++ 为例):在继承层次结构中,将共同的基类声明为虚基类,在继承时使用virtual关键字。例如:

class Base {
    // 基类的成员
};
class Derived1 : virtual public Base {
    // 派生类的成员
};
class Derived2 : virtual public Base {
    // 派生类的成员
};
class MultiDerived : public Derived1, public Derived2 {
    // 此时在MultiDerived中访问Base的成员不会产生二义性
};

通过将Base声明为Derived1Derived2的虚基类,在MultiDerived中就只有一个Base的实例,从而避免了访问Base成员时的二义性。


实验任务

参考实验指导书第七章的实验任务4:

  1. 从实验 6 中的 people(人员)类派生出 student (学生)类,
    添加属性:班号 char classNO[7];
  2. 从 people 类派生出teacher(教师)类,
    添加属性:职务 char principalship[11]、部门 char department[21]。
  3. 从 student 类中派生出 graduate(研究生)类,
    添加属性:专业 char subject[21]、导师 teacher adviser;
  4. 从 graduate 类和 teacher 类派生出 TA(助教生)类,
    注意虚基类的使用。重载相应的成员函数,测试这些类。

(类之间的关系如下图所示。)

实验步骤

  1. 创建一个教师实例,姓名为Zheng Li,编号为1001,性别为Female,1978年1月1日生,身份证号为1234567890,职务为professor,部门为CST。
  2. 创建一个助教实例,姓名为Li Chao,编号为011401,性别为Male,1988年6月1日生,身份证号为12345619880601,职务为TA,部门为CST,班号为cst61,专业为computer science,导师为Zheng Li。
  3. 依次输出该助教的姓名,编号,部门,班号,专业和导师。

编程要求

根据提示,在右侧编辑器补充代码,并输出正确的值。

测试说明

平台会对你编写的代码进行测试:

预期输出:
TA name: Li Chao
No.: 011401
Department: CST
Class No.: cst61
Subject: computer science
Advisor: Zheng Li

开始你的任务吧,祝你成功!


通关代码

#include <iostream>
#include <cstring>
using namespace std;

class Date
{
public:
	int year;
	int month;
	int day;
	Date() {year = 1900; month = 1; day = 1;}
	Date(int y, int m, int d) : year(y), month(m), day(d) {}
//	Date(const Date& b) {year = b.year; month = b.month; day = b.day;}
};

class people
{
	char name[11];
	char number[7];
	char sex[3];
	Date birth;
	char id[16];
public:
	char* getName() {return name;}
	char* getNumber() {return number;}
	char* getSex() {return sex;}
	Date getBirth() {return birth;}
	char* getId() {return id;}
	people() {}
	people(const char* nm, const char* no, const char* gd, Date b, const char* i) : birth(b) {
		strcpy(name, nm);
		strcpy(number, no);
		strcpy(sex, gd);
		strcpy(id, i);
	}
};

class teacher : virtual public people
{
	char principalship[11];
	char department[21];
public:
	char* getPs() {return principalship;}
	char* getDpm() {return department;}
	teacher() {}
	teacher(const char* ps, const char* dpm) {
		strcpy(principalship, ps);
		strcpy(department, dpm);
	}
	teacher(const char* nm, const char* no, const char* gd, Date b, const char* i, const char* ps, const char* dpm) : people(nm, no, gd, b, i) {
		strcpy(principalship, ps);
		strcpy(department, dpm);
	}
};

class student : virtual public people
{
	char classNO[7];
public:
	char* getClassNO() {return classNO;}
	student() {}
	student(const char* cln) {strcpy(classNO, cln);}
	student(const char* nm, const char* no, const char* gd, Date b, const char* i, const char* cln) : people(nm, no, gd, b, i) {
		strcpy(classNO, cln);
	}
};

class graduate : public student
{
	char subject[21];
	teacher adviser;
public:
	char* getSubject() {return subject;}
	teacher getAdviser() {return adviser;}
	graduate() {}
	graduate(const char* sbj, teacher adv) : adviser(adv) {strcpy(subject, sbj);}
	graduate(const char* cln, const char* sbj, teacher adv) : student(cln), adviser(adv) {strcpy(subject, sbj);}
	graduate(const char* nm, const char* no, const char* gd, Date b, const char* i, const char* cln, const char* sbj, teacher adv) : 
        student(nm, no, gd, b, i, cln), adviser(adv) {strcpy(subject, sbj);}
};

class TA : public graduate, public teacher
{
public:
	TA() {}
	TA(const char* nm, const char* no, const char* gd, Date b, const char* i, const char* ps, const char* dpm, const char* cln, const char* sbj, teacher adv) : 
        people(nm, no, gd, b, i), teacher(ps, dpm), graduate(cln, sbj, adv) {}
};

int main()
{
	/********** Begin **********/
    teacher ad("Zheng Li","1001","Female",Date(1978,1,1),"1234567890","professor","CST");
    TA ta ("Li Chao","011401","Male",Date(1988,6,1),"12345619880601","TA","CST","cst61","computer science",ad);
    /********** End **********/
	cout << "TA name: " << ta.getName() << endl;
	cout << "No.: " << ta.getNumber() << endl;
	cout << "Department: " << ta.getDpm() << endl;
	cout << "Class No.: " << ta.getClassNO() << endl;
	cout << "Subject: " << ta.getSubject() << endl;
	cout << "Advisor: " << ad.getName() << endl;
	return 0;
}

测试结果

在这里插入图片描述


http://www.kler.cn/a/470768.html

相关文章:

  • java 转义 反斜杠 Unexpected internal error near index 1
  • nlp培训重点-2
  • 阿尔法linux开发板ping不通百度
  • 数值分析速成复习笔记
  • 批量写入数据到数据库,卡顿怎么解决
  • iOS - Tagged Pointer
  • Flink-CDC 全面解析
  • 【pytorch-lightning】架构一览
  • 复杂园区网基本分支的构建
  • 工控主板ESM7000/6800E支持远程桌面控制
  • GolangWeb开发-好用的HTTP客户端httplib(beego)
  • 对智能手表进行逆向工程
  • 数据结构:二叉搜索树详解
  • 搭建SSL邮件服务器
  • 2024年最新外包干了10个月,技术退步明显,程序人生
  • 基于云效 Windows 构建环境和 Nuget 制品仓库进行 .Net 应用开发
  • 在 Windows 上安装 NodeJS
  • linux下vfio显卡透传
  • Flink系统知识讲解之:如何识别反压的源头
  • flask-admin 非自定义modelview下扩展默认视图(base.html)
  • 20241230 AI智能体-用例学习(LlamaIndex/Ollama)
  • 【每日学点鸿蒙知识】Hap 安装失败、ArkTS 与C++ 数组转换、渐变遮罩效果等
  • 从源码编译Qt5
  • RWKV 语言模型
  • 2025年的加密软件市场如何?
  • 原型模式详解与实践