Why is it preferred to have non-virtual interfaces?

喜你入骨 提交于 2019-12-30 14:44:17

问题


I am going through this article http://www.gotw.ca/publications/mill18.htm by Herb Sutter. The author mentions that writing non-virtual interfaces separates the interface specification from the "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();
  // ...
};

What kind of implementation detail (or customizable behavior) does the above example specify? I am slightly confused about what is wrong with the above code, which requires us to have non-virtual interfaces


回答1:


By customizable behavior it means the implementation provided by different Derived Classes, i.e the classes which will derive from your Interface.

Consider this:

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

So, in above example even though pMachine points to different concrete implementations (read: derived classes), the output is same irrespective of chosen implementation/derived class. That is, the customizable behavior of Machine A and Machine B is not coming in-effect or not honored. So, by having non virtual IMachine::ProcessJob(), the interface IMachine has separated/ignored/suppressed the way in which the Job will get processed irrespective of the type of Machine (CMachine_A or CMachine_B) which is used.

Now consider this:

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

Here, when pMachine points to different concrete implementations (read: derived classes), the output is according to the chosen implementation/derived class. That is, the customizable behavior of Machine A and Machine B is coming in-effect or honored. So, by having virtual IMachine::ProcessOrder(), the interface IMachine has kept the option/way open in which the Order will get processed depending upon the type of Machine (CMachine_A or CMachine_B) which is used.

In short, since the interface IMachine has kept the ProcessOrder as virtual therefore different implementation/derived class can provide customizable behavior for the function ProcessOrder.




回答2:


When you specify the virtual public interface, int Process( Gadget& );, you are also restricting the extension interface to match this public interface. Whoever extends this class will need to do this by implementing the Process function.

Providing a cleaner public interface and a more suitable [batch] of well designed private functions for customization will allow tackling our two goals individually.



来源:https://stackoverflow.com/questions/37872978/why-is-it-preferred-to-have-non-virtual-interfaces

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!