快捷搜索:   服务器  安全  linux 安全  MYSQL  dedecms

EffectiveC++2eItem39(2)


        psa->creditInterest();
      }

      // 尝试将它安全转换为CheckingAccount
      else if (CheckingAccount *pca =
                 dynamic_cast<CheckingAccount*>(*p)) {
        pca->creditInterest();
      }

      // 未知的帐户类型
      else {
        error("Unknown account type!");
      }
    }

    这种方法远不够理想,但至少可以检测到转换失败,而用dynamic_cast是无法做到的。但要注意,对所有转换都失败的情况也要检查。这正是上面代码中最后一个else语句的用意所在。采用虚函数,就不必进行这样的检查,因为每个虚函数调用必然都会被解析为某个函数。然而,一旦打算进行转换,这一切好处都化为乌有。例如,如果某个人在类层次结构中增加了一种新类型的帐户,但又忘了更新上面的代码,所有对它的转换就会失败。所以,处理这种可能发生的情况十分重要。大部分情况下,并非所有的转换都会失败;但是,一旦允许转换,再好的程序员也会碰上麻烦。

    上面if语句的条件部分,有些看上去象变量定义的东西,看到它你是不是慌张地擦了擦眼镜?如果真这样,别担心,你没看错。这种定义变量的方法是和dynamic_cast同时增加到C++语言中的。这一特性使得写出的代码更简洁,因为对psa或pca来说,它们只有在被dynamic_cast成功初始化的情况下,才会真正被用到;使用新的语法,就不必在(包含转换的)条件语句外定义这些变量。(条款32解释了为什么通常要避免多余的变量定义)如果编译器尚不支持这种定义变量的新方法,可以按老方法来做:

    for (list<BankAccount*>::iterator p = allAccounts.begin();
         p != allAccounts.end();
         ++p) {

      SavingsAccount *psa;        // 传统定义
      CheckingAccount *pca;       // 传统定义

      if (psa = dynamic_cast<SavingsAccount*>(*p)) {
        psa->creditInterest();
      }

      else if (pca = dynamic_cast<CheckingAccount*>(*p)) {
        pca->creditInterest();
      }

      else {
        error("Unknown account type!");
      }
    }

    当然,从处理事情的重要性来说,把psa和pca这样的变量放在哪儿定义并不十分重要。重要之处在于:用if-then-else风格的编程来进行向下转换比用虚函数要逊色得多,应该将这种方法保留到万不得已的情况下使用。运气好的话,你的程序世界里将永远看不到这样悲惨荒凉的景象。

顶(0)
踩(0)

您可能还会对下面的文章感兴趣:

最新评论