第一部分:习惯C++(条款1-4)
来源:互联网 发布:3d地球仪软件 编辑:程序博客网 时间:2024/05/17 07:03
这里是effective C++第一部分
条款1:对C++的整体认识。它包括 1. C部分。C++以C语言为基础发展而来。2.面向对象部分。3.C++泛型编程部分也叫template C++. 4.STL
条款2:用const,enum,inline对define替换
1.#define RATIO 3.14 改为const double Ratio = 3.14这么做是有原因的,#define作为预处理器也许不被视作语言的一部分。记号RATIO也许没有被编译器看见;也许 编译器开始处理源码时就被预处理器移走了。于是记号RATIO可能没有进入记号表。于是当你运用此常量可能获得一个编译错误。但是作为一个语言常量Ratio当然就会进入 记号表。另外使用常量可能获得比预处理更少的代码,因为预处理器只是盲目的替换。
2.当你在你的class内需要在编译期间一个常量的时候这种情况会有所不同。enum可以作为补偿。看下面的列子
class Game
{
private:
enum{NumTurns=5};
int scores[NumTurns];
....
}
enum对于有时候更像define,取const的地址是合法的,但是取enum的地址是不合法的。如果你不想让别人获得一个pointer或者reference指向你的某个整数常量enum 可以帮你约束。
3.inline
看个列子 #define CALL_MAX(a,b)f((a)>(b)?(a):(b))来看不可思议的调用:
inta = 5, b=0;
CALL_MAX(++a,b); //a被累加2次
CALL_MAX(++a,b+10) //a被累加1次
改成inline函数可以避免类似的事情发生
template<typename T>
inlinevoid Call_Max(const T& a,const T& b)
{
f(a>b?a:b);
}
条款3:const
const是多才多艺的
首先注意区别 const int* a和 *const int b。 a是指向一个int常量的指针,意味着a也可以指向其他int常量。b是一个const指针,只能够指向一个固定的内存,当然对它所指向的值是否可以修改不是由它说了算。
函数返回值为const避免不必要的修改
const成员函数标示哪些成员函数可以修改成员变量,哪些不可以 函数参数为const引用可以提高效率。注意基于const的成员函数的重载
class Text
{
public:
...........
const char& operator[ ](intx) const
{ return text[x];}
char& operator[int x]
{ return text[x];}
private:
std::string text;
};
Text tb("Hello");
std::cout<<tb[0]; //调用non-const
tb[0] = 'x'; //没问题
Text ctb("World");
std::cout<<ctb[0]; //调用const
ctb[0] = 'x'; //错误
应该如何避免const和non-const代码的重复?用non-const调用const
class Text
{
public:
...........
const char& operator[ ](intx) const
{ return text[x];}
char& operator[int x]
{ return
const_cast<char&>(
static_const<const Text&>(*this)
[x]);
}
private:
std::string text;
};
上面的代码第一个const_cast是移除const特性。第二个static_cast是加上const特性。那么这句话的意思就是加上const特性在Text上面,然后对其求下标运算即调用了const成员函数版本,这里如果不加上const,那么函数会自己调用自己导致一个死循环。因为其返回值是一个const,我们希望非const Text的成员变量值是可以改变的,所以我们移除它的const特性了。
那么用const调用non-const可以吗?答案是不可以的,因为const承诺不改变,而non-const没有这个说法,这里就存在成员有可能被non-const改变的危险,这是一种错误的行为
条款4: 对象使用前被初始化
这个条款有一个值得注意的地方。例子里面有很多说明了
class FileSystem
{
public:
int num() const;
........
};
extern FileSystem tfs;
另外一个客户:
class Dir
{
public:
Dir(....);
........
};
Dir::Dir()
{
......
int disks = tfs.num();
}
//假设客户创建对象
Dir temp(....);
这里除非tfs在temp之前初始化,否则就会有错误
下面是一个解决办法:
class FileSystem{ .... };
FileSystem& tfs()
{
static FileSystem fs;
return fs;
}
class Dir{...};
Dir::Dir(...)
{
int disks = tfs().num();
.....
}
Dir& temp()
{
static Dir dir;
retuen dir;
}
以上就是典型的单例模式
- 第一部分:习惯C++(条款1-4)
- 《Effective C++》让自己习惯C++:条款1-条款4
- 【Effective C++】条款01-让自己习惯c++
- Effective C++(条款1-4)
- Effective C++读书笔记 第一部分 让自己习惯C++
- Effective C++笔记第一部分:让自己习惯C++
- Effective C++ 笔记 第一部分 让自己习惯C++
- c语言结构第一部分
- Objective-c for Java程序员 第一部分1
- chapter 4第一部分
- 第一部分(4)
- 第一部分 4
- 14第一部分 1
- Effective C++——条款4(第1章)
- Guru of the Week 条款22:对象的生存期(第一部分)
- Guru of the Week 条款20:代码的复杂性(第一部分)
- 《Effective C#》Part I:第一部分总结
- C语言测试题第一部分
- Linux网络协议栈 -- socket创建(2)
- ScrollView’s handy trick
- boost学习之-weak_ptr
- DIV透明度设置
- Interview Q&A - 程序会在哪一行死掉?
- 第一部分:习惯C++(条款1-4)
- poj 1703
- android获取手机唯一识别号
- 快播资源哪里跑(逆向)
- android 发送json 到服务器
- Android平台调用WebService详解
- WSDL 编写说明
- Ruby on Rails常用命令
- 解决 Flex4 Error in Module 的问题