More Effectvie C++笔记(一)--指针与引用区别,C++风格的类型转换

来源:互联网 发布:淘宝证书 编辑:程序博客网 时间:2024/05/20 06:50

ITEM1.指针与引用的区别

1. 指针可指向空变量,引用不可指向空变量。

2.引用应被初始化。

3.指针可以被重新赋值,引用总是指向初始化时的对象,不能改变。


ITEM2.尽量使用C++风格的类型转换

1. 语法:static_cast<type>(expression)

四个操作符:static_cast、const_cast、dynamic_cast、reinterpret_cast。

例:

C风格:double rst = ((double)firstNum)/secondNum;

变为C++风格:double rst = static_cast<double>(firstNum)/secondNum;

2.const_cast用于去掉表达式中的const或volatileness属性。

例: 
class Widget { ... }; 
class SpecialWidget: public Widget { ... }; 
void update(SpecialWidget *psw); 
SpecialWidget sw; // sw 是一个非const 对象。 
const SpecialWidget& csw = sw; // csw 是sw的一个引用,它是一个const 对象
update(&csw);   // 错误!不能传递一个const SpecialWidget* 变量给一个处理SpecialWidget*类型变量的函数
update(const_cast<SpecialWidget*>(&csw)); // 正确,csw的const被显示地转换掉(csw和sw两个变量值在update 函数中能被更新) 
update((SpecialWidget*)&csw); // 同上,但用了一个更难识别的C风格的类型转换 
Widget *pw = new SpecialWidget;  
update(pw); // 错误!pw的类型是Widget*,但是update函数处理的是SpecialWidget*类型  
update(const_cast<SpecialWidget*>(pw)); 
// 错误!const_cast仅能被用在影响constness or volatileness的地方上。不能用在向继承子类进行类型转换。

3.dynamic_cast把指向基类的指针或引用转换成指向其派生类或其兄弟类的指针或引用,

能知道转换是否成功。失败:返回空指针(当对指针进行类型转换时)或者抛出异常

(当对引用进行类型转换时)。

例:

update(dynamic_cast<SpecialWidget*>(pw)); 
// 正确,传递给update函数一个指针是指向变量类型为SpecialWidget的pw的指针 
// 如果pw确实指向一个对象, 否则传递过去的将使空指针。
void updateViaRef(SpecialWidget& rsw); 
updateViaRef(dynamic_cast<SpecialWidget&>(*pw)); 
 //正确。 传递给updateViaRef函数,SpecialWidget pw  指针,如果pw 确实指向了某个对象,否则将抛出异常

4.reinterpret_casts:在函数指针类型之间进行转换,由于可能会产生错误,

应该避免转换函数指针类型。

例:

函数指针数组: 
typedef void (*FuncPtr)();      // FuncPtr is  一个指向函数的指针,该函数没有参数返回值类型为void 
FuncPtr funcPtrArray[10];       // funcPtrArray 是一个能容纳10 个FuncPtrs指针的数组 

int doSomething(); 

funcPtrArray[0] = &doSomething;     //  错误!类型不匹配
funcPtrArray[0] =  reinterpret_cast<FuncPtr>(&doSomething);

5.可用传统类型转换方法代替static_cast, const_cast, 以及reinterpret_cast。

也可以用下面的宏替换来模拟新的类型转换语法: 
#define static_cast(TYPE,EXPR)      ((TYPE)(EXPR)) 
#define const_cast(TYPE,EXPR)        ((TYPE)(EXPR)) 
#define reinterpret_cast(TYPE,EXPR)  ((TYPE)(EXPR))

你可以象这样使用使用: 
double result = static_cast(double, firstNumber)/secondNumber; 
update(const_cast(SpecialWidget*, &sw)); 
funcPtrArray[0] = reinterpret_cast(FuncPtr, &doSomething);

没有一个容易的方法来模拟dynamic_cast的操作,但是很多函数库提供了函数,

安全地在派生类与基类之间进行类型转换

(待续……)