没有合适的资源?快使用搜索试试~ 我知道了~
Effective C++ 第2版(中文版).pdf
需积分: 0 0 下载量 80 浏览量
2012-09-14
00:33:12
上传
评论
收藏 516KB PDF 举报
温馨提示
试读
304页
很好的c++资料,高清带书签哦。程序中程序中
资源详情
资源评论
资源推荐
从 C 转向 C++
对每个人来说,习惯 C++需要一些时间,对于已经熟悉 C 的程序员来说,
这个过程尤其令人苦恼。因为 C 是 C++的子集,所有的 C 的技术都可以继续使
用,但很多用起来又不太合适。例如,C++程序员会认为指针的指针看起来很
古怪,他们会问:为什么不用指针的引用来代替呢?
C 是一种简单的语言。它真正提供的只有有宏、指针、结构、数组和函数。
不管什么问题,C 都靠宏、指针、结构、数组和函数来解决。而 C++不是这样。
宏、指针、结构、数组和函数当然还存在,此外还有私有和保护型成员、函数
重载、缺省参数、构造和析构函数、自定义操作符、内联函数、引用、友元、
模板、异常、名字空间,等等。用 C++比用 C 具有更宽广的空间,因为设计时
有更多的选择可以考虑。
在面对这么多的选择时,许多 C 程序员墨守成规,坚持他们的老习惯。一
般来说,这也不是什么很大的罪过。但某些 C 的习惯有悖于 C++的精神本质,
他们都在下面的条款进行了阐述。
条款 1:尽量用 const 和 inline 而不用#define
这个条款最好称为:“尽量用编译器而不用预处理”,因为#define 经常被认
为好象不是语言本身的一部分。这是问题之一。再看下面的语句:
#define ASPECT_RATIO 1.653
编译器会永远也看不到 ASPECT_RATIO 这个符号名,因为在源码进入编译器
之前,它会被预处理程序去掉,于是 ASPECT_RATIO 不会加入到符号列表中。
如果涉及到这个常量的代码在编译时报错,就会很令人费解,因为报错信息指
的是 1.653,而不是 ASPECT_RATIO。如果 ASPECT_RATIO 不是在你自己写
的头文件中定义的,你就会奇怪 1.653 是从哪里来的,甚至会花时间跟踪下去。
这个问题也会出现在符号调试器中,因为同样地,你所写的符号名不会出现在
符号列表中。
解决这个问题的方案很简单:不用预处理宏,定义一个常量:
const double ASPECT_RATIO = 1.653;
这种方法很有效。但有两个特殊情况要注意。
首先,定义指针常量时会有点不同。因为常量定义一般是放在头文件中(许
多源文件会包含它),除了指针所指的类型要定义成 const 外,重要的是指针也
经常要定义成 const。例如,要在头文件中定义一个基于 char*的字符串常量,
你要写两次 const:
const char * const authorName = "Scott Meyers";
关于 const 的含义和用法,特别是和指针相关联的问题,参见条款 21。
另外,定义某个类(class)的常量一般也很方便,只有一点点不同。要把常
量限制在类中,首先要使它成为类的成员;为了保证常量最多只有一份拷贝,
还要把它定义为静态成员:
class GamePlayer {
private:
static const int NUM_TURNS = 5; // constant declaration
int scores[NUM_TURNS]; // use of constant
...
};
还有一点,正如你看到的,上面的语句是 NUM_TURNS 的声明,而不是定义,
所以你还必须在类的实现代码文件中定义类的静态成员:
const int GamePlayer::NUM_TURNS; // mandatory definition;
// goes in class impl. file
你不必过于担心这种小事。如果你忘了定义,链接器会提醒你。
旧一点的编译器会不接受这种语法,因为它认为类的静态成员在声明时定
义初始值是非法的;而且,类内只允许初始化整数类型(如:int, bool, char 等),
还只能是常量。
在上面的语法不能使用的情况下,可以在定义时赋初值:
class EngineeringConstants { // this goes in the class
private: // header file
static const double FUDGE_FACTOR;
...
};
// this goes in the class implementation file
const double EngineeringConstants::FUDGE_FACTOR = 1.35;
大多数情况下你只要做这么多。唯一例外的是当你的类在编译时需要用到
这个类的常量的情况,例如上面 GamePlayer::scores 数组的声明(编译过程中
编译器一定要知道数组的大小)。所以,为了弥补那些(不正确地)禁止类内进行
整型类常量初始化的编译器的不足,可以采用称之为“借用 enum”的方法来解
决。这种技术很好地利用了当需要 int 类型时可以使用枚举类型的原则,所以
GamePlayer 也可以象这样来定义:
class GamePlayer {
private:
enum { NUM_TURNS = 5 }; // "the enum hack" — makes
// NUM_TURNS a symbolic name
// for 5
int scores[NUM_TURNS]; // fine
...
};
除非你正在用老的编译器(即写于 1995 年之前),你不必借用 enum。当然,
知道有这种方法还是值得的,因为这种可以追溯到很久以前的时代的代码可是
不常见的哟。
回到预处理的话题上来。另一个普遍的#define 指令的用法是用它来实现那
些看起来象函数而又不会导致函数调用的宏。典型的例子是计算两个对象的最
大值:
#define max(a,b) ((a) > (b) ? (a) : (b))
这个语句有很多缺陷,光想想都让人头疼,甚至比在高峰时间到高速公路去开
车还让人痛苦。
无论什么时候你写了象这样的宏,你必须记住在写宏体时对每个参数都要
加上括号;否则,别人调用你的宏时如果用了表达式就会造成很大的麻烦。但
是即使你象这样做了,还会有象下面这样奇怪的事发生:
int a = 5, b = 0;
max(++a, b); // a 的值增加了 2 次
max(++a, b+10); // a 的值只增加了 1 次
这种情况下,max 内部发生些什么取决于它比较的是什么值!
幸运的是你不必再忍受这样愚笨的语句了。你可以用普通函数实现宏的效
率,再加上可预计的行为和类型安全,这就是内联函数(见条款 33):
inline int max(int a, int b) { return a > b ? a : b; }
不过这和上面的宏不大一样,因为这个版本的 max 只能处理 int 类型。但模板
可以很轻巧地解决这个问题:
template<class T>
inline const T& max(const T& a, const T& b)
{ return a > b ? a : b; }
这个模板产生了一整套函数,每个函数拿两个可以转换成同种类型的对象
进行比较然后返回较大的(常量)对象的引用。因为不知道 T 的类型,返回时传
递引用可以提高效率(见条款 22)。
顺便说一句,在你打算用模板写象 max 这样有用的通用函数时,先检查一
下标准库(见条款 49),看看他们是不是已经存在。比如说上面说的 max,你会
惊喜地发现你可以后人乘凉:max 是 C++标准库的一部分。
有了 const 和 inline,你对预处理的需要减少了,但也不能完全没有它。抛弃
#include 的日子还很远,#ifdef/#ifndef 在控制编译的过程中还扮演重要角色。
预处理还不能退休,但你一定要计划给它经常放长假。
条款 2:尽量用<iostream>而不用<stdio.h>
是的,scanf 和 printf 很轻巧,很高效,你也早就知道怎么用它们,这我承
认。但尽管他们很有用,事实上 scanf 和 printf 及其系列还可以做些改进。尤其
是,他们不是类型安全的,而且没有扩展性。因为类型安全和扩展性是 C++的
基石,所以你也要服从这一点。另外,scanf/printf 系列函数把要读写的变量和
控制读写格式的信息分开来,就象古老的 FORTRAN 那样。是该向五十年代说
诀别的时候了!
不必惊奇,scanf/printf 的这些弱点正是操作符>>和<<的强项:
int i;
剩余303页未读,继续阅读
xluren
- 粉丝: 182
- 资源: 2
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 二叉树7-1-1.cpp
- android 9.0 原生模拟器 签名文件
- 技术面试最后反问面试官的话 校招面试非技术问题有哪些 非技术问题如何回答.png
- NB-IOT-BC26全网通模块Altium+ CADENCE +PADS三种格式(原理图SCH+PCB封装库)文件.zip
- 基于微信小程序开发的校园失物招领系统源码毕业设计(优质项目源码).zip
- 词向量是一种将自然语言中的单词转换为数值向量的技术,它能够捕捉词义和上下文信息
- nmap与masscan的简单使用
- MyBatis动态SQL.pdf
- 基于stm32单片机protues仿真的温湿度控制系统设计(仿真图、源代码)
- 词向量:自然语言处理的基石
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0