【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++]类的继承与派生
继承性是面向对象程序设计的第二大特性,它允许在既有类的基础上创建新类,新类可以继承既有类的数据成员和成员函数,可以添加自己特有的数据成员和成员函数,还可以对既有类中的成员函数重新定义.利用类的继承和派 ...
随机推荐
- Collections of Zujin Zhang's Published works
I am not good, but I shall do my best to be better. Any questions, please feel free to contact zhang ...
- Coursera, Big Data 1, Introduction (week 3)
什么是分布式文件系统?为什么需要分布式文件系统? 如果文件系统可以管理用网络连接的很多个存储单元,叫分布式文件系统. 分布式文件系统提供了数据可扩展性,容错性,高并发. 这些是传统文件系统不具有的. ...
- sql server 2008 windows验证改为混合登陆SqlServer身份验证用户名密码
安装过程中,SQL Server 数据库引擎设置为 Windows 身份验证模式或 SQL Server 和 Windows 身份验证模式.本主题介绍如何在安装后更改安全模式. 如果在安装过程中选择“ ...
- 解决radio、select表单返回时,再次选择失效
应用场景:我们在选择好radio跟select之后提交表单,返回历史记录时,再次选择,提交表单,发现提交的是上次表单选择的 解决办法:我们可以一进页面就给radio跟select的选项重置掉,因为,返 ...
- 响应消息的内容类型 text/html; charset=utf-8 与绑定(application/soap+xml; charset=utf-8)的内容类型不匹配。
问题表述: 响应消息的内容类型 text/html; charset=utf-8 与绑定(application/soap+xml; charset=utf-8)的内容类型不匹配. 说明: 此类问题当 ...
- python的一些基本概念
1.为什么python被称为胶水语言?他是新一代的系统脚本参考博客:https://www.cnblogs.com/ningskyer/articles/5264172.html 2.python百度 ...
- 【原创】Linux基础之SSH秘钥登录
官方:https://www.ssh.com/ssh/ The SSH protocol uses encryption to secure the connection between a clie ...
- Visual Studio 2015 NuGet Update-Package 失败/报错:Update-Package : Unable to load the service index for source https://api.nuget.org/v3/index.json.
起因 为了用VS2015 community中的NuGet获取Quartz,在[工具]-[NuGet包管理器]-[程序包管理器控制台]中执行 Install-Package Quartz. 却报如下错 ...
- 18 常用模块 random shutil shevle logging sys.stdin/out/err
random:随机数 (0, 1) 小数:random.random() ***[1, 10] 整数:random.randint(1, 10) *****[1, 10) 整数:random.rand ...
- javascript事件委托的原理与实现
事件委托 事件流 捕获:查找目标元素: 目标:执行目标的事件: 冒泡:依次执行祖先元素的事件. onmouseenter和onmouseleave不支持冒泡: onmouseover和onmouseo ...