明明白白c++ 继承 接口继承和实现继承
来源:互联网 发布:vnr翻译软件 编辑:程序博客网 时间:2024/06/04 18:59
前言
继承,为什么要设计继承呢?这个是面向对象的一个重要概念,减少设计的复杂度。通过继承可以减少代码量。
c++中的继承形式比较多,公有继承,保护继承,和私有继承。如果是为了对付考试,那么你还是需要弄清楚这些概念。但是实际上公有继承比较有用,其他的可以忽略掉,大多数情况下他们很不实用,而且还用弄错。所以google推荐使用组合的方式来代替那些私有和保护继承。
组合和继承,has和is的关系。这里就不讨论了。
就继承的目的来看,包括接口继承和实现继承两种。
根据前面讲过的虚函数的概念,这这里又要用到。
本文参考
http://dev.yesky.com/218/2145218_2.shtml
一 纯虚函数。-----------接口继承
纯虚函数的作用是为了实现接口。
这里拿移动为例子吧,因为很多讲这里的时候都是拿形状为例子的。用自己的例子将一东西,才能让自己学习明白。
比如我做游戏设计的,人型和飞鸟两种角色。他们的移动肯定是不同的,会播放不用的动画效果。(例如dota里面的普通英雄和蝙蝠火焰状态)
#include <iostream>using namespace std;class character{public: virtual void move()=0; void id();};class people:public character{public:virtual void move();};class bird:public character{public:virtual void move();};void people::move(){ cout<<"people move"<<endl;}void bird ::move(){ cout<<"bird move"<<endl;}int main(){ character c;//报错 people p; bird b; p.move(); b.move(); c.move();//报错}注释掉报错那句话上面的程序的输出结果是
people move
bird move
有几个细节需要注意:
1 如果你用class 定义类,那么类里面默认声明是private,类之间的继承关系是private,所以一定养成好的习惯明确用public,private,protected来表示,因为你很可能记混淆struct 和class的默认关键字。
2 如果是接口继承一定要定义成纯虚函数。可以认为只是个接口,随着子类不同,属性不用。父类没有明确的定义,是抽象的概念。
3 含义纯虚函数的类叫做抽象类,它不能声明对象,因为它是抽象的,它没有具体形态,所以也就不存在。
二 虚函数--------------接口继承+ 缺省实现
这里我们拿两个英雄来说,lina 和 jugg 火女和剑圣,大家都知道剑圣有跳劈,攻击时候会是攻击力的倍数值,但是普通英雄并没有。
#include <iostream>using namespace std;class character{public: virtual void attact(character &c); int getLife(); void setLife(int value); void setAccactValue(int value); int getAccactValue(); private: int life; int accactValue;};int character::getAccactValue(){ return accactValue;}void character::setAccactValue(int value){ accactValue = value;}int character::getLife(){return life;}void character::attact(character &c){ int life = c.getLife(); c.setLife(life - getAccactValue()); cout<<"common acctact"<<endl;}void character::setLife(int value){ if (value > 0) life = value; else life = 0;}class lina:public character{};class jugg:public character{public: virtual void attact(character &c);float randomRate();};float jugg::randomRate(){ //这里为了简化写成1.5,实际是个区间的随机数 return 1.5;}void jugg::attact(character &c){int life = c.getLife();c.setLife(life - getAccactValue() * randomRate());cout<<"jugg acctact"<<endl;}int main(){ lina l; jugg j; l.setLife(100); l.setAccactValue(10); j.setLife(100); j.setAccactValue(10); l.attact(j); j.attact(l); cout<<"lina's life"<<l.getLife()<<endl; cout<<"jugg's life"<<j.getLife()<<endl;}
上面一段代码描述了jugg和lina相互攻击的过程。
其中有一个地方需要注意攻击函数传递的对象要加&,这样才能改变传入的对象,不然就是值传递。你会发现最后两个英雄打来打去,生命都不会减少。
http://blog.csdn.net/mlkiller/article/details/8754330如果不明白可以看这篇文章
输出如下:
common acctact
jugg acctact
lina's life85
jugg's life90
火女只会调用父类的普通攻击,而剑圣则会调用自己的攻击方式,所以导致相同生命,相同攻击力,最终结果不同。
所以,虚函数可以理解为很多情况下, 子类都可以用父类的缺省值,但是也有一些例外的,对例外情况进行重写。
三 非虚函数 (即能实现接口,又能强制实现)
我之前的那篇文章中也说了非虚函数和虚函数的一些区别,如果想了解可以查看
http://blog.csdn.net/mlkiller/article/details/8852200 明明白白c++ 虚函数
它和上面的虚函数最大的区别就是虚函数是动态绑定。
也就是说只有一种情况是不一样的,当用父类指针和引用的时候,它会根据指针或者引用的真实内容是属于父类还是子类,来绑定对于的函数。
这里就不展开讲了,另外java里面也没有非虚函数这种形式。
那它存在有两个原因,我想,
第一是历史原因,因为c++源于c语言,可以单独的定义函数。
大家是从c转换到c++都很容易接受这种函数形式,直接加virtual反而不容易接受。
第二是效率上会稍微有点提高。但是如果所有的函数都用虚函数其实也没有坏处。
- 明明白白c++ 继承 接口继承和实现继承
- C++:接口继承和实现继承
- 接口继承和实现继承
- 接口继承和实现继承
- 接口继承和实现继承
- 继承:继承接口和实现
- [effective c++]条款34-区分接口继承和实现继承
- Effective C++:条款34:区分接口继承和实现继承
- 《Effective C++》:条款34:区分接口继承和实现继承
- 区分接口继承和实现继承(Effective C++_34)
- [C++]接口继承与实现继承
- [C++]接口继承与实现继承
- C++箴言:接口继承和实现继承
- 区分接口继承和实现继承
- 接口继承和实现继承的区别
- 接口继承和实现继承的区别
- C++箴言:接口继承和实现继承
- C++箴言:接口继承和实现继承
- POJ 计算几何入门题目推荐(转)
- Linux将中文目录名改为英文
- 学习笔记 二
- 黑马程序员_二 【注释】【标识符】【常量】【变量】【进制】【运算符】
- 内核模块编译--Makefile写法
- 明明白白c++ 继承 接口继承和实现继承
- POJ 2886: Who Gets the Most Candies?
- java环境变量设置
- setsockopt()用法(参数详细说明)
- MPEG4码流简单分析
- 快速排序
- hdu1075-What Are You Talking About
- 关于MPEG4 码流(mpeg4 raw data)的格式分析
- 贝叶斯分类器的matlab实现