C++学习 —— 重新认识C++
我大概是从读研究生入学那天开始,想要学好C++的,学习C++几乎也成了我每个学期的计划之一。为什么会每个学期都想要学好C++呢?因为每次学习都失败了啊。。。
本月,我开始再Coursera上学习Heterogeneous Parallel Programming 以及 北京大学的C++。也从此时开始思考C++或者说编程到底是什么,以及如何学习。
1、C++到底是什么
我以前一直以为C++是一种语言。我的女朋友很长一段时间都和我说“帮我用VC++写个程序”,显然她觉得C++就是那个VC6.0的IDE了。经过一段时间的学习,我发现C++并不完全是一种语言,它是一种标准。就像汉字,点横竖撇捺组成方块字,每个字都是标准的,你自己不许造,造了就是错别字。如果我们自己造了C++的语法,那当然编译器是不认的。C++仅仅是一堆语法吗?
不是的,C++的意义还包括了“特性”,特性和语法其实是两个层面上的东西,语法需要死记硬背,而特性则更容易被理解。C++的特性指的应该是那些比较高级的功能,继承、组合、委托、封装、泛型、模版......这些功能是为了更好的帮助我们完成程序设计。包括更少的编码,更好的管理、重用代码,更利于阅读等等。这些特性强依赖于标准,必须以标准的方式来表达,才能使用这些特性。C++强大是因为它的特性方便吗?
也不完全是,C++的强大还在于它历史悠久,效率高,有很多可以使用的“库函数”。库与特性又不一样,库更接近我们的专业知识,比如PCL, OPENCV, Boost, Eigen, BLAS, 这些都是基于C/C++的库。它离我们的专业知识仅有一步之遥。很多时候我们解决专业问题会想着使用库,然后程序编译失败,程序崩溃,最终自己也崩溃了。开始质疑人生质疑价值观。这怪C++吗?
这还真不怪C++,编译失败可能是语法不符合C++的标准,可能是使用某特性时没有很好的理解导致程序太乱,自己无法收场。可能是库函数本身不靠谱,可能时自己没有读明白库函数的API文档。可能是自己对专业知识的理解有问题,建模失败,导致程序里的变量和你期望的值不一样。
2、学习C++
C++本身强调松耦合,然后我们在学习C++的时候,各个环节却是紧耦合的... 任何一个层面出问题,都会崩盘...
我觉得学习C++应该是一个使用的过程,天天写些hello world除了能验证工具链正确,偶尔在语法层面做些验证以外,没有任何作用。关键的关键,就是需要一个足够大的项目,能够让C++的各种特性有用武之地,能够提升自己对C++特性的理解。至于标准层面的学习,应该是在编译器不停的报错中学会处理的吧。强大的面向对象工具 = 特性+标准。 这个工具和我们的专业知识,或者其他库函数并不耦合,不妨先用matlab完成专业知识的训练,一边训练C++的技能。一定曾都的时候将专业知识代码移植到C++上,来感受C++的效率以及自己的能力。
我觉得学习C++就应该从特性入手,到大型程序里取体会。没写过个一两千行代码,是没法聊C++的特性的。总而言之,I have a plan, attack.
3、面向对象
在完成第三周魔兽世界相关的作业后,我对类和对象又有了新的认识。C++需要我们做的就是抽象,不停的找到共性,具体的每个对象再分配特性。共性的部分就是类的成员变量名,特性的部分就是成员变量的取值不同。货车轿车本质是一类,只不过“载重”这个成员变量的取值不同。轿车消防车却不是一类,轿车并没有一个成员变量叫做”载水量“ 啊。C++的特性就是为了让我们能把心里想好的抽象能够实现出来。特性只能帮助我们实现脑子里的抽象,它并不能替我们抽象,自己脑子里都不知道应该怎样抽象,不能怪C++的特性难啊。总之面向对象是一种思路。
最后附上第三周作业的一些代码,这些代码不能通过考核,因为Coursera 的平台不支持C++11.
编程题#4:魔兽世界之一:备战
注意: 总时间限制: 1000ms 内存限制: 65536kB
描述
魔兽世界的西面是红魔军的司令部,东面是蓝魔军的司令部。两个司令部之间是依次排列的若干城市。
红司令部,City 1,City 2,……,City n,蓝司令部
两军的司令部都会制造武士。武士一共有 dragon 、ninja、iceman、lion、wolf 五种。每种武士都有编号、生命值、攻击力这三种属性。
双方的武士编号都是从1开始计算。红方制造出来的第n个武士,编号就是n。同样,蓝方制造出来的第n个武士,编号也是n。
武士在刚降生的时候有一个生命值。
在每个整点,双方的司令部中各有一个武士降生。
红方司令部按照iceman、lion、wolf、ninja、dragon的顺序循环制造武士。
蓝方司令部按照lion、dragon、ninja、iceman、wolf的顺序循环制造武士。
制造武士需要生命元。
制造一个初始生命值为m的武士,司令部中的生命元就要减少m个。
如果司令部中的生命元不足以制造某个按顺序应该制造的武士,那么司令部就试图制造下一个。如果所有武士都不能制造了,则司令部停止制造武士。
给定一个时间,和双方司令部的初始生命元数目,要求你将从0点0分开始到双方司令部停止制造武士为止的所有事件按顺序输出。
一共有两种事件,其对应的输出样例如下:
1) 武士降生
输出样例: 004 blue lion 5 born with strength 5,2 lion in red headquarter
表示在4点整,编号为5的蓝魔lion武士降生,它降生时生命值为5,降生后蓝魔司令部里共有2个lion武士。(为简单起见,不考虑单词的复数形式)注意,每制造出一个新的武士,都要输出此时司令部里共有多少个该种武士。
2) 司令部停止制造武士
输出样例: 010 red headquarter stops making warriors
表示在10点整,红方司令部停止制造武士
输出事件时:
首先按时间顺序输出;
同一时间发生的事件,先输出红司令部的,再输出蓝司令部的。
输入
第一行是一个整数,代表测试数据组数。
每组测试数据共两行。
第一行:一个整数M。其含义为, 每个司令部一开始都有M个生命元( 1 <= M <= 10000)。
第二行:五个整数,依次是 dragon 、ninja、iceman、lion、wolf 的初始生命值。它们都大于0小于等于10000。
输出
对每组测试数据,要求输出从0时0分开始,到双方司令部都停止制造武士为止的所有事件。
对每组测试数据,首先输出"Case:n" n是测试数据的编号,从1开始 。
接下来按恰当的顺序和格式输出所有事件。每个事件都以事件发生的时间开头,时间以小时为单位,有三位。
样例输入
1
20
3 4 5 6 7
样例输出
Case:1
000 red iceman 1 born with strength 5,1 iceman in red headquarter
000 blue lion 1 born with strength 6,1 lion in blue headquarter
001 red lion 2 born with strength 6,1 lion in red headquarter
001 blue dragon 2 born with strength 3,1 dragon in blue headquarter
002 red wolf 3 born with strength 7,1 wolf in red headquarter
002 blue ninja 3 born with strength 4,1 ninja in blue headquarter
003 red headquarter stops making warriors
003 blue iceman 4 born with strength 5,1 iceman in blue headquarter
004 blue headquarter stops making warriors
1 #include <iostream> 2 #include <vector> 3 #include <string> 4 #include <iomanip> 5 using namespace std; 6 7 8 class warrior{ 9 public: 10 warrior(int life_,string name_,int num_=0):life(life_),name(name_),num(num_){} 11 int getLife() const {return this->life;} 12 string getName() const {return this->name;} 13 int getNum() const {return this->num;} 14 void addOne(){this->num += 1;} 15 private: 16 int num; 17 const string name; 18 const int life; 19 }; 20 21 22 class headquarter{ 23 public: 24 headquarter(const string quarterName_,int ALLLIFE_,vector<warrior> warriorList_):quarterName(quarterName_), 25 ALLLIFE(ALLLIFE_), 26 warriorList(warriorList_){} 27 bool warriorBurn(int time); 28 private: 29 inline void __successPrint(int time,const warrior ¤t_warrior) const; 30 inline bool __warriorBurn(warrior & burnwarrior); 31 32 const string quarterName; 33 int ALLLIFE; 34 vector<warrior> warriorList; 35 }; 36 37 38 void headquarter::__successPrint(int time,const warrior ¤t_warrior) const{ 39 40 cout<< setfill('0') << setw(3) << time; 41 cout<<' ' 42 <<this->quarterName 43 <<' '<<current_warrior.getName() 44 <<' ' 45 <<(time+1) 46 <<" with strength" 47 <<current_warrior.getLife() 48 <<", " 49 <<current_warrior.getNum() 50 <<' ' 51 <<current_warrior.getName() 52 <<" in" 53 <<this->quarterName 54 <<" headquarter" 55 <<endl; 56 } 57 58 bool headquarter::warriorBurn(int time){ 59 60 int current = time; 61 while(!__warriorBurn(warriorList.at(time%5))) 62 { 63 time++; 64 if(current+5 == time) 65 { 66 cout<<this->quarterName<<" stop making warriors"<<endl; 67 return false; 68 } 69 } 70 this->__successPrint(current,warriorList.at(time%5)); 71 return true; 72 } 73 74 75 bool headquarter::__warriorBurn(warrior & burnwarrior){ 76 77 int totalLife = ALLLIFE; 78 totalLife -= burnwarrior.getLife(); 79 if(totalLife > 0) 80 { 81 ALLLIFE = totalLife; 82 burnwarrior.addOne(); 83 return true; 84 } 85 return false; 86 } 87 88 89 int main(int argc, char const *argv[]) 90 { 91 92 93 94 int Case; 95 int alllife,lionlife,ninjialife,dragonlife,wolflife,icemanlife; 96 97 cin>>Case; 98 cin>>alllife; 99 cin>>dragonlife>>ninjialife>>icemanlife>>lionlife>>wolflife; 100 cout<<"case:"<<Case<<endl; 101 102 103 104 warrior lion(lionlife,"lion"); 105 warrior ninja(ninjialife,"ninja"); 106 warrior dragon(dragonlife,"dragon"); 107 warrior wolf(wolflife,"wolf"); 108 warrior iceman(icemanlife,"iceman"); 109 110 std::vector<warrior> red_list; 111 red_list.push_back(iceman); 112 red_list.push_back(lion); 113 red_list.push_back(wolf); 114 red_list.push_back(ninja); 115 red_list.push_back(dragon); 116 117 118 std::vector<warrior> blue_list; 119 blue_list.push_back(lion); 120 blue_list.push_back(dragon); 121 blue_list.push_back(ninja); 122 blue_list.push_back(iceman); 123 blue_list.push_back(wolf); 124 125 headquarter red("red",alllife,red_list); 126 headquarter blue("blue",alllife,blue_list); 127 128 int time = 0; 129 bool red_result = true; 130 bool blue_result = true; 131 while(1) 132 { 133 if(red_result) 134 red_result = red.warriorBurn(time); 135 if(blue_result) 136 blue_result = blue.warriorBurn(time); 137 if(red_result || blue_result) 138 { 139 time++; 140 continue; 141 } 142 break; 143 } 144 145 return 0; 146 }