C ++创建一个类型为抽象类的对象

时间:2015-06-08 01:42:21

标签: c++ abstract-class pure-virtual

我正在尝试创建一个像Java swing这样的系统,你有一个窗口,那个窗口有多个组件,比如标签(文本/图像),文本框,复选框等。 swing的工作原理是有一个Component类,它是抽象的,它有一个抽象绘制方法,它绘制组件和其他一些方法。实际窗口(JFrame)具有窗口中所有组件的列表(各种)。这些组件的实际类型是未知的,但它们都扩展了Component类。

我的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类型的对象,因为它是抽象的,尽管实际的对象是其他类型的 extends Component并拥有自己的{ {1}}方法。对于方法(paintComponent()),我可以使用

Window::addComponent()

但是,这对变量不起作用。

所以,我的问题是,如何创建抽象类型的对象,即如何创建template<typename T, typename std::enable_if<std::is_base_of<Component, T>::value>::type* = nullptr> T 对象(或扩展Component的对象,但实际的类型未知)?

提前致谢!

2 个答案:

答案 0 :(得分:5)

您无法实例化抽象类的类型。你必须通过指针来引用它。这将迫使您进行手动内存管理。因此,使用shared_ptrunique_ptr等智能指针可以帮助减轻头痛。使用指针会使你的矢量看起来像这样

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

然后在你的循环中你会像这样称呼它

p->paintComponent();

这样,您可以将Component用于从中派生的任何类型。

此外,如果要像这样使用Component,它应该有一个虚拟析构函数。这将确保在通过指向Component的指针删除时调用正确的析构函数。这会使析构函数声明看起来像这样

virtual ~Component() { }

答案 1 :(得分:1)

在类似的系统中, Label CheckBox TextBox 等类型是从 Component 类派生的单独类。因此,如果您想要类似的行为,则需要实现新类并从 Component 类派生它们。您还需要覆盖虚拟功能。