C++是早晚要过的坎,为了JNI,还是稍微拾起来一些吧。
我想用最简单的事物,讲述最复杂的道理,用最有趣的方式,引导最无聊的你。
前言:本故事纯属虚构
背景1988年,龙少参加
星宇国际
的面试,因为打印出了"Hello, World!"而震惊全场,立刻得到offer.
林兮,20岁(
选择困难症,需求改不断
)
龙少,20岁(会打印输出语句的初级工程师
)
捷特,21岁(拥有面向对象的思想中级工程师
)
1.打印语句
捷特:
龙少,C++学的怎么样?
龙少:感觉很不错,现在我都能打印Hello,World了
捷特:不错不错,再接再厉
#include <iostream> int main() { std::cout << "Hello, World!" << std::endl; return 0; } ---->[打印]---- Hello, World!
林夕:
用C++给我画个脸
龙少:给你一个嘟嘴的脸
int main() { std::cout << "----------" << std::endl; std::cout << "| - - |" << std::endl; std::cout << "| . . |" << std::endl; std::cout << "| -} |" << std::endl; std::cout << "----------" << std::endl; return 0; }
林夕:
不怎么好看,把-改成~,我来瞅瞅
龙少:好嘞,这简单,一个个字符改一下就OK了
int main() { std::cout << "~~~~~~~~~~" << std::endl; std::cout << "| ~ ~ |" << std::endl; std::cout << "| . . |" << std::endl; std::cout << "| -} |" << std::endl; std::cout << "~~~~~~~~~~" << std::endl; return 0; }
林夕:
算了,改回来吧,这样好搓
龙少:你莫不是在玩老子?一个个字符改一下...TM真麻烦
int main() { std::cout << "----------" << std::endl; std::cout << "| - - |" << std::endl; std::cout << "| . . |" << std::endl; std::cout << "| -} |" << std::endl; std::cout << "----------" << std::endl; return 0; }
林夕:
我仔细想了一下,从美学的角度,上用波浪,下用直线,眉毛也用波浪会更好。
龙少:老哥你到底想咋样,改来改去,很累的好嘛。
林夕:还不错,先这样,去午休吧,下午再说。
int main() { std::cout << "~~~~~~~~~~" << std::endl; std::cout << "| ~ ~ |" << std::endl; std::cout << "| . . |" << std::endl; std::cout << "| -} |" << std::endl; std::cout << "----------" << std::endl; return 0; }
龙少中午愤愤不平地将这件事告诉捷特
捷特:如果是上下一百行,你还能一个个改吗?
龙少:如果这样,我只写一遍,谁让我改,我跟谁急。
捷特:哎,年轻人就是心浮气躁。我来教你提取变量和for循环
2.for循环
在捷特的指导下,龙少将代码用for循环重构
#include <iostream> using namespace std; int main() { auto top="~"; for (int i = 0; i < 10; ++i) { i!=9?cout << top: cout << top<<endl; } std::cout << "| ~ ~ |" << std::endl; std::cout << "| . . |" << std::endl; std::cout << "| -} |" << std::endl; std::cout << "~~~~~~~~~~" << std::endl; return 0; }
龙少:
虽然正确,但看着有点糟心,感觉比我的代码复杂了好多啊。
捷特:简单必有简单的成本,复杂必有复杂的价值。
如果林夕再让你改上面,你只要改一处就行了。
int main() { auto top="#"; //英雄所见... }
龙少:
咦,果然,这样就少改9次,爽歪歪。
捷特:那下面你也照样子改一下。
虽说龙少是个萌新,但理解力还是非常好的。秒写:
int main() { auto top="#"; auto bottom="-"; for (int i = 0; i < 10; ++i) { i!=9?cout << top: cout << top<<endl; } std::cout << "| ~ ~ |" << std::endl; std::cout << "| . . |" << std::endl; std::cout << "| -} |" << std::endl; for (int i = 0; i < 10; ++i) { i!=9?cout << bottom: cout << bottom<<endl; } return 0; }
甚至这小子还能举一反三:
int main() { auto top="#"; auto bottom="-"; auto brow="~"; auto eyes="X"; for (int i = 0; i < 10; ++i) { i!=9?cout << top: cout << top<<endl; } cout << "| "<< brow <<" "<< brow <<" |" << endl; cout << "| "<< eyes <<" "<< eyes <<" |" << endl; cout << "| -} |" << endl; for (int i = 0; i < 10; ++i) { i!=9?cout << bottom: cout << bottom<<endl; } return 0; }
捷特:优秀如你,一看就是学编程的料,不过给你一点建议,勤加注释。
龙少:好,老哥说加,我就加。虽然已经面目全非,但是真的挺好用啊,下午我可以不用怕林夕了。
捷特:呵呵,你太小瞧产品的需求力了。
3.函数封装
捷特:
如果打印两个脸该怎么办?
龙少:对于CV工程师,这易如反掌。
int main() { auto top="#";//顶部 auto bottom="-";//底部 auto brow="~";//眉毛 auto eyes="X";//眼睛 //打印第一个脸 for (int i = 0; i < 10; ++i) { i!=9?cout << top: cout << top<<endl; } cout << "| "<< brow <<" "<< brow <<" |" << endl; cout << "| "<< eyes <<" "<< eyes <<" |" << endl; cout << "| -} |" << endl; for (int i = 0; i < 10; ++i) { i!=9?cout << bottom: cout << bottom<<endl; } //打印第二个脸 for (int i = 0; i < 10; ++i) { i!=9?cout << top: cout << top<<endl; } cout << "| "<< brow <<" "<< brow <<" |" << endl; cout << "| "<< eyes <<" "<< eyes <<" |" << endl; cout << "| -} |" << endl; for (int i = 0; i < 10; ++i) { i!=9?cout << bottom: cout << bottom<<endl; } return 0; }
捷特:
我们要有世界设计师的自尊,决不能称自己是CV工程师。
龙少:本来就是嘛,我们不就是将别的东西抄抄改改吗。
捷特无奈摇摇头:哎,现在的年轻人啊。这样,如果要打印两个脸不一样怎么办?
龙少:你是说再定义一组变量?
捷特无奈:那打印100个脸,你的代码还能不能看了?
龙少:100个...我选择死亡....
捷特:是时候让函数帮你了,它可以封装若干条语句,并且可以通过参数控制语句。
#include <iostream> //声明函数 void printFace(const char *top, const char *bottom, const char *brow, const char *eyes); using namespace std; int main() { printFace("#", "-", "~", "X"); printFace("O", "N", ".", "$"); return 0; } /** * 打印一个脸 * @param top 顶部 * @param bottom 底部 * @param brow 眉毛 * @param eyes 眼睛 */ void printFace(const char *top, const char *bottom, const char *brow, const char *eyes) { for (int i = 0; i < 10; ++i) { i!=9?cout << top: cout << top<<endl; } cout << "| "<< brow <<" "<< brow <<" |" << endl; cout << "| "<< eyes <<" "<< eyes <<" |" << endl; cout << "| -} |" << endl; for (int i = 0; i < 10; ++i) { i!=9?cout << bottom: cout << bottom<<endl; } }
龙少:
难以置信,竟然还有这种操作,调用printFace,传入四个字符就行了
捷特:现在有没有对C++有一点更深的认识?
龙少连连点头。下午面对林夕的百般刁难,龙少轻松搞定。
林夕纳闷:哥还治不了你,打印得太小了,给我放大一倍。
龙少:你怎么不让老鼠变大去抓猫
。两人小吵一架,下班后不欢而散。
4.类的封装
捷特和龙少是邻居,也是从小到大的玩伴。两个一起坐公交回家。
龙少:你给评评理,是不是他刁钻了。
捷特:确实有点,不过这也确实是个需求。先不说这个,给你说说面向对象编程。
龙少:哎,单身狗一个,哪有机会面向对象编程。
捷特:不是那个对象,你看,我们现在在坐公交对吧,为什么不自己走?
龙少:十几里路,你傻啊,腿走断了,太麻烦。
捷特:为什么不自己造一个公交车,自己开?
龙少:成本啊,坐个公交三毛三,造个公交少说几十万,够坐一辈子了。
捷特:所以我们只要通过 bus.go(0.33),就可以很简单的到家,其实编程里也有这种思想,就是面向对象。如果有一个Facer的小伙伴,你只需要通过它的printFace()就可以打印出一个脸,你想不想认识他? 就像这样:
#include "Facer.h" using namespace std; int main() { Facer face("#", "-", "~", "X"); face.printFace(); face.bottom="V"; face.printFace(); return 0; }
龙少:
感觉挺棒的,要的要的。快告诉我怎么实现?
首先定义一个头文件
Facer.h
,来说明Facer的属性(字段)和能力(方法)
#include <iostream> using namespace std; #ifndef TOLYC_FACER_H #define TOLYC_FACER_H class Facer { public: Facer(const string &top="#", const string &bottom="#", const string &brow="~", const string &eyes="."); ~Facer(); public: string top; string bottom; string brow; string eyes; public: void printFace() ; }; #endif //TOLYC_FACER_H
在
Facer.cpp
中实现构造、析构方法以及功能方法的实现。
#include "Facer.h" Facer::Facer( const string &top, const string &bottom, const string &brow, const string &eyes) : top(top), bottom(bottom), brow(brow), eyes(eyes) {} void Facer::printFace() { for (int i = 0; i < 10; ++i) { i != 9 ? cout << top : cout << top << endl; } cout << "| " << brow << " " << brow << " |" << endl; cout << "| " << eyes << " " << eyes << " |" << endl; cout << "| -} |" << endl; for (int i = 0; i < 10; ++i) { i != 9 ? cout << bottom : cout << bottom << endl; } } Facer::~Facer() { }
龙少:
我明白了,这挺简单嘛,面向对象不过如此。
捷特:too yong too simple,这只是面向对象的冰山一角,以后有机会我跟你好好说说。这里用cout处理并不灵活,我们可以使用字符串进行拼接,再一次打印。
// // Created by 张风捷特烈 on 2019/10/3. // #include <iostream> using namespace std; #ifndef TOLYC_FACER_H #define TOLYC_FACER_H class Facer { public: Facer(const string &top="#", const string &bottom="#", const string &brow="~", const string &eyes="."); ~Facer(); public: string top; string bottom; string brow; string eyes; public: void printFace() ; string getFace(); }; #endif //TOLYC_FACER_H
// // Created by 张风捷特烈 on 2019/10/3. // #include "Facer.h" Facer::Facer( const string &top, const string &bottom, const string &brow, const string &eyes) : top(top), bottom(bottom), brow(brow), eyes(eyes) {} void Facer::printFace() { cout<< getFace() << endl; } Facer::~Facer() { } string Facer::getFace() { string result; for (int i = 0; i < 10; ++i) { i != 9 ? result+=top : result+=top+"\n"; } result+= "| " +brow + " " + brow + " |" +"\n"; result+= "| " +eyes + " " + eyes + " |" +"\n"; result+= "| -} |\n"; for (int i = 0; i < 10; ++i) { i != 9 ? result+=bottom : result+=bottom+"\n"; } return result; }