Хранение производного объекта внутри другого объекта в качестве базового указателя (C ++) - PullRequest
0 голосов
/ 20 июня 2010

Так вот сделка:

У меня есть конкретный класс Window, представляющий окно операционной системы, которое будет использоваться для рисования. Окно может принимать разные типы, такие как полноэкранный режим, фиксированное окно, окно с изменяемыми размерами, окно без полей и т. Д. Это реализовано с использованием интерфейса IWindowType, в котором происходят определенные типы (классы сокращаются, чтобы сфокусироваться на точке).

class IWindowType
{
public:
    virtual void createWindow(unsigned short width, unsigned short height) = 0;
};

class FixedWindow: public IWindowType
{
public:
    virtual void createWindow(unsigned short width, unsigned short height) 
    { 
         // Fixed window creation implementation
    }
};

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

class Window
{
public:

private:
    IWindowType* mType;
};

Моя проблема в том, что я могу сохранить тип внутри Window, предоставляя Window ответственность за управление его типом. У меня есть два решения с этим дизайном, ни одно из которых мне не нравится.

Во-первых, клиент должен передать динамически назначенный тип окна и иметь дело с перераспределением памяти.

Window testWindow;
testWindow.setType(new FixedWindow());

Это работает, но для этого нужно помнить, чтобы передать динамически размещенный объект, а также использовать уродливое new без соответствующего удаления (в любом случае, если речь идет о клиенте).

Вторым, что я обнаружил после исследования, было использование метода виртуального clone (), который также работает и имеет гораздо лучший синтаксис, поскольку он выполняет глубокое копирование любого передаваемого производного класса, и окно получает контроль над этим скопированным объект.

IWindowType* FixedWindow::clone() const
{
    return new FixedWindow(*this);
} 

void Window::setType(const IWindowType& type)
{
    if(mType)
        delete mType;

    mType = type.clone()
}

Window testWindow;
testWindow.setType(FixedWindow());

Тем не менее, я чувствую, что создание метода clone () для каждого класса, который требует этой функциональности (я вижу много классов, требующих этого с таким дизайном), может стать не только утомительным, но clone () может быть использован этого контекста, который я на самом деле не хочу.

Итак, мой вопрос: есть ли другие способы передать владение производным типом, передаваемым в setType (), в Window, т.е. дать Window его собственную копию для управления? Мне не нужно сохранять этот дизайн, я просто экспериментирую, как делать что-то, поэтому, если доступен лучший дизайн, это приветствуется.

1 Ответ

0 голосов
/ 20 июня 2010

Вам нужен доступ к объектам этого типа вне класса Window? Если вы этого не сделаете, я бы попытался скрыть тот факт, что вы используете класс для представления типа. Может быть, вы могли бы сделать что-то вроде этого:

class Window
{
public:
    enum WindowType
    {
        FixedWindow,
        //more types
    };

    void setType(WindowType type)
    {
        delete mtype;

        //move type creation to some factory class
        mtype = TypeFactory::createType(type);
    }

private:
    IWindowType* mType;
};

Таким образом, вам не нужно беспокоиться о том, как получить объекты типа из внешнего мира. Они просто должны указать, какой тип должен быть в окне, окно решает, как этот тип представлен.

...