最近在啃Effective C++。
虽然一直以来都很喜欢写C++(其实是不会其他语言),也确实体会到C++语言的各种好处(清晰的变量类型,灵活的内存处理,强大的STL等等等等),但发现确实对面向对象的C++没有任何好感。
主要是书里面讲到的太多解决问题的“巧妙”方法,在我看来却是太投机取巧了。换言之,我认为如果非要这样才能写出高效的代码,那对程序员的要求实在是太苛刻了,况且这里还没有涉及实际项目的要求以及和他人的协作。当然,这本书还是让我明白到了C++设计时的一些思想,这是仅仅粗读C++ primer所无法领会的。
自己的一点粗浅体会,也写在这里吧:总体感觉就是,C++最初被设计出来时,是在考虑执行效率的前提下为程序员尽可能地提供了自由的功能实现方案。然而随着时间的推移,越来越多的技术被发明/发现出来,而C++也在不断进行扩充。直到今天在我学习的时候,发现她身上存在着太多的历史包袱,从一开始的继承C的语法以及面向过程,到后面的面向对象和模板泛型编程,虽然包罗万有,却又让人无所适从。做项目不比做题目,当一个庞大系统要实现出来时,往往代码的规范一致性和可维护性要比执行效率更重要,这也导致了很多高效的写法事实上无法应用于工程。而且,作为一门古老的语言,它提供的很多功能其实是累赘的(例如在本书P151中作者明确表示“protect继承的意义至今仍然困惑我”),并不能真正反映软件设计的需求。
相比起来,更为“现代”的语言,比如pyhton,在这一点上做得要好很多。其开发者相信“应当只用一种——而且是最好的一种——明确的方式去做一件事。”(“There should be one – and preferably only one – obvious way to do it.”),大概也是其得到广泛普及的重要原因。但个人认为,就语言学习来说,python这种“单调”的语法也对暂时不需要写项目的我没有太大吸引力。接下来想看的是Ruby作者写的松本行弘的程序世界。
还是贴几段书中有趣的小例程,第一次知道C++还可以这么写:
模板编程(这里最多只能500,不知道为何):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
#include<iostream> using namespace std; template<int n> struct F { enum { value = 1 + F<n-1>::value }; }; template<> struct F<0> { enum { value = 1 }; }; int main() { cout << F<500>::value << endl; return 0; } |
用boost的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#include<iostream> #include<vector> #include<boost/lambda/lambda.hpp> using namespace boost::lambda; int d[]={ 2, 7, 1, 8, 2, 8 }; std::vector<int> v(d, d+6); int main() { std::for_each(v.begin(), v.end(), std::cout << _1 * 2 + 10 << "\n"); return 0; } |
以及:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#include <boost/random/random_device.hpp> #include <boost/random/uniform_int_distribution.hpp> int main() { std::string chars( "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "1234567890" "!@#$%^&*()" "`~-_=+[{]{\\|;:'\",<.>/? "); boost::random::random_device rng; boost::random::uniform_int_distribution<> index_dist(0, chars.size() - 1); for(int i = 0; i < 8; ++i) { std::cout << chars[index_dist(rng)]; } std::cout << std::endl; } |
编译这个还要专门写makefile(用的是os x下brew安装的boost库):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
CC = g++ BASE_FLAGS = -g -wAll # INCLUDE BASE DIRECTORY AND BOOST DIRECTORY FOR HEADERS LDFLAGS = -I/usr/local/Cellar/boost/1.54.0/include # INCLUDE BASE DIRECTORY AND BOOST DIRECTORY FOR LIB FILES LLIBFLAGS = -L/usr/local/Cellar/boost/1.54.0/lib # SPECIFIY LINK OPTIONS LINKFLAGS = -lboost_system-mt -lboost_random-mt # FINAL FLAGS -- TO BE USED THROUGHOUT FLAGS = $(BASE_FLAGS) $(LLIBFLAGS) $(LDFLAGS) $(LINKFLAGS) # NOTE FOR BOOST -- YOU ONLY NEED TO INCLUDE THE PATH BECAUSE IT ONLY INSTALLS HEADER FILES main: main.cpp $(CC) $(FLAGS) -o main.out main.cpp |
但貌似用clang编译时还是报找不到库…不管了反正不用xcode