2015-06-08 2 views
0

Я пытаюсь создать такую ​​систему, как Java swing, где у вас есть окно, и это окно имеет несколько компонентов, таких как ярлыки (текст/изображения), текстовые поля, проверка Коробки и т. Д. Способ swing заключается в том, что существует класс Component, который является абстрактным, который имеет абстрактный метод рисования, который рисует компонент и некоторые другие методы. Фактическое окно (JFrame) имеет список (всех видов) всех компонентов в окне. Фактические типы этих компонентов неизвестны, но все они расширяют класс Component.C++ создать объект, тип которого является абстрактным классом

Мой Window класс:

class Window { 
public: 
    ... 
    template<typename T, typename std::enable_if<std::is_base_of<Component, T>::value>::type* = nullptr> T addComponent(T component); 
private: 
    ... 
    std::vector<Component> components; 
    ... 
}; 

Component:

class Component { 
public: 
    ... 
    virtual void paintComponent() = 0; 
    ... 
}; 

Где-то вдоль линии, этот код называется:

for each (Component c in components) { 
    c.paintComponent(); 
} 

Однако, я не могу сделать объект типа Component, потому что он абстрактный, хотя фактическими объектами были бы другие типы, которые распространяютComponent и имеют свой собственный метод paintComponent(). Для методов (Window::addComponent()), я могу использовать

template<typename T, typename std::enable_if<std::is_base_of<Component, T>::value>::type* = nullptr> T 

однако, это не работает для переменных.

Итак, мой вопрос, Как сделать объект абстрактного типа, то есть, как мне сделать Component объект (или объект, который расширяет компонент, но чей фактический тип неизвестен)?

Заранее благодарен!

+0

Вы не можете сделать объект абстрактного типа. Вы спрашиваете, как реализовать 'instanceof' в C++? Если это так, проверьте 'dynamic_cast'. (Как побочный вопрос, посмотрели ли вы на существующие кросс-платформенные инструменты для виджетов C++, такие как Qt и wx-widgets?) –

+0

@Andy Извините, я не был ясен по этому вопросу, я хочу создать объект, который расширяет абстрактный тип , но фактический тип которого неизвестен. – ricky3350

ответ

5

Вы не можете создать экземпляр типа абстрактного класса. Вы должны обратиться к нему с помощью указателя. Это заставит вас выполнять ручное управление памятью. Поэтому использование умного указателя, такого как shared_ptr или unique_ptr, может помочь уменьшить головные боли. Использование указателей сделает ваш вектор выглядеть следующим образом

std::vector<Component*> components; 
//     ^Indicates pointer 

, а затем в цикле вы могли бы назвать его как этот

p->paintComponent(); 

Таким образом, вы можете использовать Component для любого типа, который является производным от него.

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

virtual ~Component() { } 
1

В системах, таких как, что, типы, такие как Этикетка, CheckBox, TextBox отдельные классы, полученные из компонента класса. Итак, если вы хотите подобное поведение, вам нужно реализовать новые классы и получить их от . Компонент класс. Вам также необходимо переопределить виртуальные функции.

Смежные вопросы