C++编程-多态的意义:流程的反转控制

来源:互联网 发布:手机版网站源码 编辑:程序博客网 时间:2024/06/03 20:45

    我们在很多C++书籍中都会看到关于多态的例子,一般是写两个简单的类:
    class A
    {
         virtual int M1(){...};
    };
   
    class B:public class A
    {
        virtual init M1(){};
    };
    
  然后给出一个使用方法:
   B *b=new B;
   A *a=b;
   a->M1();
   此时执行B::M1();
   这个例子对于解释C++的多态语法是足够了,然而它没有揭示出我们为什么要用多态:既然我们能直接创建B,为什么我们不直接使用B.M1()呢?如果这样,多态与继承还有什么区别呢?
  有些书上会给稍微好一点的例子,再给一个函数:
  void test(A &a)
  {
      a.M1();
  }
        然后给出一个使用方法:
          B *b=new B;
         test(*b);
   这已经部分触及到了多态的真正意义。
  在一个有工程意义的代码中,我们的函数远比这样的示例程序复杂,它会实现一个控制流程,在控制流程的某一点,我们调用了a.M1(),这使得流程的不变部分与可变部分分离。当我们完成一个流程后,我们可以不再关心流程的实现,而只关心给我们预留出来的hook,这就叫做反转流程(inversion of control),这正是基本上所有的框架(framework)的实现基础。这种区分使得程序员有了两个类别的分工:框架的编写者与使用者,其中使用者常被称为用户或者客户。
  在编程世界里,我们处在不同的角色当中,对于C++而言,在很多书籍中我们都会看到“用户”,这个词对于像我这些写行业软件的人,最容易弄混。对我而言,“用户”是指使用我开发出来的软件的人,而书中大部分情况下的“用户”是指使用框架(或者类库)的二次开发程序员。
  顺便提一句,在反转流程中(inversion of control)中使用到多态时,基类指针指向了真正的对象,这个过程叫做对象交换(Ojbect interchangable)。
        有很多代码的实现不是简单用一个函数来实现,因为它不符合面向对象的编程思想。更常用的方法是,我们在框架的主控对象(这种对象有时也叫做主动对象,Active Object)中保留hook的基类指针,在用户代码中新写了对hook的派生类后,使用主控对象的register函数,将该新的派生类对象“注册到”主动对象中,此时主控对象会使用C++的多态特性实现动态绑定。这涉及到设计模式的边缘,在未来有暇时聊到设计模式时再细谈。
   总之,我理解的多态的真正意义在于实现流程的反转控制。如果我们的工程足够大,要求足够的灵活性,我们也可以制作自己的框架。然而作为一个实用的程序员,我想强调的一点时,没有先进的技术,只有合适的技术。不是说继承就比包含(composition)好,不用多态就不是完美的C++程序。每个特性都有它的特定用途,理解它的真正应用场合,只能通过漫长的实践过程。

原创粉丝点击