C++:实现多重继承的最佳实践
C++ : Best practice when implementing Multiple inheritance
我必须将两种类型的图形项(QGraphicsRectItem
和 QGraphicsEllipseItem
)的倍数添加到 QGraphicsScene
(添加到 QGraphicsView
)。每个图形项都应该能够与鼠标和键盘事件交互。所以最初我设计了 classes 如下。
初步设计:
class myQGraphicsRectItem : public QGraphicsRectItem
{
public:
explicit myQGraphicsRectItem();
private:
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void keyPressEvent(QKeyEvent *event);
void focusOutEvent(QFocusEvent *event);
//Many events goes here
void fnCreateRect();
};
class myQGraphicsRectItem : public QGraphicsEllipseItem
{
public:
explicit myQGraphicsRectItem();
private:
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void keyPressEvent(QKeyEvent *event);
void focusOutEvent(QFocusEvent *event);
//Many events goes here
void fnCreateCircle();
};
要了解如何避免重复的事件声明和定义,我阅读了以下答案:
- Multiple Inheritance Ambiguous Call
- Templates only be implemented in the header file?
- Virtual base class
最后设计的class如下。
修改后的设计:
头文件
template <class T>
class myQGraphicsRectItem : public QGraphicsRectItem , public QGraphicsEllipseItem{
/*commented the below event methods in the base classes*/
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void keyPressEvent(QKeyEvent *event);
void focusOutEvent(QFocusEvent *event);
//Many events goes here
}
实现文件
template <class T> myGraphicsItem<T>::myGraphicsItem()
{
this->T::setFlags(QGraphicsItem::ItemIsMovable|QGraphicsItem::ItemIsFocusable);
this->T::setFocus();
}
//**All event function definition goes here....**
template <class T> QGraphicsItem *myGraphicsItem<T>::fnGetRectObject()
{
fnCreateRect();
return (T*)this;
}
调用代码
#include "mygraphicsitem.h"
#include "mygraphicsitem.cpp"
void MainWindow::on_PushButton_clicked()
{
myGraphicsItem<myQGraphicsRectItem> *rr = new myGraphicsItem<myQGraphicsRectItem>();
scene->addItem(rr->fnGetRectObject());
}
并且应用程序使用此修改后的设计按预期工作。但是我对这个设计有些疑惑,如下:
- 这是处理这种情况的最佳做法,还是我应该使用初始方法?还是有其他最好的方法(编写单个代码来处理事件)?
QGraphicsRectItem
和 QGraphicsEllipseItem
都继承自 QAbstractGraphicsShapeItem
。那么我需要处理虚拟基地class概念吗?
根据我使用 Qt 的经验,一个一般性的答案(没有详细阅读您的代码)是:如果您认为您必须使用多重继承来处理 Qt 类 和 sub类,您很可能做错了 - 这反过来很可能表明您没有完全理解该机制。 Qt 设计得很好,如果你按预期做事,你就不需要多重继承。
试着再考虑一下,然后寻找您想要实现的目标的示例。
哇塞,想多了!
any other best method is there (to write single code to handle events)?
对我来说,这个问题并不清楚你想要达到的目标,可能是由于尝试的解决方案,所以我假设有两个 classes,QGraphicsRectItem
和 QGraphicsEllipseItem
,您正在尝试使用单个代码块来处理自定义事件,例如鼠标、按键等。
在这种情况下,Qt 为您提供了调用 installSceneEventFilter.
所需的一切
只需创建一个派生自 QGraphicsItem
的 class 并重新实现您要处理的事件。然后将这个新的 class 添加到具有 installSceneEventFilter
的其他实例
class QGraphicsItemEventsFilter : public QGraphicsItem
{
private:
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void keyPressEvent(QKeyEvent *event);
void focusOutEvent(QFocusEvent *event);
};
实例化过滤器并将其添加到其他classes
QGraphicsItemEventsFilter* pFilter = new QGraphicsItemEventsFilter;
QGraphicsRectItem* pRect = new QGraphicsRectItem;
pRect->installSceneEventFilter(pFilter);
QGraphicsEllipseItem* pEllipse = new QGraphicsEllipseItem;
pEllipse->installSceneEventFilter(pFilter);
现在 pRect
和 pEllipse
的所有事件都将由事件过滤器 pFilter 处理。
我必须将两种类型的图形项(QGraphicsRectItem
和 QGraphicsEllipseItem
)的倍数添加到 QGraphicsScene
(添加到 QGraphicsView
)。每个图形项都应该能够与鼠标和键盘事件交互。所以最初我设计了 classes 如下。
初步设计:
class myQGraphicsRectItem : public QGraphicsRectItem
{
public:
explicit myQGraphicsRectItem();
private:
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void keyPressEvent(QKeyEvent *event);
void focusOutEvent(QFocusEvent *event);
//Many events goes here
void fnCreateRect();
};
class myQGraphicsRectItem : public QGraphicsEllipseItem
{
public:
explicit myQGraphicsRectItem();
private:
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void keyPressEvent(QKeyEvent *event);
void focusOutEvent(QFocusEvent *event);
//Many events goes here
void fnCreateCircle();
};
要了解如何避免重复的事件声明和定义,我阅读了以下答案:
- Multiple Inheritance Ambiguous Call
- Templates only be implemented in the header file?
- Virtual base class
最后设计的class如下。
修改后的设计:
头文件
template <class T>
class myQGraphicsRectItem : public QGraphicsRectItem , public QGraphicsEllipseItem{
/*commented the below event methods in the base classes*/
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void keyPressEvent(QKeyEvent *event);
void focusOutEvent(QFocusEvent *event);
//Many events goes here
}
实现文件
template <class T> myGraphicsItem<T>::myGraphicsItem()
{
this->T::setFlags(QGraphicsItem::ItemIsMovable|QGraphicsItem::ItemIsFocusable);
this->T::setFocus();
}
//**All event function definition goes here....**
template <class T> QGraphicsItem *myGraphicsItem<T>::fnGetRectObject()
{
fnCreateRect();
return (T*)this;
}
调用代码
#include "mygraphicsitem.h"
#include "mygraphicsitem.cpp"
void MainWindow::on_PushButton_clicked()
{
myGraphicsItem<myQGraphicsRectItem> *rr = new myGraphicsItem<myQGraphicsRectItem>();
scene->addItem(rr->fnGetRectObject());
}
并且应用程序使用此修改后的设计按预期工作。但是我对这个设计有些疑惑,如下:
- 这是处理这种情况的最佳做法,还是我应该使用初始方法?还是有其他最好的方法(编写单个代码来处理事件)?
QGraphicsRectItem
和QGraphicsEllipseItem
都继承自QAbstractGraphicsShapeItem
。那么我需要处理虚拟基地class概念吗?
根据我使用 Qt 的经验,一个一般性的答案(没有详细阅读您的代码)是:如果您认为您必须使用多重继承来处理 Qt 类 和 sub类,您很可能做错了 - 这反过来很可能表明您没有完全理解该机制。 Qt 设计得很好,如果你按预期做事,你就不需要多重继承。
试着再考虑一下,然后寻找您想要实现的目标的示例。
哇塞,想多了!
any other best method is there (to write single code to handle events)?
对我来说,这个问题并不清楚你想要达到的目标,可能是由于尝试的解决方案,所以我假设有两个 classes,QGraphicsRectItem
和 QGraphicsEllipseItem
,您正在尝试使用单个代码块来处理自定义事件,例如鼠标、按键等。
在这种情况下,Qt 为您提供了调用 installSceneEventFilter.
所需的一切只需创建一个派生自 QGraphicsItem
的 class 并重新实现您要处理的事件。然后将这个新的 class 添加到具有 installSceneEventFilter
class QGraphicsItemEventsFilter : public QGraphicsItem
{
private:
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void keyPressEvent(QKeyEvent *event);
void focusOutEvent(QFocusEvent *event);
};
实例化过滤器并将其添加到其他classes
QGraphicsItemEventsFilter* pFilter = new QGraphicsItemEventsFilter;
QGraphicsRectItem* pRect = new QGraphicsRectItem;
pRect->installSceneEventFilter(pFilter);
QGraphicsEllipseItem* pEllipse = new QGraphicsEllipseItem;
pEllipse->installSceneEventFilter(pFilter);
现在 pRect
和 pEllipse
的所有事件都将由事件过滤器 pFilter 处理。