C++学习 之 继承(笔记)
1.继承基础:
继承就像是生物里的遗传与变异,即派生类(子代)从基类(父代)那里继承基类的某些特性(遗传),并在此基础上拥有自己的特性(变异)。
C++派生语法:
class Base//定义一个基类
{
//...基类成员
};
class Derived:access-specifier Base//定义一个派生类
{
//...派生类成员
}
其中access-specifier可以是public、private、protected(表示派生类有一个基类)。
以下程序清单从Fish类派生出了Carp和Tuna类的一种简单的继承层次结构:
#include<iostream>
using namespace std;
class Fish //定义Fish类
{
public:
bool FreshWaterFish; void Swim()
{
if (FreshWaterFish)
cout << "Swims in lake" << endl;
else
cout << "Swims in sea" << endl;
}
}; class Tuna :public Fish//定义Tuna类,将继承的Fish类的成员或方法作为自己的public成员或方法
{
public:
Tuna()
{
FreshWaterFish = false;
}
}; class Carp :public Fish
{
public:
Carp()
{
FreshWaterFish = true;
}
}; int main()
{
Carp myLunch;
Tuna myDinner; cout << "Getting my food to swim" << endl; cout << "Lunch:";
myLunch.Swim(); cout << "Dinner:";
myDinner.Swim(); return ;
}
2.向基类传递参数:
向基类传递参数在初始化派生类对象时有的时候显得很有用。比如上面的Fish类派生出Carp类和Tuna类,可以修改成如下代码:
#include<iostream>
using namespace std;
class Fish
{
protected:
bool FreshWaterFish;
Fish(bool IsFreshWater)
{
FreshWaterFish = IsFreshWater;
}
public:
void Swim()
{
if (FreshWaterFish)
cout << "Swims in lake" << endl;
else
cout << "Swims in sea" << endl;
return;
}
}; class Tuna :public Fish
{
public:
Tuna():Fish(false) {}//派生类每次定义对象都指出是淡水鱼还是咸水鱼,采用参数列表将bool值传递给基类的构造函数
}; class Carp :public Fish
{
public:
Carp():Fish(true) {}
}; int main()
{
Carp myLunch;
Tuna myDinner; cout << "Getting my food to swim" << endl; cout << "Lunch:";
myLunch.Swim(); cout << "Dinner:";
myDinner.Swim(); return ;
}
3.在派生类中覆盖基类的方法:
如果派生类中有和基类中的函数名相同,返回值和特征标也相同时,就相当于派生类的方法覆盖了基类的方法。我们还拿Fish类,Tuna类和Carp类来举例子。
用Tuna和Carp类的Swim()覆盖Fish类的Swim():
#include<iostream>
using namespace std;
class Fish
{
protected:
bool FreshWaterFish;
Fish(bool IsFreshWater)
{
FreshWaterFish = IsFreshWater;
}
public:
void Swim()
{
if (FreshWaterFish)
cout << "Swims in lake" << endl;
else
cout << "Swims in sea" << endl;
return;
}
}; class Tuna :public Fish
{
public:
Tuna():Fish(false) {}
void Swim()//此函数与基类函数在调用上效果相同,基类函数被覆盖
{
cout << "Tuna swim fast" << endl;
}
}; class Carp :public Fish
{
public:
Carp():Fish(true) {}
void Swim()
{
cout << "Carp swim low" << endl;
}
}; int main()
{
Carp myLunch;
Tuna myDinner; cout << "Getting my food to swim" << endl; cout << "Lunch:";
myLunch.Swim(); cout << "Dinner:";
myDinner.Swim(); return ;
}
上面的程序的结果显示了,在主函数中对象调用方法Swim()时调用的并不是Fish类里的方法了,而是Tuna和Carp自己的方法,这样基类的方法就相当于是被覆盖了。覆盖是的派生类的方法可以自定 义,但如果我们还想使用基类的方法,就必须想办法使得机器可以知道我们调用的Swim()的作用域在哪个范围。
4. 调用基类中被覆盖的方法:
上面说到了我们只需要让机器知道我们调用的Swim()的作用域,就可以使得被覆盖的基类方法重新被调用。我们可以在调用基类方法时使用"::"作用域解析运算符。
以上面的调用Swim()的代码为例:
myLunch.Swim();//调用派生类Carp中的Swim()
my.Lunch.Fish::Swim();//调用基类Fish中的Swim()
如果基类的方法没有被覆盖,则可以在派生类中和调用函数一样来调用基类的方法。如果被覆盖的话就要使用"::"作用域解析运算符。在主函数里调用就是类似语句:"my.Lunch.Fish::Swim();"在派 生类调用基类被覆盖方法时类似于语句:"Fish::Swim"。
5. 在派生类中隐藏基类的方法:
覆盖的一种极端情形就是,Tuna::Swim()可能隐藏Fish::Swim()的所有重载版本,使得使用这些重载版本会导致编译错误。
以下面代码为例:
#include<iostream>
using namespace std;
class Fish
{
public:
void Swim()
{
cout << "Fish swims...!" << endl;
}
void Swim(bool FreshWaterFish)
{
if (FreshWaterFish)
cout << "Swims in lake" << endl;
else
cout << "Swims in sea" << endl;
return;
}
}; class Tuna :public Fish
{
public:
void Swim()
{
cout << "Tuna swim fast" << endl;
}
};
int main()
{
Tuna myDinner; cout << "Getting my food to swim" << endl;
cout << "Dinner:";
myDinner.Swim();
//myDinner.Swim(false); return ;
}
代码在6-17行实现了基类方法Swim的重载,在23-26行实现了派生类方法Swim对基类方法Swim的覆盖。观察发现派生类里只有一个版本的Swim方法,Fish中的Swim的重载版本Swim(bool)版本好像是没 有被覆盖,但其实Swim(bool)也类似被覆盖的情况是没法在派生类或主函数中像调用其他函数那样被调用的。如果我们去掉35行的注释符号,代码就会有编译错误,这也说明了问题。以上说明了在派生类 中覆盖基类的方法时是与函数的参数无关的,只要函数名称,返回值,特征值相同就会被覆盖。
调用基类中被隐藏的方法:
解决方案1:在main函数中使用作用域解析运算符"::"。
myDinner.Fish::Swim();
解决方案2:在派生类中使用关键字using解除对基类方法的隐藏。
class Tuna:public Fish
{
public:
using Fish Swim;//解除对Fish::Swim()重载版本的隐藏,其中不包括与派生类参数也相同的方法。
void Swim(){}
}
解决方案3:在Tuna类中重新定义所有Fish类的被覆盖的方法的重载版本。
C++学习 之 继承(笔记)的更多相关文章
- Python学习的个人笔记(基础语法)
Python学习的个人笔记 题外话: 我是一个大二的计算机系的学生,这份python学习个人笔记是趁寒假这一周在慕课网,w3cschool,还有借鉴了一些博客,资料整理出来的,用于自己方便的时候查阅, ...
- hadoop2.5.2学习及实践笔记(四)—— namenode启动过程源码概览
对namenode启动时的相关操作及相关类有一个大体了解,后续深入研究时,再对本文进行补充 >实现类 HDFS启动脚本为$HADOOP_HOME/sbin/start-dfs.sh,查看star ...
- hadoop2.5.2学习及实践笔记(二)—— 编译源代码及导入源码至eclipse
生产环境中hadoop一般会选择64位版本,官方下载的hadoop安装包中的native库是32位的,因此运行64位版本时,需要自己编译64位的native库,并替换掉自带native库. 源码包下的 ...
- 开始记录学习java的笔记
今天开始记录学习java的笔记,加油
- 菜鸟教程之学习Shell script笔记(上)
菜鸟教程之学习Shell script笔记 以下内容是,学习菜鸟shell教程整理的笔记 菜鸟教程之shell教程:http://www.runoob.com/linux/linux-shell.ht ...
- Exception类的学习与继承总结
日期:2018.11.11 星期日 博客期:023 Exception类的学习与继承总结 说起来我们上课还是说过的!老师提到了报错问题出现主要分Exception和Error两类!第一次遇见这个问题是 ...
- 深度学习Keras框架笔记之AutoEncoder类
深度学习Keras框架笔记之AutoEncoder类使用笔记 keras.layers.core.AutoEncoder(encoder, decoder,output_reconstruction= ...
- 深度学习Keras框架笔记之TimeDistributedDense类
深度学习Keras框架笔记之TimeDistributedDense类使用方法笔记 例: keras.layers.core.TimeDistributedDense(output_dim,init= ...
- 深度学习Keras框架笔记之Dense类(标准的一维全连接层)
深度学习Keras框架笔记之Dense类(标准的一维全连接层) 例: keras.layers.core.Dense(output_dim,init='glorot_uniform', activat ...
- Elasticsearch7.X 入门学习第九课笔记-----聚合分析Aggregation
原文:Elasticsearch7.X 入门学习第九课笔记-----聚合分析Aggregation 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. ...
随机推荐
- noi.ac #543 商店
我们考虑可并堆维护,从深到浅贪心选取. 用priority_queue启发式合并的话,是60pts: #include<iostream> #include<cstdio> # ...
- 第03组 Alpha冲刺(4/4)
队名:不等式方程组 组长博客 作业博客 团队项目进度 组员一:张逸杰(组长) 过去两天完成的任务: 文字/口头描述: 制定了初步的项目计划,并开始学习一些推荐.搜索类算法 GitHub签入纪录: 暂无 ...
- 11-ajax
Ajax 1.什么是ajax Asynchronous JavaScript and XML(异步JavaScript和XML) 节省用户操作,时间,提高用户体验,减少数据请求 传输获取数据 特点 ...
- $\LaTeX$数学公式大全2
$2\ Math\ Constructs$$\frac{abc}{xyz}$ \frac{abc}{xyz}$f'$ f'$\sqrt{abc}$ \sqrt{abc}$\sqrt[n]{abc}$ ...
- JETSON TK1 ~ 安装Cuda和OpenCV3
一:安装Cuda6.5 1:下载安装包 Cuda6.5 2.在TK1上安装软件包: cd ~/Downloads sudo dpkg -i cuda-repo-l4t-r21.3-6-5-prod_6 ...
- 用 Docker 搭建 ORACLE 数据库开发环境
用 Docker 搭建 ORACLE 数据库开发环境 需要安装 ORACLE 数据库做开发,直接安装的话因为各类平台的限制,非常复杂,会遇到很多问题. 还好,现在有 Docker 化的部署方式,省去很 ...
- Maximum upload size exceede上传文件大小超出解决
在这里记录三种方法, 努力提高自己的姿势水平 application.yml配置 spring: servlet: multipart: enabled: true max-file-size: 10 ...
- SRS之RTMP连接处理线程conn:接收客户端推流
由 SRS之RTMP的TCP线程 分析可知,SRS 接受客户端的连接后创建了一个线程:conn,用于处理与客户端的 RTMP 连接. 本文的分析是基于该配置文件的: listen 1935; max_ ...
- [eclipse]如何修改Eclipse编辑器的字体
步骤如下, 菜单->"Window"->“Preference”->“General”->“Appearance”->“Colors & Fo ...
- LC 889. Construct Binary Tree from Preorder and Postorder Traversal
Return any binary tree that matches the given preorder and postorder traversals. Values in the trave ...