2013-09-09 2 views
2

Существует абстрактный класс A, который имеет чистую виртуальную функцию-член func(). Существует большое количество производных классов, каждый из которых имеет различную реализацию функции func().Код, разделяемый между виртуальными функциями

Представьте себе, что вы хотите добавить дополнительную задачу, которая будет выполняться при каждом вызове функции func(), скажем, cout << "hello world"; независимо от производного класса. Задача также не зависит от содержимого func(), поэтому ее можно было выполнить до, после или даже в середине функции func(), только тот факт, что она запускается после каждого вызова функции func().

Предоставляет ли C++ (11) разумный способ сделать это?

Самое лучшее, что приходит мне на ум, это написать метод pre-func() в родительском классе, в котором реализована задача, и скопировать вызов pre-func() в начале всей функции func() реализации в производных классах. Что-нибудь лучше?

+2

Что вы описываете, называется «Template Method». http://en.wikipedia.org/wiki/Template_method_pattern –

+0

@AdamBurry Спасибо, я был уверен, что это не может быть в первый раз в истории, когда эта проблема появляется :) – DarioP

ответ

4

Я считаю, что вы могли бы использовать Non-virtual interface idiom

Вы бы базовый класс следующим образом:

class A{ 

public: 
    void myFunc(); 

private: 
    virtual void myVirtualFunc(); 
} 

с особенно следующих в .cpp:

void A::myFunc(){ 
    //stuff 
    myVirtualFunc(); 
    //stuff 
} 

Тогда каждый производный класс может переопределить myVirtualFunc() и изменить его поведение. Виртуальный является приватным, поэтому вам гарантировано, что он не будет вызываться нигде, кроме публичного не виртуального, определенного базовым классом (гарантирующий, что код, который вам нужно запустить для каждого вызова, будет запущен), а закрытость 't препятствовать тому, чтобы производный класс переопределял его. Производный класс может указать, что делает виртуальное, а не где (хотя, как упоминалось @WhozCraig, производный класс все еще может переопределить виртуальную функцию как общедоступную).

+1

Вне C++ известна не виртуальная идиома интерфейса как [* Шаблон метода шаблона *] (http://en.wikipedia.org/wiki/Template_method_pattern) – dasblinkenlight

+1

Базисное 'private:' объявление не препятствует тому, чтобы производный класс получал доступ к общему доступу как public: ', поэтому о которой вы говорите, это только если вы обращаетесь к объекту с помощью указателя или ссылки «A». Нет ничего, что помешало бы вам объявить 'Derived :: myFunc()' для 'public:' и still * virtual *. [См. Это в прямом эфире] (http://ideone.com/EBRxlU). Следовательно, за пределами 'A &' или 'A *' такой гарантии не существует. – WhozCraig

+1

@dasblinkenlight Как это было отмечено на C++, я думал, что буду использовать термин, относящийся к языку (но вы правы!). – JBL

2

Если я правильно понял вопрос, один из доступных вам вариантов - создать метод «pre-func()» в базовом классе и напечатать «Hello World», а затем вызвать «func()». Таким образом, ваши производные классы переопределяют «func()», но вы вызываете API через «pre-func()» (очевидно, я бы не использовал термин pre-func, поскольку он более не описывает функциональность точно)

+0

Избита им JBL – Downie