【C++ 实验六 继承与派生】
实验内容 1. 某计算机硬件系统,为了实现特定的功能,在某个子模块设计了 ABC 三款芯片用于 数字计算。各个芯片的计算功能如下: A 芯片:计算两位整数的加法(m+n)、计算两位整数的减法(m-n) B 芯片:计算两位整数的加法(m+n)、计算两位整数的乘法(m*n) C 芯片:计算两位整数的加法(m+n)、计算两位整数的除法(m/n) 为 ABC 三个芯片分别定义类,描述上述芯片的功能,并在 main 函数中测试这三个类。 (提示:利用类的继承和派生,抽象出共有属性和操作作为基类。)
解答:
下面给出该题目的一个cpp文件
代码:
- #include<iostream>
- using namespace std;
- class Z{
- public:
- void createZ(int x0,int y0);
- void jia();
- private:
- int m;
- int n;
- };
- void Z::createZ(int x0,int y0){
- m=x0;
- n=y0;
- }
- void Z::jia(){
- cout<<"相加的结果:"<<m+n<<endl;
- }
- class A:public Z{
- public:
- void createA(int x0,int y0);
- void jian();
- private:
- int m1;
- int n1;
- };
- void A::createA(int x0,int y0){
- createZ(x0,y0);
- m1=x0;
- n1=y0;
- }
- void A::jian(){
- cout<<"相减之后的答案:"<<m1-n1 <<endl;
- }
- class B:public Z{
- public:
- void createB(int x0,int y0);
- void cheng();
- private:
- int m2;
- int n2;
- };
- void B::createB(int x0,int y0){
- createZ(x0,y0);
- m2=x0;
- n2=y0;
- }
- void B::cheng(){
- cout<<"相乘的结果:"<<m2*n2<<endl; //从A继承到B呢
- }
- class C:public Z{
- public:
- void createC(int x0,int y0);
- void chu();
- private:
- int m3;
- int n3;
- };
- void C::createC(int x0,int y0){
- createZ(x0,y0);
- m3=x0;
- n3=y0;
- }
- void C::chu(){
- cout<<"相除的结果:"<<m3/n3<<endl; //从A继承到B呢
- }
- int main(){
- A a;
- B b;
- C c;
- a.createA(,);
- a.jia();
- a.jian();
- cout<<endl;
- c.createC(,);
- c.chu();
- c.jia();
- cout<<endl;
- b.createB(,);
- b.cheng();
- b.jia();
- return ;
- }
运行截图:
该题总结:
2. 定义一个车(vehicle)基类,具有数据成员 maxspeed, weight(均为 int 型), 函数 成员 run(), stop(),由此派生出自行车(bicycle)类、汽车(motorcar)类。其中, bicycle 类 新增数据成员高度(height), motorcar 类新增数据成员座位数(seatnum)属性。再从 bicycle
第 2 页/共 4 页
和 motorcar 派生出摩托车(motorcycle)类,并在主程序中测试这个类。(每个类都要求定 义构造函数和析构函数) (提示: ① 注意把 vehicle 设置为虚基类; ② run(), stop()函数体,通过输出字符串 run, stop 简单模拟。 )
解答:
代码是一个cpp文件:
- #include<iostream>
- using namespace std;
- class vehicle{
- public:
- vehicle(int m,int w):maxspeed(m),weight(w){
- }
- ~vehicle(){
- }
- void run(){
- cout<<"正在启动中。"<<endl;
- }
- void stop(){
- cout<<"停下汽车!"<<endl;
- }
- private:
- int maxspeed;
- int weight ;
- };
- class bicycle:virtual public vehicle{
- public:
- bicycle(int w,int m,int h):vehicle(w,m),height(h){
- }
- ~bicycle(){
- }
- void getht(){
- cout<<"高度:"<<height<<endl;
- }
- private:
- int height;
- };
- class motorcar:virtual public vehicle{
- public:
- motorcar(int w,int m,int s):vehicle(w,m),seatnum(s){
- }
- ~motorcar(){
- }
- void getsm(){
- cout<<"座位数量:"<<seatnum<<endl;
- }
- private:
- int seatnum;
- };
- class motorcycle:public bicycle,public motorcar{
- public:
- motorcycle(int w,int m,int h,int s):vehicle(w,m),bicycle(w,m,h),motorcar(w,m,s){
- }
- ~motorcycle(){
- }
- };
- int main(){
- motorcycle m(,,,);
- m.getht();
- m.getsm();
- m.run();
- m.stop();
- return ;
- }
- //构造函数的写法是这个程序带给我的最大收获。
- //派生类的构造函数需要写出基类的构造函数,并可以根据参数的不同来进行修改fuzhi
运行截图:
3. 基于「实验 4 类和对象-2」中设计并实现的类 Fraction,创建派生类 iFraction,用以 描述如下形式的分数:
要求: (1) 更新 Fraction 类 为 Fraction 类编写运算符+、-、*、/重载函数,实现在 main 函数中直接用+、-、 *、/进行 Fraction 类运算。 (2)设计并实现派生 iFraction 类 ① 为派生类 iFraction 定义构造函数,实现 iFraction 对象的初始化 ② 为派生类 iFraction 增加一个成员函数,用于在屏幕上显示 iFraction 对象 (3)设计一个普通函数 convertF()用于对 iFraction 类对象进行规范化处理。(*选做*)
(提示:把 convertF()设计为 Fraction 类和 iFraction 类的友元函数) 例如:(更多情形请自行考虑)
5/3
→ 1
2 /3
(4)以多文件结构方式编写(fraction.h, fraction.cpp, ifraction.h, ifraction.cpp, main.cpp)
解答:
代码如下:
1.fraction.h
- #ifndef FRACTION_H
- #define FRACTION_H
- class fraction{
- public:
- fraction(int a=,int b=);
- // fraction(fraction &f);
- ~fraction();
- fraction operator+(const fraction &f2) const;
- fraction operator-(const fraction &f2) const;
- fraction operator*(const fraction &f2) const;
- fraction operator/(const fraction &f2) const;
- int getfenzi();
- int getfenmu();
- void result();
- friend void convertF(fraction &f);
- private:
- int fenzi;
- int fenmu;
- };
- #endif
2.fraction.cpp
- #include<iostream>
- #include"fraction.h"
- using namespace std;
- //构造函数
- fraction::fraction(int a,int b):fenzi(a),fenmu(b){
- }
- //fraction::fraction(fraction &f):fenzi(f.fenzi),fenmu(f.fenmu){
- //}为啥这里用复制构造函数反而使函数报错
- // 析构函数
- fraction::~fraction(){
- }
- fraction fraction::operator+(const fraction &f2) const{
- if(fenmu==f2.fenmu)
- {
- return fraction(fenzi+f2.fenzi,fenmu);
- }
- else{
- return fraction(fenzi*f2.fenmu+fenmu*f2.fenzi,fenmu*f2.fenmu);
- }
- }
- //运算符重载
- fraction fraction::operator-(const fraction &f2) const{
- if(fenmu==f2.fenmu)
- {
- return fraction(fenzi-f2.fenzi,fenmu);
- }
- else{
- return fraction(fenzi*f2.fenmu-fenmu*f2.fenzi,fenmu*f2.fenmu);
- }
- }
- fraction fraction::operator*(const fraction &f2) const{
- return fraction(fenzi*f2.fenzi,fenmu*f2.fenmu);
- }
- fraction fraction::operator/(const fraction &f2) const{
- return fraction(fenzi*f2.fenmu,fenmu*f2.fenzi);
- }
- //访问私有成员
- int fraction::getfenmu(){
- return fenmu;
- }
- int fraction::getfenzi(){
- return fenzi;
- }
- //输出最后结果
- void fraction::result(){
- cout<<fenzi<<"/"<<fenmu<<endl;
- }
- //友元函数规范化
- //第一次出错因为在实现函数时也加进了友元标识
- void convertF(fraction &f){
- int a,b,t;
- a=f.getfenzi();
- b= f.getfenmu();
- if(a>=b){
- t=a/b;
- while(a>b){
- a=a-b;
- }
- cout<<"分数应该化为:"<<t<<"+"<<a<<"/"<<b<<endl;
- }
- else cout<<"分数就是:"<<a<<"/"<<b<<endl;
- }
3.ifraction.h
- #ifndef ifraction_h
- #define ifraction_h
- #include"fraction.h"
- class ifraction:public fraction {
- public:
- ifraction(int a=,int b=);
- void printfra();
- ~ifraction();
- friend void convertF(ifraction &f);
- };
- #endif
4.ifraction.cpp
- #include"ifraction.h"
- #include<iostream>
- using namespace std;
- void ifraction::printfra(){
- cout<<getfenzi()<<"/"<<getfenmu()<<endl;
- }
- ifraction::ifraction(int a,int b):fraction(a,b){
- }
- ifraction::~ifraction(){
- }
- void convertF(ifraction &f){
- int a,b,t;
- a=f.getfenzi();
- b= f.getfenmu();
- if(a>=b){
- t=a/b;
- while(a>b){
- a=a-b;
- }
- cout<<"分数应该化为:"<<t<<"+"<<a<<"/"<<b<<endl;
- }
- else cout<<"分数就是:"<<a<<"/"<<b<<endl;
- }
5.main.cpp
- #include<iostream>
- using namespace std;
- #include"fraction.h"
- #include"ifraction.h"
- int main(){
- ifraction a(,),b(,),c(,);
- //c=a+b;//测试了运算符重载,发现这里报错,为什么?是运算符重载不能继承吗?
- //检查之后发现是虽然能重载,返回值的类型却是fraction类类型,比如一个函数原本是int 类型,继承之后也不会变成double吧
- fraction d,e(,);
- d=a+b;
- cout<<"输出a+b=";
- d.result();
- cout<<"输出a-b=";
- d=a-b;
- d.result();
- cout<<"输出a*b=";
- d=a*b;
- d.result();
- cout<<"输出a/b=";
- d=a/b;
- d.result();
- cout<<"输出ifraction的对象c:";
- c.printfra();
- convertF(e);
- convertF(c);
- return ;
- }
运行截图:
该实验总结:
运算符重载能不能被继承?修改过后的代码显示当然可以。是不是所有的运算符重载都能被继承?
查到赋值操作符的特殊,如下解释:
- class widget
{
① widget& operator=( const widget& rhs ){} // 这个叫做赋值操作符
② widget& operator=( const int ) {} // 这个叫做赋值操作符重载
} ;- ①. 赋值操作符属于类的复制控制的一部分(默构,复构,赋值,析构), 自己不定义,编译器会自动合成.它的正式叫法是(copy assignment operator),强调的是属于复制控制的一部分.
- ②. 赋值操作符重载和赋值操作符不一样,你不定义,编译器不会自动合成.
- 所以你要是问子类赋值操作符会不会继承父类,那肯定是不会的.
1. 如果 子类没定义赋值操作符, 那么 子类会自动合成赋值操作符, 子类在赋值的时候会自动调用父类的赋值操作符来完成基类部分的复制拷贝.
2. 如果 子类自己定义了赋值操作符, 那么 子类就不会继续自动合成, 仍然子类必须手动调用父类的赋值操作符来完成基类部分的赋值拷贝,否则会造成部分复制( partial copy assignment )
4. (***选做***) 基于提供的程序文件,补足并扩充程序,实现一个多类型玩家角色扮演游戏。 在本次实验附件包 ex4 中有如下文件: container.h, container.cpp, player.h, player.cpp, swordsman.h, swordsman.cpp, main.cpp (1)阅读源码,理解并补足程序,让程序运行生效。 其中,程序中出现有????????之处,是需要补足的部分。 (2)画出这个角色扮演游戏 UML 类图,尤其是类和类之间的关系 (3)设计并实现 archer 类和 mage 类。在 UML 类图中也加进这两个新类。 (4)修改 main 函数,随机生成不同角色的敌人,并保证程序正常运行。 (5)为游戏增加其它元素,完善游戏的可玩性、趣味性,等。 (说明:这道涉及虚函数、运行时多态。你可以在第 8 章学完后尝试编写,或者, 在尝试编写这道题的过程中,学习第 8 章虚函数和运行时多态的知识。 )
这道题待我计算完毕之后再行更新。。。
【C++ 实验六 继承与派生】的更多相关文章
- c++学习--继承与派生
继承和派生 1 含有对象成员(子对象)的派生类的构造函数,定义派生类对象成员时,构造函数的执行顺序如下: 1 调用基类的构造函数,对基类数据成员初始化: 2 调用对象成员的构造函数,对对象成员的数据成 ...
- C++复习:继承与派生
1继承概念 面向对象程序设计有4个主要特点:抽象.封装.继承和多态性.说了类和对象,了解了面向对象程序设计的两个重要特征一数据抽象与封装,已经能够设计出基于对象的程序,这是面向对象程序设计的基础. 要 ...
- 实验 六:分析linux内核创建一个新进程的过程
实验六:分析Linux内核创建一个新进程的过程 作者:王朝宪 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029 ...
- java 实验3 继承+多态
实验3 继承与多态 **类可以实现多个接口 但只有单继承!** 1.继承 1).继承语法 class 子类名 extends 父类{ } 2).构造函数(通过source即可得到) 注意: ...
- Day08:继承与派生,多态,封装,绑定与非绑定方法,面向对象高级(反射,__str__,__del__)
上节课复习:1.编程思想 面向过程 核心是过程二字,过程指的是解决问题的步骤,即先干什么再干什么后干什么 基于该思想编写程序就好比在设计一条流水线,是一种机械式的思维 ...
- Python面向对象编程——继承与派生
Python面向对象编程--继承与派生 一.初始继承 1.什么是继承 继承指的是类与类之间的关系,是一种什么"是"什么的关系,继承的功能之一就是用来解决代码重用问题. 继承是一种创 ...
- 类属性与对象实现,init方法的作用,绑定方法,绑定方法与普通函数的区别,继承,抽象与继承,派生与覆盖
今日内容: 1.类属性与对象属性 2.init方法的作用 3.绑定方法 4.绑定方法与普通函数的区别(非绑定方法) 5.继承 6.抽象与继承 7.派生与覆盖 1.类属性与对象属性 类中应该进存储所有对 ...
- 不可或缺 Windows Native (21) - C++: 继承, 组合, 派生类的构造函数和析构函数, 基类与派生类的转换, 子对象的实例化, 基类成员的隐藏(派生类成员覆盖基类成员)
[源码下载] 不可或缺 Windows Native (21) - C++: 继承, 组合, 派生类的构造函数和析构函数, 基类与派生类的转换, 子对象的实例化, 基类成员的隐藏(派生类成员覆盖基类成 ...
- [C++]类的继承与派生
继承性是面向对象程序设计的第二大特性,它允许在既有类的基础上创建新类,新类可以继承既有类的数据成员和成员函数,可以添加自己特有的数据成员和成员函数,还可以对既有类中的成员函数重新定义.利用类的继承和派 ...
随机推荐
- apt-get本地软件源搭建
参考:https://www.cnblogs.com/myitroad/p/4970416.html 试验机器: Ubuntu 12.04.Lubuntu.Debian都可,其他版本应该也没问题,服务 ...
- 解决radio、select表单返回时,再次选择失效
应用场景:我们在选择好radio跟select之后提交表单,返回历史记录时,再次选择,提交表单,发现提交的是上次表单选择的 解决办法:我们可以一进页面就给radio跟select的选项重置掉,因为,返 ...
- 两个c语言结构体复制的问题
以前一直以为结构体要通过memcpy来复制,现在才明白可直接用“=”复制 C语言中,结构体是一篇连续的内存空间,使用=赋值操作,底层用到的就是memcpy:如果结构体中有指针变量:操作后.两个指针指向 ...
- vue ssr github 项目及其 文章
https://github.com/Liao123/vue-js-webpack-ssr 这个项目可以完美运行 npm run start 是运行
- AD证书导入文档(单向认证)
AD证书或者SSL证书导入的方法步骤(在root用户下操作) 1. 将证书命名为AD-PRO.cer,并确定证书的颁发. 2. 将/app/ad_cert/keystore下的原有证书删除掉和文件 ...
- SVN 版本控制安装
客户端 一路点击next即可 注意事项: 这个一定要选,否则后面使用会出现问题. 选择下拉菜单的第一项
- Nhibernate 使用 (二)
在第一篇中该做的配置基本上已经全部完成,现在直接开始测试 public static ISession NhibClient() { try { // Nhibernate 配置文件的位置 var p ...
- vmware安装centOs操作系统配置网络的一系列问题
1:最近公司在测试项目,需要在linux操作系统上面测试,可惜自己之前学linux操作系统不是很深,配置网络也不是很熟练,网上方法太多,但是不是很好用,确实难为了自己一把,在这里自己总结一下配置网络的 ...
- SQL反模式学习笔记16 使用随机数排序
目标:随机排序,使用高效的SQL语句查询获取随机数据样本. 反模式:使用RAND()随机函数 SELECT * FROM Employees AS e ORDER BY RAND() Limit 1 ...
- java 安装以及配置
1.下载 JDK 下载地址:https://www.oracle.com/technetwork/java/javase/downloads/index-jsp-138363.html 2.环境变量配 ...