Почему предпочтительнее иметь не виртуальные интерфейсы?

Я прохожу эту статью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();
  // ...
};

Какую деталь реализации (или настраиваемое поведение) указывает приведенный выше пример? Я немного смущен тем, что не так с приведенным выше кодом, который требует от нас не виртуальных интерфейсов

Ответы на вопрос(2)

Когда вы указываете виртуальный публичный интерфейс,int Process( Gadget& );Вы также ограничиваете интерфейс расширения для соответствия этому общедоступному интерфейсу. Тот, кто расширяет этот класс, должен будет сделать это путем реализацииProcess функция.

Обеспечение более чистого общедоступного интерфейса и более подходящей [партии] хорошо разработанных частных функций для настройки позволит решать наши две задачи индивидуально.

От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 указывает на разные конкретные реализации (читай: производные классы), вывод одинаков независимо от выбранной реализации / производного класса. Этоcustomizable behavior машины A и машины B не вступают в силу или не соблюдаются. Итак, имеяне виртуальный IMachine::ProcessJob()интерфейсIMachine отделил / проигнорировал / подавил способ обработки задания независимо от типа машины (CMachine_A или жеCMachine_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 указывает на разные конкретные реализации (читай: производные классы), вывод соответствует выбранной реализации / производному классу. Этоcustomizable behavior машины A и машины B вступают в силу или будут приняты. Итак, имеявиртуальный IMachine::ProcessOrder()интерфейсIMachine оставил открытой опцию / путь, в котором ордер будет обрабатываться в зависимости от типа машины (CMachine_A или жеCMachine_B) который используется.

Короче, так как интерфейсIMachine сохранилProcessOrder какvirtual поэтому различные реализации / производные классы могут обеспечитьcustomizable behavior для функцииProcessOrder.

Ваш ответ на вопрос