Возможно ли иметь не шаблонный подкласс классового шаблона? - PullRequest
2 голосов
/ 26 октября 2009

У меня есть шаблонный класс, определенный так:

template <class T>
class Command {
public:
    virtual T HandleSuccess(std::string response) = 0;
    virtual std::string FullCommand() const = 0;
    // ... other methods here ...
};

Позволит ли C ++ создавать не шаблонный подкласс шаблонного класса? Я имею в виду, могу ли я сделать что-то вроде этого:

class NoopCommand : public Command<NoopResult> {
public:
    NoopResult HandleSuccess(std::string response);
    std::string FullCommand() const;
    // ... other methods here ...
};

Так как это не работает для меня, потому что он говорит, что следующие виртуальные функции не определены:

T admix::Command<T>::HandleSuccess(std::string) [with T = admix::NoopResult]
std::string admix::Command<T>::FullCommand() const [with T = admix::NoopResult]

Как я могу конкретно определить их для данного T?

Ответы [ 5 ]

4 голосов
/ 26 октября 2009

Как мы выяснили в IRC, это потому, что у вас есть

  1. Сделано ваши функции не чистыми
  2. Нарезал часть производного объекта. Итак, функции базового класса были вызваны, потому что объект больше не был законченным производным объектом.

(Ниже следует мое подозрение в отношении более ранних версий вашего вопроса - я оставляю его для дальнейшего рассмотрения и для того, чтобы комментарии были значимыми)


Я думаю, что проблема заключается в том, что компилятор может свободно создавать экземпляры любых виртуальных функций-членов шаблона класса, даже если он не используется (т.е. не вызывается). Для создания функции потребуется определение функции. Попробуйте добавить это в заголовок, где компилятор найдет их и создаст определение из:

template<typename T>
T Command<T>::HandleSuccess(std::string response) { /* put some default action ... */ }

template<typename T>
std::string Command<T>::FullCommand() const { /* put some default action ... */ }

C ++ Стандарт 14.7.1/9:

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

3 голосов
/ 26 октября 2009

«Виртуальные функции не определены» означает, что вы не определили тела функций NoopCommand :: HandleSuccess и NoopCommand :: FullCommand.

Следующее должно решить вашу проблему.

class NoopCommand : public Command<NoopResult> {
public:
    NoopResult HandleSuccess(std::string response) {}
    std::string FullCommand() const {}
    // ... other methods here ...
};

Или у вас есть NoopCommand.cpp, убедитесь, что он включен в ваш процесс сборки.

2 голосов
/ 26 октября 2009

Шаблон, который вы используете, широко известен как " Любопытно повторяющийся шаблон ". так что да, вы можете сделать это.
Я не могу придумать причину, по которой он не компилируется.

0 голосов
/ 26 октября 2009

litb нашел решение на ## c ++ вчера вечером.

Проблема заключалась в том, что я передавал NoopCommand функции, подобной этой:

void SendCommand(Command<T> command);

Когда я должен был подписать это:

void SendCommand(Command<T>& command);

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

0 голосов
/ 26 октября 2009

Код, который вы дали, компилируется для меня без ошибок (после добавления struct NoopResult { };). Может быть, проблема в коде, который вы пропустили?

...