2010-06-20 1 views
0

Так вот сделка:Сохранение производного объекта внутри другого объекта в качестве базового указателя (C++)

У меня есть конкретный класс 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 
    } 
}; 

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

class Window 
{ 
public: 

private: 
    IWindowType* mType; 
}; 

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

Прежде всего, нужно, чтобы клиент прошел динамически распределенный тип окна и имел оконное соглашение с де-распределением памяти.

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

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

Второй, который я нашел после исследования, - это использование виртуального метода 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()); 

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

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

+0

Я не уверен, почему люди боятся указателей. Мне нравится ваш первый подход лучше, но я не уверен, что это изменчивое состояние, поэтому, возможно, он заслуживает того, чтобы быть параметром конструктора. (Многие откровенные фанатичные противники raw-ptr на SO будут горячо расходиться со мной здесь). Но вы можете использовать 'scoped_ptr', чтобы избежать собственного управления памятью. – Stephen

+0

@ Stephen: использование умных указателей - это не вопрос фанатизма. Они устраняют любую двусмысленность по поводу владения объектами и обеспечивают удаление объектов в нужное время, устраняя необходимость в таких вопросах, как эта. –

+0

Могу ли я спросить, почему вы просто не делаете «Window» абстрактным базовым классом и извлекаете из него «FixedWindow» и т. Д.? Таким образом вы можете просто сделать «Window * pTestWindow = new FixedWindow()» и т. Д. –

ответ

0

Вам нужен доступ к этим объектам типа вне класса 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; 
}; 

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