Вместо регистрации новых типов данных в методе initFruit и использования глобальных переменных лучше создать класс провайдера:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <cstring>
class Fruit: public QObject
{
Q_OBJECT
public:
virtual Q_INVOKABLE QString name() = 0;
};
class Apple: public Fruit{
public:
QString name(){
return "apple";
}
};
class Banana: public Fruit{
public:
QString name(){
return "banana";
}
};
class FruitProvider: public QObject{
Q_OBJECT
Q_PROPERTY(Fruit* fruit READ fruit WRITE setFruit NOTIFY fruitChanged)
public:
FruitProvider(QObject *parent=nullptr):QObject(parent){}
Fruit* fruit() const{
return m_fruit.get();
}
public slots:
void setFruit(Fruit* fruit){
m_fruit.reset(fruit);
emit fruitChanged();
}
Q_SIGNALS:
void fruitChanged();
private:
QScopedPointer<Fruit> m_fruit;
};
int main(int argc, char *argv[]){
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
FruitProvider provider;
if(argc < 1){
return -1;
}
if (std::strcmp(argv[1], "Apple") == 0){
provider.setFruit(new Apple());
}
else if (std::strcmp(argv[1], "Banana") == 0){
provider.setFruit(new Banana());
}
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("provider", &provider);
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
#include "main.moc"
Text{
text: provider.fruit.name()
}
Обновление:
Как я указывал в комментариях, идея исключения if-elseif-else заключается в стандартизации доступа к свойствам, в случае с Fruit вы можете использовать провайдера. В случае свойств «число» и «цвет» вы можете создать универсальное свойство c, которое обновляется каждый раз, когда изменяются другие свойства, и использовать это свойство для доступа к информации в QML.
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <cstring>
class Peel: public QObject{
Q_OBJECT
Q_PROPERTY(QString color MEMBER m_peelColor NOTIFY peelChanged)
private:
QString m_peelColor;
signals:
void peelChanged();
public:
void someFunction(QString peelColor){
m_peelColor = peelColor;
emit peelChanged();
}
};
class Slice: public QObject{
Q_OBJECT
Q_PROPERTY(int number MEMBER m_slices NOTIFY sliceChanged)
private:
int m_slices;
signals:
void sliceChanged();
public:
void someFunction(int slices){
m_slices = slices;
emit sliceChanged();
}
};
class Fruit: public QObject{
Q_OBJECT
Q_PROPERTY(QVariant common MEMBER m_common NOTIFY commonChanged)
public:
void startEating(){
initFruit();
}
QVariant common() const{
return m_common;
}
Q_SIGNALS:
void commonChanged();
protected:
virtual void initFruit() = 0;
void setCommon(QVariant common){
m_common = common;
emit commonChanged();
}
private:
QVariant m_common;
};
class Apple: public Fruit{
public:
void initFruit(){
slice.reset(new Slice());
slice->someFunction(100);
setCommon(slice->property("number"));
connect(slice.get(), &Slice::sliceChanged, [this](){
setCommon(slice->property("number"));
});
}
private:
QScopedPointer<Slice> slice;
};
class Banana: public Fruit{
public:
void initFruit(){
peel.reset(new Peel());
peel->someFunction("red");
setCommon(peel->property("color"));
connect(peel.get(), &Peel::peelChanged, [this](){
setCommon(peel->property("color"));
});
}
private:
QScopedPointer<Peel> peel;
};
class FruitProvider: public QObject{
Q_OBJECT
Q_PROPERTY(Fruit* fruit READ fruit WRITE setFruit NOTIFY fruitChanged)
public:
Fruit* fruit() const{
return m_fruit.get();
}
public slots:
void setFruit(Fruit* fruit){
m_fruit.reset(fruit);
emit fruitChanged();
}
Q_SIGNALS:
void fruitChanged();
private:
QScopedPointer<Fruit> m_fruit;
};
int main(int argc, char *argv[]){
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
FruitProvider provider;
if(argc < 1){
return -1;
}
if (std::strcmp(argv[1], "Apple") == 0){
provider.setFruit(new Apple());
}
else if (std::strcmp(argv[1], "Banana") == 0){
provider.setFruit(new Banana());
}
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("provider", &provider);
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
provider.fruit()->startEating();
return app.exec();
}
#include "main.moc"
Text{
text: provider.fruit.common
}