首页 文章

为什么首选非虚拟接口?

提问于
浏览
0

我正在阅读Herb Sutter的这篇文章http://www.gotw.ca/publications/mill18.htm . 作者提到编写非虚拟接口将接口规范与"implementation details (namely the internally customizable behavior)"分开

// Example 1: A traditional base class.
//
class Widget
{
public:
  // Each of these functions might optionally be
  // pure virtual, and if so might or might not have
  // an implementation in Widget; see Item 27 in [1].
  //
  virtual int Process( Gadget& );
  virtual bool IsDone();
  // ...
};

上面的示例指定了哪种实现细节(或可自定义的行为)?我对上面的代码有什么问题感到有些困惑,这需要我们使用非虚拟接口

2 回答

  • 0

    通过 customizable behavior 它表示由不同的 Derived Classes 提供的实现,即从 Interface 派生的类 .

    考虑一下:

    class IMachine
    {
        public:
            int ProcessJob()
            {
                cout << "Processing Job in By-Default way" << endl;
            }
            virtual int ProcessOrder()
            {
                cout << "Processing Order in By-Default way" << endl;
            }
    };
    class CMachine_A : public IMachine
    {
        public:
            int ProcessJob()
            {
                cout << "Processing Job in Machine A's way" << endl;
            }
            int ProcessOrder()
            {
                cout << "Processing Order in Machine A's way" << endl;
            }
    };
    class CMachine_B : public IMachine
    {
        public:
            int ProcessJob()
            {
                cout << "Processing Job in Machine B's way" << endl;
            }
            int ProcessOrder()
            {
                cout << "Processing Order in Machine B's way" << endl;
            }
    };
    
    IMachine *pMachine;
    CMachine_A oMachineA;
    CMachine_B oMachineB;
    
    pMachine = &oMachineA;
    pMachine->ProcessJob();
    pMachine = &oMachineB;
    pMachine->ProcessJob();
    
    Output:
    Processing Job in By-Default way
    Processing Job in By-Default way
    

    因此,在上面的示例中,尽管 pMachine 指向不同的具体实现(读取:派生类),但无论选择的实现/派生类如何,输出都是相同的 . 也就是说,机器A和机器B的 customizable behavior 没有生效或没有兑现 . 因此,通过 non virtual IMachine::ProcessJob() ,接口 IMachine 已分离/忽略/禁止处理作业的方式,而不管使用的机器类型( CMachine_ACMachine_B )如何 .

    现在考虑一下:

    IMachine *pMachine;
    CMachine_A oMachineA;
    CMachine_B oMachineB;
    
    pMachine = &oMachineA;
    pMachine->ProcessOrder();
    pMachine = &oMachineB;
    pMachine->ProcessOrder();
    
    Output:
    Processing Order in Machine A's way
    Processing Order in Machine B's way
    

    这里,当 pMachine 指向不同的具体实现(读取:派生类)时,输出根据所选的实现/派生类 . 也就是说,机器A和机器B的 customizable behavior 即将生效或受到尊重 . 因此,通过 virtual IMachine::ProcessOrder() ,接口 IMachine 保持选项/方式打开,其中订单将被处理,具体取决于所使用的机器类型( CMachine_ACMachine_B ) .

    简而言之,由于接口 IMachineProcessOrder 保持为 virtual 因此不同的实现/派生类可以为函数 ProcessOrder 提供 customizable behavior .

  • 1

    指定虚拟公共接口 int Process( Gadget& ); 时,您还要限制扩展接口以匹配此公共接口 . 扩展此类的任何人都需要通过实现 Process 函数来完成此操作 .

    提供更清晰的公共界面和更适合[批量]精心设计的私人定制功能将允许单独解决我们的两个目标 .

相关问题