Last active
December 15, 2016 01:45
-
-
Save BartVandewoestyne/1a6d718ac1df522413b1 to your computer and use it in GitHub Desktop.
Material for my blog post "Faking QObject derived classes (part 1)".
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Material for my blog post 'Faking QObject derived classes (part 1)'. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* I have the impression that this idea is also the answer described in [1]. | |
* | |
* References: | |
* [1] http://stackoverflow.com/questions/22693729/closest-solution-to-multiple-inheritance-through-qobject-subclasses?rq=1 | |
*/ | |
#include <QObject> | |
#include <iostream> | |
class QObjectInterface { | |
public: | |
virtual ~QObjectInterface() {} | |
virtual QString objectName() = 0; | |
virtual void setObjectName(const QString & name) = 0; | |
}; | |
class FooInterface : public QObjectInterface { | |
public: | |
virtual ~FooInterface() {} | |
virtual void doFooStuff() = 0; | |
}; | |
class Foo : public QObject, public FooInterface { | |
public: | |
QString objectName() { return QObject::objectName(); } | |
void setObjectName(const QString& name) { QObject::setObjectName(name); } | |
void doFooStuff() { std::cout << "Foo::doFooStuff()" << std::endl; } | |
}; | |
class FakeFoo : public QObject, public FooInterface { | |
public: | |
QString objectName() { return QObject::objectName(); } | |
void setObjectName(const QString& name) { QObject::setObjectName(name); } | |
void doFooStuff() { std::cout << "Foo::doFakeFooStuff()" << std::endl; } | |
}; | |
int main() | |
{ | |
FooInterface* fakeFoo = new FakeFoo(); | |
fakeFoo->setObjectName("fake foo"); | |
std::cout << fakeFoo->objectName().toStdString() << std::endl; | |
fakeFoo->doFooStuff(); | |
FooInterface* realFoo = new Foo(); | |
realFoo->setObjectName("real foo"); | |
std::cout << realFoo->objectName().toStdString() << std::endl; | |
realFoo->doFooStuff(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
TEMPLATE = app | |
TARGET = current_solution | |
CONFIG += console | |
SOURCES = current_solution.cpp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <QObject> | |
#include <iostream> | |
class FooInterface | |
{ | |
public: | |
virtual ~FooInterface() {} | |
virtual void doFooStuff() = 0; | |
}; | |
class Foo : public QObject, public FooInterface { | |
public: | |
void doFooStuff() { | |
std::cout << "Foo::doFooStuff()" << std::endl; | |
} | |
}; | |
class FakeFoo : public QObject, public FooInterface { | |
public: | |
void doFooStuff() { | |
std::cout << "Foo::doFakeFooStuff()" << std::endl; | |
} | |
}; | |
int main() | |
{ | |
FooInterface* fakeFoo = new FakeFoo(); | |
fakeFoo->setObjectName("fake foo"); | |
std::cout << fakeFoo->objectName().toStdString() << std::endl; | |
fakeFoo->doFooStuff(); | |
FooInterface* realFoo = new Foo(); | |
realFoo->setObjectName("real foo"); | |
std::cout << realFoo->objectName().toStdString() << std::endl; | |
realFoo->doFooStuff(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
TEMPLATE = app | |
TARGET = failed_attempt | |
CONFIG += console | |
SOURCES = failed_attempt.cpp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <QObject> | |
#include <iostream> | |
class FooInterface : public QObject { | |
Q_OBJECT | |
public: | |
virtual ~FooInterface() {} | |
virtual void doFooStuff() = 0; | |
}; | |
class Foo : public FooInterface { | |
Q_OBJECT | |
public: | |
void doFooStuff() { std::cout << "Foo::doFooStuff()" << std::endl; } | |
}; | |
class FakeFoo : public FooInterface { | |
Q_OBJECT | |
public: | |
void doFooStuff() { std::cout << "Foo::doFakeFooStuff()" << std::endl; } | |
}; | |
int main() | |
{ | |
FooInterface* fakeFoo = new FakeFoo(); | |
fakeFoo->setObjectName("fake foo"); | |
std::cout << fakeFoo->objectName().toStdString() << std::endl; | |
fakeFoo->doFooStuff(); | |
FooInterface* realFoo = new Foo(); | |
realFoo->setObjectName("real foo"); | |
std::cout << realFoo->objectName().toStdString() << std::endl; | |
realFoo->doFooStuff(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
TEMPLATE = app | |
TARGET = second_solution | |
CONFIG += console | |
SOURCES = second_solution.cpp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <QObject> | |
#include <iostream> | |
class Foo : public QObject { | |
public: | |
void doFooStuff() { | |
std::cout << "Foo::doFooStuff()" << std::endl; | |
} | |
}; | |
int main() | |
{ | |
Foo foo; | |
foo.setObjectName("foo"); | |
std::cout << foo.objectName().toStdString() << std::endl; | |
foo.doFooStuff(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
TEMPLATE = app | |
TARGET = starting_point | |
CONFIG += console | |
SOURCES = starting_point.cpp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* When building this solution, I get the errors: | |
* third_solution.cpp:29: Warning: Class FooBar inherits from two QObject subclasses FooInterface and BarInterface. This is not supported! | |
* third_solution.cpp:38: Warning: Class FakeFooBar inherits from two QObject subclasses FooInterface and BarInterface. This is not supported! | |
* | |
* References: | |
* [1] http://stackoverflow.com/questions/8578657/qobject-multiple-inheritance | |
* [2] http://doc.qt.io/qt-4.8/moc.html#multiple-inheritance-requires-qobject-to-be-first | |
* [3] http://stackoverflow.com/questions/22693729/closest-solution-to-multiple-inheritance-through-qobject-subclasses?rq=1 | |
*/ | |
#include <QObject> | |
#include <iostream> | |
class FooInterface : public virtual QObject { | |
Q_OBJECT | |
public: | |
virtual ~FooInterface() {} | |
virtual void doFooStuff() = 0; | |
}; | |
class BarInterface : public virtual QObject { | |
Q_OBJECT | |
public: | |
virtual ~BarInterface() {} | |
virtual void doBarStuff() = 0; | |
}; | |
class FooBar : public FooInterface, public BarInterface { | |
Q_OBJECT | |
public: | |
void doFooStuff() { std::cout << "FooBar::doFooStuff()" << std::endl; } | |
void doBarStuff() { std::cout << "FooBar::doBarStuff()" << std::endl; } | |
}; | |
class FakeFooBar : public FooInterface, public BarInterface { | |
Q_OBJECT | |
public: | |
void doFooStuff() { std::cout << "FooBar::doFakeFooStuff()" << std::endl; } | |
void doBarStuff() { std::cout << "FooBar::doFakeBarStuff()" << std::endl; } | |
}; | |
int main() | |
{ | |
// Use real and fake implementation as a FooInterface. | |
FooInterface* fakeFooBar = new FakeFooBar(); | |
fakeFooBar->setObjectName("fake foobar"); | |
std::cout << fakeFooBar->objectName().toStdString() << std::endl; | |
fakeFooBar->doFooStuff(); | |
FooInterface* realFooBar = new FooBar(); | |
realFooBar->setObjectName("real foobar"); | |
std::cout << realFooBar->objectName().toStdString() << std::endl; | |
realFooBar->doFooStuff(); | |
// TODO: can we find an example that demonstrates that virtual inheritance | |
// with QObject is not supported? | |
} | |
// To force moc-compiler to process this file. | |
#include "third_solution.moc" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
TEMPLATE = app | |
TARGET = third_solution | |
CONFIG += console | |
SOURCES = third_solution.cpp |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment