Qt多重继承出错
Qt Multiple-inheritance goes wrong
我的一个项目是用 Qt 编写的,我有一个 QWidget Widget
,它应该显示 MyTreeWidget
(继承自 QTreeWidget
)或 MyTableWidget
(继承自 QTableWidget
)
约束
Widget
应该不知道它在和谁说话。因此它必须 (??) 拥有一个由 My(Tree|Table)Widget
继承的 class
MyTreeWidget
和 MyTableWidget
共享很多代码,我不想复制粘贴此代码。所以我想让它们继承自 MyGenericView
继承自 QAbstractItemView
接口
#include <QAbstractItemView>
#include <QTreeWidget>
#include <QTableWidget>
class MyGenericView : public QAbstractItemView
{
Q_OBJECT
public:
MyGenericView();
};
class MyTreeWidget : virtual public QTreeWidget,
virtual public MyGenericView
{
Q_OBJECT
public:
explicit MyTreeWidget(QWidget *parent = 0);
};
class MyTableWidget : public MyGenericView, public QTableWidget { ... };
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0) :
QWidget(parent)
{
m_genericView = new MyTreeWidget();
}
private:
MyGenericView *m_genericView;
};
错误
erreur : invalid new-expression of abstract class type 'MyTableWidget'
m_genericView = new MyTableWidget();
note: because the following virtual functions are pure within 'MyTableWidget':
class MyTableWidget : public QTableWidget, public MyGenericView
MyTreeWidget 也是如此。
那么你会如何纠正这个问题?
编辑:正如下面评论中所建议的,这个答案是基于错误的假设。请参阅下面更好的答案。
首先,您有一个钻石继承问题。你的错误是因为 MyTableWidget 有一个未定义的纯虚成员函数。
但坦率地说,我不确定您为什么要在这里使用多重继承。如果是为了节省代码重复,为什么 MyTreeWidget 和 MyTableWidget 不能通过组合而不是继承来共享行为元素?这绝对是 is-a vs has-a 的情况吗?如果它是特定于共享的小部件的代码,但不以任何方式与 QTableWidget/QTreeWidget 方法重叠,只需编写一个适配器 class,它将填充树或 Table 小部件.
看来您的尝试是不明智的。您派生的两个视图都是便利视图。他们无可救药地将视图与模型混为一谈。如果您的需求很简单并且您只追求方便,那么可以使用它们,但在您的情况下,我认为大部分共享代码都与事物的模型方面相关,而不是与视图相关。您可以通过简单地在股票 QTableView
或股票 QTreeView
上显示 QStandardItemModel
并让 class 使用 QStandardItemModel
来实现您的愿望建立你的数据结构。
如果结果证明是正确的做法,请参阅 this answer。
有关如何执行此操作的更多详细信息
我的一个项目是用 Qt 编写的,我有一个 QWidget Widget
,它应该显示 MyTreeWidget
(继承自 QTreeWidget
)或 MyTableWidget
(继承自 QTableWidget
)
约束
Widget
应该不知道它在和谁说话。因此它必须 (??) 拥有一个由My(Tree|Table)Widget
继承的 class
MyTreeWidget
和MyTableWidget
共享很多代码,我不想复制粘贴此代码。所以我想让它们继承自MyGenericView
继承自QAbstractItemView
接口
#include <QAbstractItemView>
#include <QTreeWidget>
#include <QTableWidget>
class MyGenericView : public QAbstractItemView
{
Q_OBJECT
public:
MyGenericView();
};
class MyTreeWidget : virtual public QTreeWidget,
virtual public MyGenericView
{
Q_OBJECT
public:
explicit MyTreeWidget(QWidget *parent = 0);
};
class MyTableWidget : public MyGenericView, public QTableWidget { ... };
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0) :
QWidget(parent)
{
m_genericView = new MyTreeWidget();
}
private:
MyGenericView *m_genericView;
};
错误
erreur : invalid new-expression of abstract class type 'MyTableWidget'
m_genericView = new MyTableWidget();
note: because the following virtual functions are pure within 'MyTableWidget':
class MyTableWidget : public QTableWidget, public MyGenericView
MyTreeWidget 也是如此。
那么你会如何纠正这个问题?
编辑:正如下面评论中所建议的,这个答案是基于错误的假设。请参阅下面更好的答案。
首先,您有一个钻石继承问题。你的错误是因为 MyTableWidget 有一个未定义的纯虚成员函数。
但坦率地说,我不确定您为什么要在这里使用多重继承。如果是为了节省代码重复,为什么 MyTreeWidget 和 MyTableWidget 不能通过组合而不是继承来共享行为元素?这绝对是 is-a vs has-a 的情况吗?如果它是特定于共享的小部件的代码,但不以任何方式与 QTableWidget/QTreeWidget 方法重叠,只需编写一个适配器 class,它将填充树或 Table 小部件.
看来您的尝试是不明智的。您派生的两个视图都是便利视图。他们无可救药地将视图与模型混为一谈。如果您的需求很简单并且您只追求方便,那么可以使用它们,但在您的情况下,我认为大部分共享代码都与事物的模型方面相关,而不是与视图相关。您可以通过简单地在股票 QTableView
或股票 QTreeView
上显示 QStandardItemModel
并让 class 使用 QStandardItemModel
来实现您的愿望建立你的数据结构。
如果结果证明是正确的做法,请参阅 this answer。
有关如何执行此操作的更多详细信息