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

(一个)C风格遗留转换:

(T)expression

T(expression)

(二)C++提供四种新式转型:

(1)const_cast<T>(expression):去除表达式的常量性。是C++中唯一能做此操作的转型操作符。

(2)dynamic_cast<T>(expression):主要用来运行“安全向下转型”,即用来决定某对象是否归属继承体系中的某个类型。它是唯一无法由旧式语法运行的动作,也是唯一可能耗费重大运行成本的转型动作。

(3)reinterpret_cast<T>(expression):试图运行低级转型(比如将一个指向整数变量的指针转换为整数),实际动作及结果可能与编译器相关,因而减少了可移植性。

(4)static_cast<T>(expression):隐式转换。注意尽管能够使非const类型转换为const。但反之不能(这个仅仅能由const_cast来完毕)。

(三)新式转型比較受欢迎,原因:

1,非常easy在代码中被辨别出来。

2,各转型动作的目标愈窄化。编译器愈可能诊断出错误的运用。

(四)唯一使用旧式转型的时机是当调用一个explicit构造函数将一个对象传递给一个函数时:

class Widget{
public:
    explicit Widget(int size);
    ...
};
void doSomeWork(const Widget &w);
doSomeWork(Widget(15));//函数风格的转型动作创建一个Widget
doSomeWork(static_cast<Widget>(15));//c++风格的转型动作创建一个Widget对象

(五)先看以下这个代码:

class Base{...};
class Derived : public Base{...};
Derived d;
Base* pb = &d;//隐喻的将derived*转换成Base*

在这里表明:单一的对象可能拥有一个以上的地址。这里我们仅仅是建立一个base
class指针指向一个derived class对象,但有时候上述的两个指针值并不同样。这样的情况下会有个偏移量offset在执行期被施行于Derived*指针身上,用于取得正确的Base*指针值。

实际上一旦使用多重继承,这事差点儿一直发生.即使在单一继承中也可能发生.恐怖!为什么会发生这种事情呢?

由于对象的布局方式和它们的地址计算发式随着编译器的不同而不同,这就以为着写出"依据对象怎样布局"而写出的转型代码在某一平台上行得通,在其他平台上则不一定。

(六)

还有一件关于转型的有趣事情是:我们非常easy写出某些似是而非的代码(其它语言中或许是对的)。

比如SpecialWindow的onResize被要求首先调用Window的onResize。以下是看起来对,实际上错:

class Window {
public:
    virtual void onResize() {...}
};
class SpecialWinddow : public Window {
public:
    virtual void onResize() {
       static_cast<Window>(*this).onResize();//将*this转换成Window,然后调用其onResize;这样不行!
    }
};

这里会发生什么问题呢?static_cast<Window>(*this)这个转型动作并非如你想象的那样得到当前对象的基类对象部分,事实上编译器为你产生了的是基类对象的副本。

我运行的onResize方法压根就没有运行到基类对象上。而是运行在它的副本上。

可是SpecialWindow的专属onResize却运行在子类对象上。使得这个对象处于一种"伤残状态“。

解决方法:

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

(七)

首先。dynamic_cast的运行速度相当慢。

之所以要用dynamic_cast,一般是由于你想在一个你认定为derived
class对象身上运行derived class操作函数。但你的手上仅仅有一个“指向base”的pointer或者reference。你仅仅能靠他们来处理对象。

可是我们应该尽量避免使用dynamic_cast,有两种替代方法!

第一种方法:

使用容器并在当中存储直接指向derived
class对象的指针(一般是智能指针)如此便消除了“通过base class接口处理对象”的须要。

不要像以下这样用dynamic_cast:

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 != vinPtrs.end(); ++iter) {
    if(SpecialWindow* psw = dynamic_cast<SpecialWindow*>(iter->get()))
        psw->blink();
}

要改成这样:

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

另外一种方法:

能够通过base class接口处理“全部可能之各种window派生类”,那就是在base class 里提供virtual函数做你想对各个Window派生类做的事。

class Window {
public:
    virtual void blink() {  }
};
class SpecialWindow : public Window {
public:
    virtual void blink() {...};
};
typedef std::vector<std::tr1::shared_ptr<Window>> VPW;
VPW winPtrs;
for(VPW::iterator iter = winPtrs.begin(); iter != vinPtrs.end(); ++iter) {
    (*iter)->blink();
}

(八)

绝对必须拒绝的是所谓的“连串(cascading)dynamic_casts”:

typedef std::vector<std::tr1::shared_ptr<Window>> VPW;
VPW winPtrs;
for (VPW::iterator iter = winPtrs.begin(); iter != winPtrs.end(); ++iter)
{
    if (SpecialWindow1 * psw1 = dynamic_cast<SpecialWindow1*>(iter->get())) {...}
    if (SpecialWindow2 * psw1 = dynamic_cast<SpecialWindow2*>(iter->get())) {...}
    if (SpecialWindow3 * psw1 = dynamic_cast<SpecialWindow3*>(iter->get())) {...}
}

这种代码应该总是以某些“基于virtual函数调用”的东西取而代之。

优良的c++代码非常少使用转型,我们应该尽可能隔离转型动作。一般是把它隐藏在某个函数内,函数的接口会保护调用者不受函数内部不论什么肮脏龌龊的动作的影响。

请记住:

(1)假设能够,尽量避免转型,特别是在注重下来的代码中避免dynamic_cast.假设有个设计须要转型动作,试着发展无需转型的替代设计。

(2)假设转型是必要的,试着将它隐藏于某个函数背后.客户随后能够调用该函数,而不需将转型放进它们自己的代码内。

(3)宁可使用C++-style(新式)转型,不要使用旧式转型.前者非常easy辨识出来,并且也比較有着分门别类的职掌。

版权声明:本文博客原创文章,博客,未经同意,不得转载。

时间: 2024-08-06 04:35:33

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

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

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

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 C++ --027]尽量少做转型动作

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

Effective C++ 条款27

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

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) 执行"安全向下转型",也就是用来决定某对象是否归属继承体系中的

尽量少嵌套无用的div;外部文件尽量使用link而不要使用用@import

最近的工作又学到了很多东西,在这里记录一下. 1,尽量少嵌套无用的div,这个问题领导很严肃的跟我提过很多次,因为我很喜欢用很多div,而且有很多div都是无存在意义的.后来领导给了我一些资料,我看了一下,发现这样做确实存在很大的问题,原因如下:(以下蓝底文字摘自搜狐WEB标准) 2.1 节约运营成本 采用 WEB 标准制作,我们可以做到表现和形式及内容的分离,我们采用XHTML 语言来表现(数据),用CSS 来控制(页面元素呈现的)形式.写的好的页面,XHTML 代码中基本上都是用户要看的数据