2013-12-14 3 views
0

Учитывая, что разница между постоянным посетителем и изменяемых визитером, что методы постоянным посетителем не разрешается изменять посещаемый объект.посетители Реализации: Constant против Мутабельного Visitor

class Integer_Field; 
class Boolean_Field; 
class Text_Field; 

class Visitor_Constant 
{ 
    public: 
    virtual void visit(const Integer_Field& f) = 0; 
    virtual void visit(const Boolean_Field& f) = 0; 
    virtual void visit(const Text_Field& f) = 0; 
}; 

class Visitor_Mutable 
{ 
    public: 
    virtual void visit(Integer_Field& f) = 0; 
    virtual void visit(Boolean_Field& f) = 0; 
    virtual void visit(Text_Field& f) = 0; 
}; 

Я хотел бы свести к минимуму поддержку этих посетителей. Например, если я придумал класс Blob_Field, мне нужно изменить оба класса. Я предпочел бы иметь что-то, где мне нужно только изменить один класс или трафарет.

Проблема обслуживания вентиляторов, когда есть много классов, определенных этими родительскими посетителями. Это основная причина, по которой я хочу упростить техническое обслуживание.

Мои вопросы:
(Примечание. Это должны быть решены без использования C++ 11 функций в моей среде разработки не поддерживает C++ 11 и я не позволил обновить в это время)

  1. есть ли способ, чтобы использовать механизм template объединить два (например, поставки «сопзЬ» в качестве параметра шаблона)?
  2. Как я могу настроить этих посетителей, чтобы передать Visitor_Constant методам, используя Visitor_Mutable?

Примечание: объединение этих классов через родительский класс позволяет удвоить методы посетителей, которые должны быть реализованы и поддерживаться.

Edit 1: отношения классов

class Component; // Base class for fields and records. 
class Field : public Component; // Base class for all fields 
class Record : public Component // Base class for all records 
{ 
    std::vector< boost::shared_ptr<Component> > component_container; 
}; 
class Integer_Field : public Field; 
class Boolean_Field : public Field; 
class Text_Field : public Field; 

Edit 2: Рациональность полого
Один рациональности для месторождений, леченных конкретно в случае генерации оператора SQL для создания таблицы.
Другое для загрузки полей из таблицы базы данных.

+0

Как относятся к классам «поле»? –

+0

@ Cheersandhth.-Alf Классы полей являются компонентами записи, например, в записи базы данных/таблицы. –

+0

Не считая проблемы 'const', вы можете позволить каждой функции' visit' соответствовать определенному интерфейсу. Посетителю нужно только реализовать интерфейсы, которыми он управляет (и они могут быть организованы в некотором иерархическом порядке для поддержки иерархии типов). Посещаемый объект поля может затем «dynamic_cast» посетителя перейти к интерфейсу, соответствующему его собственному базовому типу, и если такой интерфейс присутствует, вызовите его функцию. Это централизует явное понижение. Напротив, ваша схема выше не требует какого-либо понижения, но имеет эту потенциальную поддержку prblm –

ответ

0

Есть ли способ использовать механизм template для слияния двух (например, снабжение «const» в качестве параметра к шаблону)?

Вы можете предоставить его с помощью параметра шаблона шаблона, а также сохранить целостность обычного посетителя. Я изначально сделал это на C++ 11, но, поскольку вы говорите, что у вас его нет, я приведу вместо него списки типов.

Вот реализация списка типов.

/* Our empty node for our type list. */ 
class Empty {}; 

/* Cons for our type list. */ 
template <typename First_, typename Rest_> 
class Cons { 
    public: 

    /* First type */ 
    typedef First_ First; 

    /* Rest. */ 
    typedef Rest_ Rest; 

}; // Cons<First_, Rest_> 

Вот общая реализация посетителя.

/* Forward declaration. */ 
template <template <typename> class Decorator, typename Members> 
class VisitorRecur; 

/* Base case. */ 
template <template <typename> class Decorator, typename Member> 
class VisitorRecur<Decorator, Cons<Member, Empty> > { 
    public: 

    /* Pure virtual for each of the members. */ 
    virtual void operator()(
     typename Decorator<Member>::Type that) const = 0; 

}; // VisitorRecur<Decorator, Member> 

/* Recursive case. */ 
template <template <typename> class Decorator, typename Members> 
class VisitorRecur 
    : public VisitorRecur<Decorator, typename Members::Rest> { 
    public: 

    /* Bring the operator()s into scope. */ 
    using VisitorRecur<Decorator, typename Members::Rest>::operator(); 

    /* Pure virtual for each of the members. */ 
    virtual void operator()(
     typename Decorator<typename Members::First>::Type that) const = 0; 

}; // VisitorRecur<Decorator, typename Members::Rest> 

/* Final visitor. */ 
template <template <typename> class Decorator, typename Members> 
class Visitor : public VisitorRecur<Decorator, Members> { 
    public: 

    /* Bring the operator()s into scope. */ 
    using VisitorRecur<Decorator, Members>::operator(); 

}; // Visitor<Decorator, Members> 

Вот два декоратора, которые мы определим.

/* ConstRef. */ 
template <typename T> 
class ConstRef { 
    public: 

    typedef const T & Type; 

}; // ConstRef<T> 

/* Ref. */ 
template <typename T> 
class Ref { 
    public: 

    typedef T & Type; 

}; // Ref<T> 

Вот пример использования.

/* Forward declarations. */ 
class Circle; 
class Square; 
class Triangle; 

/* Add the members into a type list. */ 
typedef Cons<Circle, Cons<Square, Cons<Triangle, Empty> > > Members; 

/* Our const visitor which accepts the members by const-ref. */ 
typedef Visitor<ConstRef, Members> ConstVisitor; 

/* Our mutating visitor which accepts the members by ref. */ 
typedef Visitor<Ref, Members> MutatingVisitor;