I looked up all the different compiler errors that my design seems to cause. All the answers and fixes make sense but I reached a point where fixing one thing raises another bad thing.
My C++ project is getting bigger and bigger so I'm trying to generalize my problem to benefit from the experienced C++ developers out there.
The software I am writing is an XML-parser, that creates UI objects in runtime. I designed ContainerInterface
for the different types of containers I want to use. For example TabWidget
is a subclassed QTabWidget
and it also inherits ContainerInterface
. For now, those are AbsoluteWidget
, TreeWidget
and TabWidget
. All having implementations for the following pure virtual functions defined in ContainerInterface
:
virtual PushButton* createButton(const QString& label, const QString& define, const QPoint& topLeft, const QSize& size) = 0;
virtual CheckBox* createCheckBox(const QString& label, const QString& define, const QString& header, const QPoint& topLeft, const QSize& size) = 0;
virtual ComboBox* createComboBox(const QString& label, const QString& define, const QString& header, const QPoint& topLeft, const QSize& size) = 0;
virtual Image* createImage(const QString& file, const QString& define, const QPoint& topLeft, const QSize& size) = 0;
virtual Led* createLed(const QString& define, const QString& onColor, const QString& offColor, const QPoint& topLeft, const QSize& size) = 0;
virtual Text* createText(const QString& define, const QString& label, const QPoint& topLeft, const QSize& size) = 0;
So in the parser, I can use the ContainerInterface
, for example:
void XmlReader::readCheckBox(ContainerInterface* container, const QString& header)
{
Q_ASSERT(xml.isStartElement() && xml.name() == "checkbox");
QXmlStreamAttributes attr = xml.attributes();
CheckBox* checkBox = container->createCheckBox(getLabel(attr), getDefine(attr), getHeader(attr, header), getTopLeft(attr), getSize(attr));
m_centralWidget->setUIElement(getDefine(attr), checkBox); //this is why i need a return value anyway
}
This saved me a lot of code and works nice. So i would like the ContainerInterface
to also have:
virtual TabWidget* createTabWidget(const QPoint& topLeft, const QSize& size) = 0;
virtual TreeWidget* createTreeWidget(const QStringList& labels, const QPoint& topLeft, const QSize& size) = 0;
And now we come to the part where I'm having a hard time: this would need the implementation of createTabWidget
in TabWidget
and so on (which is fine because I could have a Tabwidget
included in a Tabwidget
, itself included in another TabWidget
). If I use the same design that I used for the other elements (e.g. CheckBox
), this would return a pointer to a new TabWidget
:
TabWidget* TabWidget::createTabWidget(const QPoint& topLeft, const QSize& size)
{
return new TabWidget(topLeft, size);
}
Doing so is giving me a real hard time debugging, so this raises several questions:
- Is the upper
TabWidget::createTabWidget
possible? (without those, it builds fine) - Shall I include the files for the containers e.g.
tabwidget.h
in the container interface to avoid circular depencies? (this gives meexpected class name before '{' token
) - Do I need to forward declare
TabWidget
inTreeWidget
then? (this gives me aninvalid use of incomplete type
error)