Лучший метод для создания экземпляра и регистрации производных классов с помощью CRTP?

#c #crtp

#c #crtp

Вопрос:

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

 - class Widget
- class Button : public Widget
- class AdvancedButton : public Button
- etc
  

и я мог бы использовать центральный класс GUI для создания этих виджетов и управления ими:

 class GUI
{ 
public:
    template <class T> 
    Widget* createWidget() {
        auto new_widget = new T();
        return new_widget;
    }
}
  

Это всего лишь тривиальный пример, иллюстрирующий мою точку зрения. Конечно, я бы использовал интеллектуальные указатели, и я обычно сохраняю указатель на вновь созданный объект на карте или в списке. Для создания экземпляров моих виджетов я бы сделал:

auto new_button = gui->createWidget<Button>() который автоматически создаст и зарегистрирует кнопку.

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

Итак, теперь вместо стандартного наследования у меня есть:

 struct BaseWidget {
    virtual ~BaseWidget() {}
};

template <typename Derived>
class Widget : BaseWidget { }
  

и мои подклассы — это что-то вроде:

 template <typename Derived>
class Label : public Widget<Label<Derived>> {
    virtual Labelamp; setter(int i)   { m_i= i; return static_cast<Derived>(*this); }
}
  

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

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

Комментарии:

1. Можете ли вы предоставить некоторую информацию о том, как вы хотели бы создавать экземпляры своих виджетов? Мне немного неясно, что именно не работает.

2. В чем именно проблема? Не могли бы вы подробнее рассказать о «похоже, это исключает мой оригинальный шаблонный способ создания экземпляров виджетов» ?

3. Привет, спасибо за ответ! Когда я пытаюсь вызвать: gui->create_widget<Label>() Я получаю сообщение об ошибке «нет соответствующего вызова функции» и «ошибка вычета / замены аргумента шаблона». Нужно ли мне вместо этого явно вызывать create_widget<Label<Widget>>()?

4. @AndrewLytle Могу я спросить, почему вы используете статический полиморфизм в этом случае? Вы работаете с очень ограниченными ресурсами устройства?

5. Как я уже сказал, это чисто академическое упражнение. Тем не менее, я думаю, что ответил на свой собственный вопрос. Вы не можете совместно использовать указатель на общий базовый класс для всех производных классов, потому что классы не имеют общей базы. Поэтому я, вероятно, мог бы создать их аналогичным образом, но мне нужно хранить разные типы объектов независимо.