Помогите с этим (указатели и полиморфизм) - PullRequest
2 голосов
/ 06 октября 2010

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

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

Какой самый лучший и чистый способ сделать это?

Спасибо

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

class AguiWidgetContainer
{

    std::vector<AguiWidgetBase*> widgets;
    public:
        AguiWidgetContainer(void);
        ~AguiWidgetContainer(void);
        void handleEvent(ALLEGRO_EVENT* event);
        int add(AguiWidgetBase *widget);
        bool remove(int widgetId);
};

Ответы [ 3 ]

1 голос
/ 06 октября 2010

Я могу придумать как минимум два способа сделать это.

1. Укажите шаблон версии add:

template<class T>
int add() {
  widgets.push_back(new T);
}

2. Используйте фабричный класс:

У вас может быть базовый фабричный класс , который определяет методы для размещения (и, возможно, также свободных) виджетов. Затем ваши пользователи предоставляют свой собственный подкласс фабрики, который создает правильный тип виджета. Например:

class AguiWidgetFactory {
  AguiWidgetBase *createWidget() = 0;
};

class AguiSuperWidgetFactory : public AguiWidgetFactory {
  AguiWidgetBase *createWidget() {
    return new SuperTextBoxWidget();
  }
};

Ваш метод add затем принимает объект фабрики в качестве входных данных и использует его для создания нового виджета.

1 голос
/ 06 октября 2010

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

EDIT: Пример:

class IWidget
{
public:
    virtual Size Measure() = 0;
    virtual void Draw(Point) = 0;
    //and so on

    virtual void Release() = 0;
};

class TextBoxWidget : public IWidget
{
    TextBoxWidget() {}
   ~TextBoxWidget() {}
public:
    // implement IWidget functions, etc, etc

    static TextBoxWidget* Create() { return new TextBoxWidget(); }
    virtual void Release() { delete this; }
};

Теперь TextBoxWidget можетможет быть создан только с TextBoxWidget::Create() и выпущен с someTBW->Release() и всегда использует new и delete внутри одной и той же DLL, гарантируя, что они совпадают.

0 голосов
/ 06 октября 2010

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

Почему это кажется вам странным?

Если контейнер начинает нести ответственность за выделение объектов, которые будут содержаться, он нарушает SRP .Я бы порекомендовал вам спроектировать свои интерфейсы так, чтобы они принимали указатели на объекты Widget, которые выделяются пользователями.Контейнер отвечает только за их хранение / хранение / получение.

Пользователь также несет ответственность за удаление выделенных объектов.

Большинство контейнеров STL работают таким образом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...