C++学习 —— 灵活的继承特性
0、继承与算法开发
在之前的笔记中,我展示了来自继承的威力。继承这种机制能够大幅度减小编码量,子类可以继承父类所有的变量,方法。利用这种机制,我们可以在其他人工作的基础上,完成有自己特色的部分。比如我们要开发icp算法,但是pcl中已经提供了icp类,其中有各种方法,可以调用完成功能。但是icp是瀑布模型的,对于特定的任务有它的瓶颈,如果需要利用C++实现高性能的icp算法,则可以继承已有的代码,开发我们自己的子流程。
上面那一段听起来很有道理,其实不然。coding的终极目标并不是减少编码量,而是需要有清晰的架构可读性,好的扩展性,并且耐造。继承一部分代码确实是很偷懒的做法,但是很难保证子类可以用到父类所有的方法,也就更无从谈起父类是子类的抽象了。这对以后的工作留下了隐患,无意义的方法存在对象中,会对后续的继任者造成困扰。所以如果不是架构清晰,目标明确,最好是不要这样继承了。代码应该扁平化!!!
1、何时使用继承
继承除了刚刚提到的偷懒以外,它被发明出来当然有更艰巨的任务。实现这个艰巨任务还依赖一个很灵活的特性,称为多态。多态才是真正的大杀器。多态是指,在base类中使用虚函数,而后,以base类指针指向一个derive class object. 那么当我们调用base class 中的虚函数时,指令会前往 derive class 存放函数的空间中,找到对应的实现。比如,base class 是 shape, shape 里面有 cut rotate move draw 方法,但是对于二维图形,三维图形,draw的实现是不一样的。如果在后续的程序中,我们要对shape 进行一系列的操作。而具体是操作二维图形还是三维图形,可能需要在程序运行的时候决定。所以我们可以用基类 shape 的指针来进行后面的工作。此外,shape 指针还可以放在同一个容器中,而两个不同类的指针是没法放在同一个容器里的。
总而言之,继承+多态这种方法,让我们可以在抽象的概念中编写程序。这种特性很灵活,很强大。比如小汽车可以move, 客车也可以 move,挖掘机也可以move。。。。那么我们就只需要对不同的子类实现各自的move,最后决定坐什么车,就调用哪个move即可。但是。。。虽然这个特性很灵活很强大,可是对于科研来说。。。作用实在有限,可能我只在乎我的方法,而没有那么多其他方法可以实现。继承最大的作用还是增强程序的可扩展性,或者说增加程序支持的方法。
对 C++了解的越多,越发觉得,它适合的是软件工程,是架构超大规模,面向大量不同客户的大系统。而不是用来实现一个功能,或者一个简单的算法。继承是为了大软件服务,泛型是为了大型库服务.........越发觉得C++不是玩具,而是生产工具。
2、一个简单的多态例子
还是那个魔兽世界的问题,现在warrior 的不同不仅仅是名字了,而是不同的warrior 有不同的特点。我利用多态 & 工厂模式实现了不同特性的warrior 降生。
#include <iostream>
#include <vector>
#include <string>
#include <iomanip> using namespace std; class warrior{
public:
warrior(int life_,string name_):life(life_),name(name_){
armList.push_back("sword");
armList.push_back("bomb");
armList.push_back("arrow");
}
int getLife() const {return this->life;}
string getName() const {return this->name;}
virtual int getNum() const = ;
virtual void create(int alllife,int bianhao_) = ;
void CommonBurnPrint(int special_num) const{
cout<<' '<<getName()
<<' '
<<bianhao
<<" with strength "
<<getLife()
<<", "
<<special_num
<<' '
<<getName();
}
virtual void selfBurnPrint() const = ; virtual ~warrior(){} private:
static int num;
const string name;
protected:
int bianhao;
int life;
vector<string> armList;
}; class Lion: public warrior{
public:
Lion(int life_):warrior(life_,"lion"){}
void create(int alllife,int bianhao_) {
num++;
loyal = alllife;
bianhao = bianhao_; }
int getNum() const {return num;}
int getLoyal()const{return loyal;}
void selfBurnPrint() const {cout<<"its loyalty is "<<loyal<<endl;}
private:
static int num;
int loyal;
}; class Dragon: public warrior
{
public:
Dragon(int life_):warrior(life_,"dragon"){}
void create(int alllife,int bianhao_) {
bianhao =bianhao_;
num++;
morale = float(alllife)/life;
arm = armList.at((bianhao)%); }
int getNum() const {return num;}
string getArm() const{return arm;}
int getMorale() const{return morale;}
void selfBurnPrint() const {cout<<"it has a "<<arm<<" and its morale is "<<std::setprecision()<<morale<<endl;}
private:
static int num;
float morale;
string arm;
}; class Ninja:public warrior{ public:
Ninja(int life_):warrior(life_,"ninja"){}
void create(int alllife,int bianhao_){
num++;
bianhao = bianhao_;
arm1 = armList.at((bianhao)%);
arm2 = armList.at((bianhao+)%);
}
void selfBurnPrint() const {cout<<"it has a "<<arm1<<" and "<<arm2<<endl;}
int getNum() const {return num;}
string getArm1() const {return arm1;}
string getArm2() const{return arm2;}
private:
static int num;
string arm1;
string arm2;
}; class Iceman:public warrior{
public:
Iceman(int life_):warrior(life_,"iceman"){}
void create(int alllife,int bianhao_){
num++;
bianhao = bianhao_;
arm = armList.at((bianhao)%);
}
int getNum() const {return num;}
string getArm()const {return arm;}
void selfBurnPrint() const {cout<<"it has a "<<arm<<endl;}
private:
static int num;
string arm;
}; class Wolf:public warrior{
public:
Wolf(int life_):warrior(life_,"wolf"){}
int getNum() const {return num;}
void create(int alllife,int bianhao_){
num++;
bianhao = bianhao_;
}
void selfBurnPrint() const {}
private:
static int num;
}; int warrior::num = ;
int Lion::num = ;
int Iceman::num = ;
int Dragon::num = ;
int Wolf::num = ;
int Ninja::num = ; class headquarter{
public:
headquarter(const string quarterName_,int ALLLIFE_,vector<int> warriorList_,int * warriorlife_):quarterName(quarterName_),
ALLLIFE(ALLLIFE_),
warriorList(warriorList_),
warriorlifeLists(warriorlife_){}
bool warriorBurn(int time);
private:
inline bool __warriorBurn(int warrior_no);
const string quarterName;
int ALLLIFE;
warrior * Warrior;
std::vector<warrior*> warrior_house;
std::vector<int> warriorList;
int * warriorlifeLists;
}; bool headquarter::warriorBurn(int time){ int current = time;
cout<< setfill('') << setw() << time<<" ";
while(!__warriorBurn(warriorList.at(time%)))
{
time++;
if(current+ == time)
{
cout<<this->quarterName<<" stop making warriors"<<endl;
return false;
}
}
return true;
} bool headquarter::__warriorBurn(int warrior_no){ int dragonlife = warriorlifeLists[];
int ninjialife = warriorlifeLists[];
int icemanlife = warriorlifeLists[];
int lionlife = warriorlifeLists[];
int wolflife = warriorlifeLists[]; switch(warrior_no){
case :
Warrior = new Dragon(dragonlife);
break;
case :
Warrior = new Ninja(ninjialife);
break;
case :
Warrior = new Iceman(icemanlife);
break;
case :
Warrior = new Lion(lionlife);
break;
case :
Warrior = new Wolf(wolflife);
break;
default:
return false;
} int totalLife = ALLLIFE;
totalLife -= Warrior->getLife();
if(totalLife > )
{
ALLLIFE = totalLife; int bianhao = warrior_house.size()+;
Warrior->create(ALLLIFE,bianhao); cout<<this->quarterName; Warrior->CommonBurnPrint(Warrior->getNum()); cout<<" in "
<<this->quarterName
<<" headquarter"
<<endl; Warrior->selfBurnPrint(); warrior_house.push_back(Warrior); return true;
}
return false;
} int main(int argc, char const *argv[])
{ int Case;
int alllife,lionlife,ninjialife,dragonlife,wolflife,icemanlife; cin>>Case;
cin>>alllife;
cin>>dragonlife>>ninjialife>>icemanlife>>lionlife>>wolflife;
cout<<"case:"<<Case<<endl; int warriorLife[] = {dragonlife,ninjialife,icemanlife,lionlife,wolflife}; warrior * ninja = new Ninja(ninjialife); /* No.1 for dragon
No.2 fir ninja
No.3 for iceman
No.4 for lion
No.5 for wolf
*/
int dragon_No = ;
int ninja_No = ;
int iceman_No = ;
int lion_No = ;
int wolf_No = ; std::vector<int> red_list;
red_list.push_back(iceman_No);
red_list.push_back(lion_No);
red_list.push_back(wolf_No);
red_list.push_back(ninja_No);
red_list.push_back(dragon_No); std::vector<int> blue_list;
blue_list.push_back(lion_No);
blue_list.push_back(dragon_No);
blue_list.push_back(ninja_No);
blue_list.push_back(iceman_No);
blue_list.push_back(wolf_No); headquarter red("red",alllife,red_list,warriorLife);
headquarter blue("blue",alllife,blue_list,warriorLife); int time = ;
bool red_result = true;
bool blue_result = true;
while()
{
if(red_result)
red_result = red.warriorBurn(time);
if(blue_result)
blue_result = blue.warriorBurn(time);
if(red_result || blue_result)
{
time++;
continue;
}
break;
} return ; }
C++学习 —— 灵活的继承特性的更多相关文章
- 从 prototype.js 深入学习 javascript 的面向对象特性
从 prototype.js 深入学习 javascript 的面向对象特性 js是一门很强大的语言,灵活,方便. 目前我接触到的语言当中,从语法角度上讲,只有 Ruby 比它更爽. 不过我接触的动态 ...
- Java-Maven(七):Eclipse中Maven依赖、聚合、继承特性
之前通过学习了解,maven集成到eclipse中的如何创建项目,以及maven命令插件在eclipse中安装后的用法.那么接下来我们将会学习一些maven在项目中的一些特性,及如何使用. Maven ...
- 《挑战30天C++入门极限》图例实解:C++中类的继承特性
图例实解:C++中类的继承特性 整个c++程序设计全面围绕面向对象的方式进行,类的继承特性是c++的一个非常非常重要的机制,继承特性可以使一个新类获得其父类的操作和数据结构,程序员只需在新类中 ...
- C++ Primer Plus 学习之 类继承
主要介绍了类的继承.虚函数.类继承的动态内存分配问题.继承与友元函数. 公有派生 基类的公有成员和私有成员都会成为派生类的一部分. 基类的私有成员只能通过基类的公有或者保护方法访问.但是,基类指针或引 ...
- MVC5 Entity Framework学习之实现继承
之前你已经学习了怎样处理并发异常,在本节中你将学习怎样实现继承. 在面向对象的编程中,你能够使用继承来重用代码.接下来你将改动Instructor和Student类,让它们派生自Person基类,该基 ...
- c++学习笔记之继承篇
title: c++学习笔记之继承篇 date: 2017-03-26 16:36:33 tags: [c++,继承,public,virtual,private,protected] categor ...
- 可能是最早的学习Android N新特性的文章
可能是最早的学习Android N新特性的文章 Google在今天放出了Android N开发者预览版.Android N支持Nexus6及以上的设备.5太子Nexus5不再得到更新. Android ...
- 从零开始一起学习SLAM | C++新特性要不要学?
LAM,C++编程是必备技能.不过,大家在学校里学习的书本一般比较老,主要还是C++98那些老一套. 本文所谓的C++新特性是指C++11及其以后的C++14.C++17增加的新关键字和新语法特性.其 ...
- PHP实现多继承 - 通过接口的多继承特性(二)
原文地址:http://small.aiweimeng.top/index.php/archives/51.html 在上篇文章中写到php可以使用```Trait```实现代码的复用,下面介绍使用接 ...
随机推荐
- 从MongoDB里面取得json格式的数据,然后存为本地的json文件,然后再从json读取变为dict
帮宣传下彩印网(www.caiyin.com) 有印刷,广告等等方面的需求就找这个网站吧,没错的. 天气预报在MongoDB中的天气预报的存储方式是: /* 1 */ { "_id" ...
- wget整站抓取、网站抓取功能;下载整个网站;下载网站到本地
wget -r -p -np -k -E http://www.xxx.com 抓取整站 wget -l 1 -p -np -k http://www.xxx.com 抓取第一级 - ...
- 微信小程序生成海报分享:canvas绘制文字溢出如何换行
主要思路: 1.先分割为字符串数组,然后一个字一个字绘图,利用ctx.measureText(string) 方法,获取绘制后的宽度,判断宽度在多少内就另起一行,再将各行拼成一个字符串 2.计算另起的 ...
- 吐槽下mac的打印机设置
只有第一次使用的时候,会提示密码和用户名验证,但是如果中途修改了密码, 找了半天都找不到,给人一种挫败感. 最后是在:点击作业队列某一作业右边的刷新按钮,才会弹出验证的对话框, 可能,mac当初设计这 ...
- 【JVM】垃圾收集器
程序计数器.Java虚拟机栈.本地方法栈分配的内存是确定的,生命周期与线程同样.所以不须要过多考虑回收问题. 而Java堆和方法区仅仅有运行时才知道有哪些对象被创建,须要多少内存,这部分的内存分配和回 ...
- .NET/C# 资源
.NET/C# 开源资源收集 Roslyn ---C# 开源编译器 iSpy免费的开源视频监控平台 https://github.com/ispysoftware/iSpy .NET Fram ...
- html5学习笔记3——高级特性
一:Web存储 数据以 键/值 对存在, web网页的数据只允许该网页访问使用. web存储有两种: localStorage - 没有时间限制的数据存储,存于浏览器缓存 sessionStorage ...
- EAS开发环境搭建.
一:EAS开发环境安装 解压EAS服务器安装包到E盘即可,内含BOS开发环境. 二:EAS客户端安装 EAS8.0.exe安装到D盘,这是客户端. 三:远程数据库 使用远程运维系统,登陆数据库.
- git图解
- 微信小程序+微信管理后台+微信用户前台
代码地址如下:http://www.demodashi.com/demo/15043.html #### 微信小程序+微信管理后台+微信用户前台 #### 产品介绍 基础功能开发:景区微信地图导游.天 ...