2015-07-30 3 views
0

я перейду прямо к нему: У меня есть шаблон класса, который содержит справочную и обновление информацию к нему:Как инициализировать «плохую» пустую ссылку на абстрактный класс

template<class T> 
class Parser { 
    T& m_ref; 
public: 
    typedef T ValueType; 
    Parser(T& ref): m_ref(ref) {} 
    virtual void read(std::istream&); 
}; 

Теперь у меня есть еще один шаблон, который создает новый объект и обновляет его с помощью этого интерфейса, для этого у меня есть поле, которое сохраняет парсер. Тем не менее, я хотел бы использовать updater для классов, которые происходят из T, что невозможно с помощью poymorphism, поскольку Parser<Derived> не наследует от Parser<Base>. Я создал это обходный, который использует промежуточный класс, который наследует от Parser<Base> но обновлений в Parser<Derived>:

template<class T> 
struct dummy {}; 
template<class T> 
class Creator { 
    typedef shared_ptr<Parser<T> > ParserPtr; 
    typedef shared_ptr<T> ValuePtr; 

    ValuePtr m_output; 
    ParserPtr m_parser; 

    template<class ParserType> 
    class LocalParser : public Parser<T> { 
     ParserType m_parser; 
    public: 
     LocalParser(typename ParserType::ValueType& val): 
      Parser<T>(/*???*/), //problems start here, I must initialize the base 
      m_parser(val) {} 
     void read(std::istream& is) { //use polymorphism to update into some derieved reference 
      m_parser.read(is); 
     } 
    }; 
public: 
    Creator(): //Uses Parser<T> as default parser 
     m_output(new T), 
     m_parser(new Parser<T>(*m_output)) {} 
    template<class ParserType> 
    Creator(dummy<ParserType>) { //Use any parser 
     auto temp = make_shared(new typename ParserType::ValueType); 
     m_output = temp; 
     m_parser = maked_shared(new LocalParser<ParserType>(*temp)); 
    } 
    virtual ValuePtr read()(std::istream& is) { 
     m_parser->read(is); 
     return m_output; 
    } 
}; 

В основном LocalParser это промежуточный класс, который наследует от Parser<T> но обновляет diffrent ссылки от одного этого основание держит , Проблема заключается в том, как инициализировать Parser<T>, особенно когда T является абстрактным (что составляет 99% времени, когда я фактически использую этот класс с производным парсером).

Мой вопрос сводится к «как определить ссылку на (возможно) абстрактный класс, который НЕ будет использоваться?» (или существует какая-либо другая работа, где я не определяю интермидацию, которая наследуется от Parser<T>).

EDIT: Интерфейс Parser - это отдельный код, который я не могу изменить.

+3

почему он должен быть ссылкой вместо указателя? –

+0

Можете ли вы создать ** минимальный **, ** полный ** пример? В этом вопросе много типов, большинство из которых не имеют отношения к тому, что вы просите. – Barry

+0

Это результат, полученный. – stark

ответ

3

Вы не можете создать пустую ссылку. Ссылка должна обратиться к чему-то. Это одно из ключевых различий между ссылкой и указателем. В самом деле, есть возможное решение для Вас:

T& ref;   // error 
T& ref = nullref; // no such thing 

T* ptr = nullptr; // "empty" pointer! 

Другой, возможно, более явное решение, которое позволяет либо ссылки или ничего бы использовать boost::optional:

boost::optional<T&> opt_ref; // empty optional 
opt_ref = some_t; 
Смежные вопросы