Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save BartVandewoestyne/1a6d718ac1df522413b1 to your computer and use it in GitHub Desktop.
Save BartVandewoestyne/1a6d718ac1df522413b1 to your computer and use it in GitHub Desktop.
Material for my blog post "Faking QObject derived classes (part 1)".
Material for my blog post 'Faking QObject derived classes (part 1)'.
/*
* 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();
}
TEMPLATE = app
TARGET = current_solution
CONFIG += console
SOURCES = current_solution.cpp
#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();
}
TEMPLATE = app
TARGET = failed_attempt
CONFIG += console
SOURCES = failed_attempt.cpp
#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();
}
TEMPLATE = app
TARGET = second_solution
CONFIG += console
SOURCES = second_solution.cpp
#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();
}
TEMPLATE = app
TARGET = starting_point
CONFIG += console
SOURCES = starting_point.cpp
/*
* 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"
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