Effective C++ Item 27 少做转型操作

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie

todo Item34

旧式转型

(T) expression 或 T (expression)

新式转型

const_cast<T>(expression)

通常被用来将对象的常量性转除(cast away the constness)

dynamic_cast<T>(expression)

执行“安全向下转型”,也就是用来决定某对象是否归属继承体系中的某个类型。

reinterpret_cast<T>(expression)

执行低级转型 //不太懂??

static_cast<T>(expression)

强迫隐式转换

//旧式转型与新式转型
class Widget{
public:
	explicit Widget(int size);
	//...
}
void soSomeWork(const Widget &w);
doSomeWork(Widget(15)); //以一个int加上“函数风格”的转型动作创建一个Widget.
doSomeWork(static_cast<Widget>(15)); //以一个int加上“C++风格”的转型动作创建一个Widget
class Base{...};
class Derived: public Base{...};
Derived d;
Base *pb = &d;

有时候上述两个指针值并不相同 ,可能会有个偏移量在运行期被施行于Derived *指针上。

对象的布局方式和它们的地址计算方式随编译器的不同而不同。

经验:如果可以,尽量避免转型,特别是在注重效率的代码中避免dynamic_casts。如果有个设计需要转型动作,试着发展

无需转型的替代设计

示例1:

class Window{ //base class
public:
	virtual void onResize(){...} //base onResize 实现代码
	//...
};

class SpecialWindow: public Window{ //derived class
public:
	virtual void onResize(){
		static_cast<Window>(*this).onResize(); //derived onResize 实现代码,将*this转型为Window,然后调用其 onResize, 错误
											   //onResize 操作的是转型生成的临时对象的数据
		//... 这里进行 SpecialWindow 专属行为
	}
}

纠正

class SpecialWindow: public Window{
public:
	virtual void onResize(){
		Window::onResize(); //调用Window::onResize作用于*this身上
	}
}

示例2:之所以需要 dynamic_cast ,通常是因为你想在一个你认定为derived class 对象身上执行 derived class操作函数,但你的手上却只有一个

“指向base”的pointer或reference,你只能靠它们来处理对象。

class Window {...};
class SpecialWindow: public Window{
public:
	void blink();
	//...
};

typedef std::vector<std::tr1::shared_ptr<Window> > VPW;
VPW winPtrs;
//...
for(VPW::iterator iter = winPtrs.begin(); iter != winPtrs.end(); ++iter){
	if(SpecialWindow *psw = dynamic_cast<SpecialWindow*> (iter->get())) //不希望使用 dynamic_cast,因为许多实现版本执行速度相当慢
		psw->blink();
}

纠正1:使用类型安全容器。使用容器并在其中存储直接指向 derived class 对象的指针,消除了“通过 base class 接口处理对象”的需要。

不过这种做法无法在同一个容器里存储指针“指向所有可能之各种Window派生类”。如果真要处理多种窗口类型,需要多个容器。

typedef std::vector<std::tr1::shared_ptr<SpecialWindow> >VPSW;
VPSW winPtrs;
//...
for(VPSW::iterator iter = winPtrs.begin(); iter != winPtrs.end(); ++iter){
	(*iter)->blink();
}

纠正2:将 virtual 函数往继承体系上方移动。在base class 内提供 virtual 函数做你想对各个 Window 派生类做的事。

class Window{
public:
	virtual void blink(){} //缺省实现代码 “什么也没做”;
						   //<span style="color:#ff0000;">Item 34 --> </span>
	//...
};
class SpecialWindow: public Window{
public:
	virtual void blink(){...}; //在此class内,blink做某些事
	//...
};

typedef std::vector<std::tr1::shared_ptr<Window> > VPW;
VPW winPtrs;
//...
for(VPW::iterator iter = winPtrs.begin(); iter != winPtrs.end(); ++iter){
	psw->blink();
}

Effective C++ Item 27 少做转型操作

时间: 2024-11-01 09:31:16

Effective C++ Item 27 少做转型操作的相关文章

Effective C++ 条款27 尽量少做转型操作

1. 转型语法有三种, C风格转型:(T)expression 函数风格转型:T(expression) 两种方式除了小括号位置不同没有差别,可以称为"旧式转型". C++提供四种新式转型: const_cast<T>(expression): 将const变量引用或指针转为非const引用或指针,移除变量的常量特性.T必须是指针或引用. 注:虽然经const_cast转型后的变量可以被更改,但由于"常量折叠"(c++编译器在编译时将const 变量替换

[Effective C++ --027]尽量少做转型动作

引言                                                                                                                                                                                                C风格的转型动作 (T)expression // 将expression转型为T 函数风格的转型动作看起来像这

Effective C++ 阅读笔记_条款27 尽量少做转型动作

Effective C++ 阅读笔记_条款27 尽量少做转型动作 1.转型的三种形式,可以分为两大类. (1)旧式转型(old-style casts) (1.1) (T) expresstion (1.2) T (expression) (2) 新式转型(c++-style casts) (2.1)const_cast<T> (expression) (2.2)dynamic_cast<T> (expression) (2.3)reinterpret_cast<T>

Effective C++:条款27:尽量少做转型动作

(一)C风格旧式转型: (T)expression T(expression) (二)C++提供四种新式转型: (1)const_cast<T>(expression):去除表达式的常量性,是C++中唯一能做此操作的转型操作符. (2)dynamic_cast<T>(expression):主要用来执行"安全向下转型",即用来决定某对象是否归属继承体系中的某个类型.它是唯一无法由旧式语法执行的动作,也是唯一可能耗费重大运行成本的转型动作. (3)reinterp

条款27:尽量少做转型动作

条款27:尽量少做转型动作 C++的四种显示类型转换 ①reinterpret_cast(在编译期间实现转换) 将一个类型的指针转换成另一个类型的指针.这种转换不用于修改指针变量值数据存放的格式(不改变指针变量值),只需在编译期间重新解释指针的类型就可以做到,可以将指针值转换为一个整型数.但是不能用于非指针类型的转换,否则将不会通过编译. 意图执行低级转型,结果取决于编译器,故不可移植. ②const_cast(在编译期间实现转换) 用于去除指针变量的常量属性,将它转换为一个对应指针类型的普通变

条款27:尽量少做转型动作(Minimize casting)

NOTE : 1.如果可以,尽量避免转型,特别是在注重效率的代码中避免dynamic_casts. 如果有个设计需要转型动作,试着发展无需转型的替代设计. 2.如果转型是必须要的,试着将它隐藏于某个函数背后.客户随后可以调用该函数,而不需要将转型放进他们自己的代码内. 3.宁可使用C++-style(新式)转型,不要使用旧式转型.前者很容易辨识出来,而且也比较有着分门别类的职撑.

Effective JavaScript Item 27 使用闭包而不是字符串来封装代码

本系列作为Effective JavaScript的读书笔记. 对于代码封装,在JavaScript中有两种方式可以办到.第一种就是使用function,第二种则是利用eval()函数,传入到该函数的字符串参数可以是一段代码. 当对使用哪种方式犹豫不决时,使用function.因为使用字符串的一个重要缺点是,传入的字符串并不是一个闭包,而function则可以代表一个闭包.关于闭包的特点,在Item 11中进行了描述. 下面是一段使用字符串来封装代码的例子: function repeat(n,

Effective C++ 条款27

尽量少做转型动作 尽量少做转型动作有什么目的?非常明显无非就是提高程序的稳定性.提高程序的运行效率. 那么.有哪些转型方式?每种方式都有什么弱点? 这是我们本节学习的重点. C++有四种转型: const_cast<T>(expression) dynamic_cast<T>(expression) reinterpret_cast<T>(expression) static_cast<T>(expression) 每种转型的作用例如以下: 1.const_

Effective C++:规定27:尽量少做动作的过渡

(一个)C风格遗留转换: (T)expression T(expression) (二)C++提供四种新式转型: (1)const_cast<T>(expression):去除表达式的常量性.是C++中唯一能做此操作的转型操作符. (2)dynamic_cast<T>(expression):主要用来运行"安全向下转型",即用来决定某对象是否归属继承体系中的某个类型.它是唯一无法由旧式语法运行的动作,也是唯一可能耗费重大运行成本的转型动作. (3)reinter