zoukankan      html  css  js  c++  java
  • 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> (expression)
      (2.4)static_cast<T> (expression)

    2.新式转型的详细介绍
       (2.1)const_cast<T> (expression)
         通常被用来将对象的常量性转除。它可是唯一有此技能的操作符哟,厉害吧。

     (2.2)dynamic_cast<T> (expression)
         主要用来执行“安全向下转型”,也就是用来决定某对象是否归属继承体系中的某个类型。
      唯一无法由旧式语法执行的动作,也是唯一可能耗费重大运行成本的转型动作。
         dynamic_cast 的许多实现版本执行速度相当慢,特别是深度继承或多重继承。

      为啥要使用dynamics_cast操作符,又如何避免使用它呢。
        使用dynamics_cast是因为你想在一个你认定为derived class对象身上执行derived class操作函数,但你手上只有一个“指向base”的pointer或regerence,

         你只能靠他们来处理对象。

        解决方案有两种:
      (1)使用容器并在其中存储直接指向derived class 对象的指针
      比如:

     1         class Window {
     2                 // ...
     3             };
     4             class SpecialWindow: public Window {
     5             public:
     6                 void blink();
     7                 //...
     8             };
     9 
    10             typedef std::vector<std::tr1::shared_ptr<Window>> VPW;
    11             VPW winPtrs;
    12             //...
    13             for (VPW::iterator iter = winPtrs.begin(); iter != winPtrs.end(); ++iter) {
    14                 if (SpecialWindow *psw = dynamic_cast<SpecialWindow *> (iter->get())) {
    15                     psw=>blink;
    16                 }
    17             }
    18            //--->修改如下:
    19            typedef std::vector<std::tr1::shared_ptr<SpecialWindow>> VPSW;
    20             VPSW winPtrs;
    21             //...
    22             for (VPSW::iterator iter = winPtrs.begin(); iter != winPtrs.end(); ++iter) {
    23                 (*iter)->blink();
    24             }     

          缺点:无法在同一个容器内存存储指针“指向所有可能地各种window派生类”。

     (2)通过base class接口处理“所有可能地各种Window派生类”,就是在base class中提供virtual函数,比如:  

     1          class Window {
     2                 // ...
     3                 virtual void blink();
     4             };
     5             class SpecialWindow: public Window {
     6             public:
     7                 virtual void blink();
     8                 //...
     9             };
    10 
    11             typedef std::vector<std::tr1::shared_ptr<Window>> VPW;
    12             VPW winPtrs;
    13             //...
    14             for (VPW::iterator iter = winPtrs.begin(); iter != winPtrs.end(); ++iter) {
    15                 (*iter)->blink();
    16             }

            另外注意:千万不要出现“连串”的dynamic_casts,这样的代码大而慢而且基础不稳定,维护性和扩展性都很差。

    (2.3)reinterpret_cast<T> (expression)
           意图执行低级转型,实际动作与编译器有关。也表示它不可移植。

     (2.4)static_cast<T> (expression)
          强迫隐式转换,特别是反向转换,但是无法const-->non-const,这是const_cast的技能。

     1     class Window {
     2         public:
     3             // ....
     4             virtual void onResize() 
     5             {
     6                 //...
     7             }
     8         };
     9 
    10         class SpecialWindow: public Window {
    11         public:
    12             virtual void onResize() {
    13                 static_cast<Window>(*this).onResize();
    14                 /*
    15                     注意:当前对象进入一种“伤残”状态:其base class 成分的更改没有落实,
    16                     而derived class成分的更改倒是落实了
    17                 */
    18                 // ....
    19             }
    20         };
    21 
    22         // --- 修正
    23         class SpecialWindow: public Window {
    24         public:
    25             virtual void onResize() {
    26                 Window::onResize();
    27             }
    28         };

    3.记住,任何一个类型转换(不论是通过转型操作而进行的显示转换,或通过编译器完成的隐式转换)往往真的令编译器编译出运行期间执行的码。

    总结:

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

       如果转型是必要的,试着将它隐藏于某个函数背后。客户随后可以调用该函数,而不需将转型放进他们自己的代码内。

       宁可使用C++-style(新式)转型,不要使用旧式转型。前者很容易辨识出来,而且也比较有着分门别类的职掌。

    其实看完之后,感觉有点不用转型了,后来回头看看标题:尽量少做转型动作。

    声明:本文所有的文字都是来源于《Effective C++》,我做的只是按照我自己读书的习惯写成的记录。如果你有帮助,那就太好了。

    =======================================================================
    所有内容都是用BSD条款。 Copyright (C) by CloudFeng.
  • 相关阅读:
    简单后台登录逻辑实现Controller
    自学semantic UI个人博客首页模板
    Spring Boot日志处理
    Thymeleaf静态资源引入方式及公共页面代码抽取
    一个简单SpringBoot应用的pom.xml文件
    Spring Boot入门程序
    easyuUI实现客户分页显示逻辑分析
    easyui自学模板代码
    网络协议-webService协议
    【转】彻底搞透Netty框架
  • 原文地址:https://www.cnblogs.com/cloudfeng/p/4355990.html
Copyright © 2011-2022 走看看