Почему бы не абстрактные политики? - PullRequest
1 голос
/ 10 марта 2012

При реализации политик необходимо следовать определенному интерфейсу. Из того, что я понимаю, политики должны быть в состоянии заменить друг друга. В современной книге на языке c ++ политики Ch 1.5 3 имеют одинаковый интерфейс «T * Create () {}». Почему нет необходимости абстрагировать это? Было бы важно, если бы имелся ряд интерфейсов, которые должны иметь политики. Насколько я понимаю, абстрактный класс дает рецепт, для которого интерфейсы должны быть в конкретных классах (классы политики). В примере Wikipedia «using» определяет, какие интерфейсы должна иметь политика, но не через абстрактный класс. Не является ли смысл абстрактного класса гарантировать, что производные классы имеют требуемые интерфейсы?

что мне не хватает?

Ответы [ 2 ]

2 голосов
/ 10 марта 2012

Разница в том, что интерфейс, использующий абстрактный базовый класс, имеет виртуальные функции, обеспечивающие полиморфизм во время выполнения.

Политики используются для обеспечения полиморфизма времени компиляции для шаблонов.Компилятор заметит, имеет ли ваш класс политики T* Create() или нет.Если этого не произойдет, вы получите ошибку времени компиляции при попытке использовать его.

1 голос
/ 10 марта 2012

На самом деле я никогда не использовал на практике политику на основе политик, и с тех пор, как я написал код на C ++, прошло много времени, но вот моя интерпретация.Как вы указали, класс хоста может налагать ограничения на политики, используемые с ним, либо через интерфейсы, либо через что-то вроде using output_policy::Print;, как показано в вики-примере.

Преимущество (или различие)метод использования заключается в том, что он менее проактивен и менее жесток, поскольку у политик есть подразумеваемый контракт, который представлен непосредственно кодом, который их использует.В примере использования, учитывая текущее состояние кода, реализация output_policy должна реализовывать только метод с именем Print, который возвращает что угодно и принимает то, что возвращает language_policy :: Message () (в этом случае все language_policies возвращают std :: string),Это немного ближе к типу утки.

Один недостаток заключается в том, что подразумеваемый контракт исчезает, когда код исчезает.Другим недостатком является то, что политики имеют определенный уровень зависимости друг от друга.В качестве очень надуманного примера, если у одного output_policy есть неуниверсальный метод Print, который печатает только строки, его нельзя использовать с language_policy, который печатает только целые числа.

Я не понимаю, почему вы не можете добавитьинтерфейсы политики, если это необходимо.Один пример - это когда класс HelloWorld может захотеть ограничить output_policy, чтобы он печатал строки и ничего больше.Вы можете достичь этого, написав что-то вроде следующего: обратите внимание, что вам нужно использовать SFINAE, чтобы принудительно реализовать output_policy<std::string> OutputPolicyInterface<std::string>.

template<typename message_type>
class OutputPolicyInterface
{
    virtual void Print( message_type message ) = 0;
};


template <template<class> class output_policy, typename language_policy>
class HelloWorld : public output_policy<std::string>, public language_policy
{

public:
    void Run()
    {
        Print( Message() );
        //Print(2);  won't work anymore
    }
};
...