《高效编程十八式》(9/13)代码编辑
2012-01-10 19:19
204 查看
代码编辑
王伟冰下面列举一些代码编辑器常用的功能,如果你正在使用的代码编辑器有此功能,请充分利用,这样可以提高写代码的效率。没有的话就算了。
添加:
自动补全:键入单词的前几个字母,自动插入整个单词。
代码模板:插入一些常用的代码结构或程序框架。
方便查看:
自动格式化:不用你自己敲Tab缩进代码,自动缩进。
折叠代码块:一个文件太多行时,把一些类和函数的代码折叠起来。
跳转:
类视图:列出当前工程的所有类和成员,可随意跳转到任一个类或成员所在的代码。
书签:在经常改动的代码放一个书签,要找就比较容易。
转到定义或声明:选中一个变量或函数或类,跳转到它定义或声明的地方。
键盘跳转:最典型如VIM,通过丰富的命令来实现各种快捷的跳转。
重构:
重构,指的是不改变代码的功能,但改变其具体实现。前面几节讨论的很多例子其实都涉及重构。比如复数类,把c.add(a,b)改成c=add(a,b),功能没变,但实现方式变了,看起来更为清晰,这就是一种重构。又如数据统计,把m=count(a,30,60)改成m=count(a,30, Func1(60)),也是一种重构,功能没变,但是使用起来可以更灵活了,这也是一种重构。
重构是整个程序开发过程要不断做的事情。因为很多情况下你往往不能在一开始就清楚什么样的设计是最佳的,而且将会使用这个程序的用户的需求也往往是变化的。所以如果只是一味地向程序添加新功能,那么整个程序的架构可能会越来越混乱,越来越难以维护。就好比我们电脑磁盘中的文件,如果我们总是随意存放新文件,那么时间一长就会很乱,有些东西你就忘记放在哪个文件夹里了,所以时不时要整理整理。写程序也是,时不时要进行重构,虽然没有改变它的功能,但是可以使它变得更清晰、更灵活,方便添加新功能。
大多数的重构还是要手工完成的,但有些简单的可以用代码编辑器来做:
文本替换:经常用于变量、类、函数的重命名,但是要非常小心,因为这只是简单地做文本替换,把变量f替换成F会把printf也替换成printF。
智能重命名:有些编辑器可以做到,比如上例,通过推理识别出哪些f才代表真正的变量f,就不会出现上面的问题了。
重新排列函数参数的顺序:重排后,所有调用这个函数的代码都会自动重新排列。
提升局部变量为函数参数:比如第二节的最开始的部分,把60提升为函数参数min,有些编辑器能自动把调用count函数的代码修改过来,比如原来是count(a,30),就改成count(a,30,60)。
……
尽管如此,代码编辑器所能够做的重构还是很有限。我认为未来的代码编辑器应该往更为智能的重构方面发展。
我认为代码编辑器还应该支持重构的导入和导出,但是似乎现在还没有哪个代码编辑器做到这一点。比如A同学写了一个类库,把它发布到网上,B同学在自己的程序里使用到了A的类库。后来,A同学对类库进行了升级,改进了架构,但是某些类的接口发生了变化,比如有些函数的名字发生了变化,参数个数发生了变化。B同学如果想让原来的程序使用上A同学的新类库,那就要对程序里所有使用到这些类的代码进行修改,那显然很麻烦。所以编程的接口一旦制定,是很难修改的。Win32的API函数,十几年了还是那个样子,因为一旦修改,很多程序就无法在Windows上运行了。但是如果重构可以导入和导出,A同学就可以把它对类库接口所做的更改导出为一个文件,随新类库一起发布,B同学让代码编辑器导入这个文件,自动对B的程序中的代码进行更改,然后重新编译就行了。
这一节的题目叫“代码编辑”,不过好像没有太多可说的。不如说一些别的:C++模板元编程。
什么是元编程?来看一个例子,比如我们要算n的阶乘,可以用下面的递归函数:
void factorial(int n){
if(n==0)return 1;
else return n*factorial(n-1);
}
但是你还可以用模板来实现:
template<int N>
struct factorial{ //默认情况下用这个版本
static const int value=N*factorial<N-1>::value;
};
template<>
struct factorial<0>{ //N=0时用这个特化版本
static const int value=1;
};
上面的代码的意思就是:
如果N=0,则使用factorial的特化版本,factorial<N>::value=1;
否则使用factorial的普通版本,factorial<N>::value =N*factorial<N-1>::value;
所以,factorial<3>::value就表示3的阶乘。
用模板来计算阶乘,和用函数来计算阶乘,有什么不同呢?不同就在于,前者是在程序编译的时候进行计算的,而后者是在程序运行的时候进行计算的,经过编译之后,factorial<3>::value就会变成6。所以你不能这样:
int x=3;
int y=factorial<x>::value;
因为x的值只有在运行的时候才知道,所以上面的代码编译不通过。
这种在编译时进行计算的程序就称为“元程序”。通过把一些运行时的计算提前到编译时来完成,可以提高程序运行时的性能(当然,编译速度就会变慢)。甚至有人证明,C++的模板元编程是图灵完备的,也就是说,所有普通程序能够完成的计算,元程序也能完成。
除了能够对数值进行计算,元编程还可以对类型进行计算,这是普通编程做不到的。比如判断两个类型是否相等,你总不能用if(int==double)…吧!但是下面的代码可以对类型进行比较:
template<class T1,class T2>
struct is_same{ //默认情况下用这个版本
static const bool value=false;
};
template<class T1>
struct is_same<T1,T1>{
//T1和T2相等时用这个版本
static const bool value=true;
};
上面的代码的意思就是:
如果T1和T2相等,则使用is_same的特化版本,is_same <T1,T2>::value=true;
否则使用is_same的普通版本,is_same <T1,T2>::value=false;
于是is_same<int,doube>::value就是false,is_same<int,int>::value的值就是true。
可是类型计算有什么意义?难道我不知道int和double相不相等?看一个应用的例子。假设我们写了一个模板类class1,这个类具体做什么不重要,我们只知道它的某个函数func里,需要对浮点型的数值进行特别的处理,而对其它的类型不需要特别处理,那么可以这样:
template<class T>
class class1{
……
void func(){
if(is_same<T,double>::value || is_same<T,float>::value){
……
//如果T是double或float型,则做一些特别处理
}
……
//默认情况下做的操作
}
};
C++模板元编程,是C++最高深的部分,这里举的都是最简单的例子,涉及的都只是皮毛。C++模板强大的类型运算能力,弥补了C++无法在运行时获取类型信息的缺陷。对于能够在运行时获取类型信息的语言,像C#,提供了对元编程的原生支持,如typeof(int) ==typeof(double),很直观地比较两个类型。当然,由于是在运行时实现的,它的性能肯定不如C++。
相关文章推荐
- Xamarin iOS教程之编辑界面编写代码
- 【phpcms-v9】后台编辑碎片时会自动篡改你的代码
- 软件著作权申请中源代码文档的编辑方法
- 【C代码练习13】求符合给定条件的整数集
- iOS编辑图片位图的代码
- vim编辑lua代码配置
- php access 数据连接与读取保存编辑数据的实现代码
- 测试代码编辑
- ABAP--如何限制REUSE_ALV_GRID_DISPLAY_LVC函数的某行某列的编辑(代码样例)
- 修改Eclipse 代码编辑界面主题为黑色主题
- 12小时进制的时间输出的编辑代码
- Mac本地编辑服务器代码
- GridView 实现自定义分页、排序、查询、添加、编辑、多选删除 之代码规范
- PHP插入数据库代码,编辑,删除
- vim for dos编辑汇编语言代码简易教程
- JAVA功能代码《13》----在Java中调整数组大小
- 代码在线编辑器发布 – 支持在线编辑/保存HTML代码
- js实现编辑框用户名 密码 日期选择 按钮提交特效代码
- RunJs 在线编辑JavaScript 代码