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 降生。
1 #include 2 #include 3 #include 4 #include 5 6 using namespace std; 7 8 class warrior{ 9 public: 10 warrior(int life_,string name_):life(life_),name(name_){ 11 armList.push_back("sword"); 12 armList.push_back("bomb"); 13 armList.push_back("arrow"); 14 } 15 int getLife() const { return this->life;} 16 string getName() const { return this->name;} 17 virtual int getNum() const = 0; 18 virtual void create(int alllife,int bianhao_) = 0; 19 void CommonBurnPrint(int special_num) const{ 20 cout<<' '< armList; 41 }; 42 43 44 class Lion: public warrior{ 45 public: 46 Lion(int life_):warrior(life_,"lion"){} 47 void create(int alllife,int bianhao_) { 48 num++; 49 loyal = alllife; 50 bianhao = bianhao_; 51 52 } 53 int getNum() const { return num;} 54 int getLoyal()const{ return loyal;} 55 void selfBurnPrint() const {cout<<"its loyalty is "< <
warriorList_,int * warriorlife_):quarterName(quarterName_),141 ALLLIFE(ALLLIFE_),142 warriorList(warriorList_),143 warriorlifeLists(warriorlife_){}144 bool warriorBurn(int time);145 private:146 inline bool __warriorBurn(int warrior_no);147 const string quarterName;148 int ALLLIFE;149 warrior * Warrior;150 std::vector
warrior_house;151 std::vector warriorList;152 int * warriorlifeLists;153 };154 155 156 157 bool headquarter::warriorBurn(int time){158 159 int current = time;160 cout<< setfill('0') << setw(3) << time<<" ";161 while(!__warriorBurn(warriorList.at(time%5)))162 {163 time++;164 if(current+5 == time)165 {166 cout< quarterName<<" stop making warriors"< getLife();205 if(totalLife > 0)206 {207 ALLLIFE = totalLife; 208 209 int bianhao = warrior_house.size()+1;210 Warrior->create(ALLLIFE,bianhao); 211 212 cout< quarterName;213 214 Warrior->CommonBurnPrint(Warrior->getNum());215 216 cout<<" in "217 < quarterName218 <<" headquarter"219 < selfBurnPrint();222 223 warrior_house.push_back(Warrior);224 225 return true;226 }227 return false;228 }229 230 231 int main(int argc, char const *argv[])232 {233 234 235 236 int Case;237 int alllife,lionlife,ninjialife,dragonlife,wolflife,icemanlife;238 239 cin>>Case;240 cin>>alllife;241 cin>>dragonlife>>ninjialife>>icemanlife>>lionlife>>wolflife; 242 cout<<"case:"< < red_list;265 red_list.push_back(iceman_No);266 red_list.push_back(lion_No);267 red_list.push_back(wolf_No);268 red_list.push_back(ninja_No);269 red_list.push_back(dragon_No);270 271 272 std::vector
blue_list;273 blue_list.push_back(lion_No);274 blue_list.push_back(dragon_No);275 blue_list.push_back(ninja_No);276 blue_list.push_back(iceman_No);277 blue_list.push_back(wolf_No);278 279 headquarter red("red",alllife,red_list,warriorLife);280 headquarter blue("blue",alllife,blue_list,warriorLife);281 282 int time = 0;283 bool red_result = true;284 bool blue_result = true;285 while(1)286 { 287 if(red_result)288 red_result = red.warriorBurn(time);289 if(blue_result)290 blue_result = blue.warriorBurn(time);291 if(red_result || blue_result)292 {293 time++;294 continue;295 }296 break;297 }298 299 return 0;300 301 }