【问题标题】:Why is it preferred to have non-virtual interfaces?为什么首选非虚拟接口?
【发布时间】:2016-10-18 18:49:56
【问题描述】:

我正在阅读 Herb Sutter 的这篇文章 http://www.gotw.ca/publications/mill18.htm。作者提到编写非虚拟接口将接口规范与“实现细节(即内部可定制的行为)”分开

// 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();
  // ...
};

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

【问题讨论】:

    标签: c++ interface


    【解决方案1】:

    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 没有生效或没有兑现。因此,通过 非虚拟 IMachine::ProcessJob(),接口 IMachine 已经分离/忽略/抑制了处理作业的方式,而与机器类型无关(CMachine_A 或 @987654330 @) 使用。

    现在考虑一下:

    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

    【讨论】:

      【解决方案2】:

      当您指定虚拟公共接口int Process( Gadget&amp; ); 时,您也在限制扩展接口以匹配此公共接口。扩展这个类的任何人都需要通过实现Process 函数来做到这一点。

      提供更干净的公共界面和更合适的 [batch] 精心设计的私有函数以进行定制将允许我们分别实现两个目标。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-09-13
        • 2022-01-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多