effective C++笔记之条款39: 避免“向下转换”继承层次

原创 2012年03月27日 16:15:00

  • 先看如下例子:

class Person {…};
class BankAccount
{
public:
         BankAccount(const Person *primaryOwner, const Person *jointOwner);
         virtual ~BankAccount();
         virtual void makeDeposit(double amount)= 0;
         virtual void makeWithdrawal(doubleamount) = 0;
         virtual double balance() const = 0;
         …
};
class SavingsAccount : public BankAccount
{
public:
        SavingsAccount(constPerson *primaryOwner, const Person *jointOwner);
         ~SavingsAccount();
         void creditInterest();   //给账户增加利息
                   …
 };

 假设为所有账户维持一个列表,通过list类模板实现。

         list<BankAccount*>allAccount;   //银行中所有账户

         现在准备写一段代码来遍历所有账户,为每个账户计算利息。如下所示代码:

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

                  (*p)->creditInterest();  //错误

         因为creditInterest只是为SavingsAccount对象声明的,而不是BankAccount。

        

  • 向下转换:从一个基类指针到一个派生类指针。向下转换了继承的层次结构。
  •  通过向下转换可以得到通过编译,并正常运行。(static_cast<SavingsAccount *>(*p)->creditInterest();)但是对以后的扩充类难以维护。向下转换难看、容易导致错误,而且使得代码难于理解、升级和维护。
  •  向下转换可以通过如下两种方法消除:
  1.  最好的方法是将这种转换用虚函数调用来代替,同时,它可能对有些类不适用,所以要使这些类的每个虚函数成为一个空操作
  2. 加强类型约束,使得指针的声明类型和你所知道的真的指针类型之间没有出入。
  • 当不得不进行向下转换时,可以采用比原始转换更好的办法。这种方法称为“安全的向下转换”,通过dynamic_cast运算符来实现。当对一个指针使用dynamic_cast时,先尝试转换,如果成功(即指针的动态类型和正被转换的类型一致),就返回新类型的合法指针;如果dynamic_cast失败,返回空指针。

条款 39: 避免"向下转换" 继承层次

class Person { ... }; class BankAccount { public: BankAccount(const Person *primaryOwner, const Pers...

Effective C++ 第二版 37)不要重定义非虚函数 38)不要重定义缺省参数值 39)避免向下转换

条款37 决不要重新定义继承而来的非虚函数 实践依据 假设类D公有继承于类B, B中定义了公有成员函数mf; mf的参数和返回类型假设为void; 1 2 3 4 5 6 7...

读书笔记《Effective C++》条款33:避免遮掩继承而来的名称

我们知道在诸如这般的代码中: int x;//global变量 void someFunc() { double x;//local变量 std::cin >> x;/...

Effective modern C++ 条款 39:让std::thread在所有路径上不可join(Make std::threads unjoinable on all paths)

每个std::thread对象都处于两种状态之一:joinable和unjoinable。一个joinable的std::thread对象对应一个正在运行或处于可以运行状态的异步执行的线程。例如,一个...
  • acaiwlj
  • acaiwlj
  • 2015年10月19日 09:18
  • 1302

Effective C++(条款39-40)

一、明智而审慎的使用private继承
  • nawuyao
  • nawuyao
  • 2016年01月15日 18:06
  • 172

effective C++笔记之条款20、21:避免public接口出现数据成员、尽可能使用const

条款20: 避免public接口出现数据成员   l        如果接口里存在数据成员,用户每次访问类的成员时候会想是该用括号还是不该用括号。如果每个成员都是函数,就不用多想了。 l    ...
  • lifu119
  • lifu119
  • 2012年03月13日 17:13
  • 727

effective C++笔记之条款29: 避免返回内部数据的句柄

const A a;是否会变化?答案取决于其成员函数的组成结构。先看一个String类: class String { public: String(const char *...
  • lifu119
  • lifu119
  • 2012年03月19日 15:47
  • 733

读书笔记《Effective C++》条款40:明智而审慎地使用多重继承

要点: 1.多重继承比单一继承复杂。它可能导致新的歧义性,以及对virtual继承的需要。 2.virtual继承会增加大小、速度、初始化(及赋值)复杂度等等成本。如果virtual base cla...

effective C++笔记之条款43: 明智地使用多继承(MI)

l        多继承带来了单继承中绝对不会存在的复杂性。最基本的一条是二义性。如果一个派生类从多个基类继承了一个成员名,所有对这个名字的访问都是二义的;你必须明确地说出你所指的是哪个成员。如下所示...
  • lifu119
  • lifu119
  • 2012年04月04日 15:21
  • 1715

《Effective C++ 》学习笔记-第六章 条款37:绝不重新定义继承而来的缺省参数值

Never redefine a function's inherited default parameter value
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:effective C++笔记之条款39: 避免“向下转换”继承层次
举报原因:
原因补充:

(最多只允许输入30个字)