I've created an SSCE to better explain this.
In a class, I have a variable, a struct, and a declaration of the struct. Within that struct is a constructor, a variable, a struct and a declaration of that struct. And inside THAT struct is a constructor.
So is goes Mother > Daughter > GDaughter aka class > struct > struct
mother.h
#ifndef MOTHER_H
#define MOTHER_H
#include <QSplitter>
class Mother : public QSplitter
{
Q_OBJECT
public:
Mother(int);
int age;
struct Daughter
{
Daughter();
int height1;
struct GDaughter
{
GDaughter();
};
GDaughter *kate;
};
Daughter *tina;
};
#endif // MOTHER_H
Now let's take a look at the constructors/source. Here lies my issue.
mother.cpp
#include "mother.h"
#include <QDebug>
Mother::Mother(int a)
{
age = a;
tina = new Daughter();
}
Mother::Daughter::Daughter()
{
qDebug() << age; //Not going to work... I get it. Daughter isnt a derived class
height1 = 10;
kate = new GDaughter();
}
Mother::Daughter::GDaughter::GDaughter()
{
qDebug() << height1; //Why not? The GDaughter instance is a member of Daughter!
}
Both qDebug() lines throw is not a type name, static, or enumerator.
The goal is to create "child" structs dynamically. So a parent struct might have 0 child structs, 1 child struct, or even 100 child structs. That is why I am using structs instead of derived classes. This setup looks like it would work except for the problem where "parent" variables can't be accessed.
I will include the other files anyway:
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "mother.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
mom = new Mother(50);
}
MainWindow::~MainWindow()
{
delete ui;
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "mother.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
Mother *mom;
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
If I am misunderstanding how to go about making something like this then let me know.
Thanks for your time.
AFTER ANSWER
In the mother.h I added parent pointers:
struct Daughter
{
Daughter(Mother *p); //Here
int height1;
struct GDaughter
{
GDaughter(Daughter *p); //And here
};
GDaughter *kate;
};
and in mother.cpp I filled in the needed code:
Mother::Mother(int a)
{
age = a;
tina = new Daughter(this); //Here
}
Mother::Daughter::Daughter(Mother *m) //Here
{
qDebug() << m->age; //Here
height1 = 10;
kate = new GDaughter(this); //Here
}
Mother::Daughter::GDaughter::GDaughter(Daughter *d) //Here
{
qDebug() << d->height1; //Here
}
keep pointer(std::weak_ptr if you use smart pointers, for example) to parent class object in nested object.
explicit MainWindow(QWidget *parent = 0);
look at Qt code here, you pass pointer to the parent object in constructor,
if parent is nullptr that means MainWindow has no parent object, Also you can keep
pointer to MainWindow parent object and then static_cast it to exact class
#include <iostream>
class A {
class B{
public:
B(A *p):parent(p) { parent->hello(); }
private:
A *parent;
};
public:
A() { b = new B(this); }
void hello() { std::cout << "hello world" << std::endl; }
private:
B *b;
};
Related
I am trying to access the member of a class declared in another class as an attribute.
The project class has a workArea that is also a class defined in the project.h.
I instanciate a project in the main, and then I send it to the mainWindow through its constructor. Once in the mainWindow constructor I try to access project->lat that works fine, but project->workArea->latInf crashes.
Any help will be highly appreciated.
project.h
#ifndef PROJECT_H
#define PROJECT_H
#include <QObject>
class WorkArea{
public://attributes
int latInf = 30;
public://methods
WorkArea()//Default constructor
{
}
~WorkArea();
};
class Project : public QObject
{
Q_OBJECT
public: //attributes
int lat = 20;
WorkArea* workArea;
public: //methods
explicit Project(QObject *parent = nullptr);
signals:
public slots:
};
#endif // PROJECT_H
main.cpp
#include "ui/mainwindow.h"
#include <QApplication>
#include "project.h"
int main(int argc, char *argv[])
{
Project* pj;
QApplication app(argc, argv);
MainWindow w( 0 , pj);
w.show();
return app.exec();
}
mainWindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent, Project *project) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
try
{
qDebug() << "Project latInf" << project->lat << "\n"; // works fine
qDebug()<< "Project lowLeft: " << project->workArea->latInf << "\n" ; // crashes
}
catch(std::exception &ex)
{
qDebug() << ex.what() ;
}
catch (...)
{
}
}
That was it. Thanks #eyllanesc. I forgot to create workArea. I though just instanciting it as an attribute in Project was fine, but I had to fill that memory space in the constructor of project.
project.h
#ifndef PROJECT_H
#define PROJECT_H
#include <QObject>
class WorkArea{
public://attributes
int latInf = 30;
public://methods
WorkArea()//Default constructor
{
}
~WorkArea();
};
class Project : public QObject
{
Q_OBJECT
public: //attributes
int lat = 20;
WorkArea* workArea;
public: //methods
explicit Project(QObject *parent = nullptr){
workArea = new WorkArea;
}
signals:
public slots:
};
#endif // PROJECT_H
I am trying to create QQuickWidget based application.
What i am trying to do:
Class A(game.h) and Class B(gamestate.h) are forward declared. Class A is main QQuickWidget class with methods. Class B QObject derived class contains signals, slots, variables and methods.
Class B Variable values can set from class A -- Working
When variable value changes signal should be emitted -- working
when signal was emitted slot method should be called in class B -- working
Class B should invoke a method in class A -- working
Class A should create another qquickwidget -- NOT WORKING
(No compiling error. Application crashes on load)
I tried to call from class A and showIntro() function working fine. But when tried to call from class B its not working.
Game.h
#ifndef GAME_H
#define GAME_H
#include <QQuickWidget>
class GameState;
class Game: public QQuickWidget
{
Q_OBJECT
public:
Game();
GameState *gameState;
void showIntro();
public slots:
void onStatusChanged(QQuickWidget::Status);
};
#endif // GAME_H
Game.cpp
#include "game.h"
#include <QQuickWidget>
#include <QDebug>
#include "gamestate.h"
Game::Game(): QQuickWidget()
{
gameState = new GameState(this);
mainScreen = new QQuickWidget();
connect(this, SIGNAL(statusChanged(QQuickWidget::Status)), this, SLOT(onStatusChanged(QQuickWidget::Status)));
setFixedSize(450, 710);
setSource(QUrl("qrc:/EmptyScreen.qml"));
}
void Game::onStatusChanged(QQuickWidget::Status status)
{
switch(status)
{
case QQuickWidget::Ready:
qDebug() << "hi";
gameState->setValue(1);
//showIntro();
break;
case QQuickWidget::Error:
qDebug() << "Error";
break;
}
}
void Game::showIntro()
{
mainScreen->setSource(QUrl("qrc:/MainScreen.qml"));
mainScreen->setAttribute(Qt::WA_TranslucentBackground);
mainScreen->setParent(this);
}
Here is my Gamestate.h
#ifndef GAMESTATE_H
#define GAMESTATE_H
#include <QObject>
class Game;
class GameState : public QObject
{
Q_OBJECT
public:
explicit GameState(QObject *parent = 0);
int value() const {return m_value; }
Game *game;
signals:
void valueChanged(int newValue);
public slots:
void setValue(int value);
void stateChanged(int value);
private:
int m_value;
};
#endif // GAMESTATE_H
GameState.cpp
#include "gamestate.h"
#include "game.h"
GameState::GameState(QObject *parent) : QObject(parent)
{
m_value = 0;
connect(this,SIGNAL(valueChanged(int)), this, SLOT(stateChanged(int)));
}
void GameState::setValue(int value)
{
if(value != m_value)
{
m_value = value;
emit valueChanged(value);
}
}
void GameState::stateChanged(int value)
{
if(value == 1)
{
game->showIntro();
}
}
and my final main.cpp
#include <QApplication>
#include <QQmlApplicationEngine>
#include "game.h"
Game *game;
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
game = new Game();
game->show();
return app.exec();
}
Pls suggest me what could be the issue.
Member variable Game* game of class GameState is not initialized and therefore the program crashes when trying to dereference the pointer within GameState::stateChanged().
Change the constructor of GameState to the following:
// in gamestate.h
explicit GameState(Game *parent = 0);
// in gamestate.cpp
GameState::GameState(Game *parent) : QObject(parent), game(parent)
{
m_value = 0;
connect(this,SIGNAL(valueChanged(int)), this, SLOT(stateChanged(int)));
}
i'm trying to make a simple currency converter and I have some problems with my class designed to make the calculations.
I want to create an object of this class in my MainWindow to use the total variable for displaying the result in a widget on my appi form.
Member functions aren't all here yet, but the problem I have is that i get a
'Calculator' : no appropriate default constructor available error in mainwindow.cpp
While I do know what that means, I don't know how to avoid (solve) the issue because i kind of need the reference on the map to get the echange rates needed.
.cpp
#include <QObject>
#include <QString>
#include <QDebug>
#include <ui_mainwindow.h>
class Calculator
{
public:
explicit Calculator(QMap<QString,double> ¤cy_map);
void multiply(double x, double y);
void getValues(QString strFrom, QString strTo);
private:
double total, firstCurr, secondCurr;
QMap<QString,double> ↦
};
.h
#include "calculator.h"
Calculator::Calculator(QMap<QString,double> ¤cy_map):map(currency_map)
{
total = 0;
firstCurr = 0;
secondCurr= 0;
}
void Calculator::getValues(QString strFrom, QString strTo)
{
QMapIterator<QString, double> i(map);
while(i.hasNext())
{
if(i.key() == strFrom)
firstCurr=i.value();
if(i.key() == strTo)
secondCurr = i.value();
}
}
void Calculator::multiply(double x, double y)
{
total = x * y;
}
and now im trying to create an object of that class in my MainWindow class:
#include <QMainWindow>
#include <ui_mainwindow.h>
#include "calculator.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QMap<QString,double> ¤cy_map, QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
parser currency_parser;
Calculator calc; // error
};
MainWindow.h
MainWindow::MainWindow(QMap<QString, double> ¤cy_map, QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->from_Combox->addItems(currency_parser.currency_list);
ui->to_Combox->addItems(currency_parser.currency_list);
}
the idea behind was that i have a Map in my main in which i save all my data needed and pass the map around to classes that use it.
i'll post my main even tho im not sure if it's needed
#include "downloader.h"
#include "mainwindow.h"
#include "parser.h"
#include "calculator.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QMap<QString,double> currency_map;
downloader d;
d.Do_download();
parser p;
p.read_line(currency_map);
MainWindow w(currency_map);
w.show();
return a.exec();
};
The error occurs, because you don't specify the appropriate constructor for class Calculator in the MainWindow constructors member initializer list (the compiler want's to use the default constructor then):
MainWindow::MainWindow(QMap<QString, double> ¤cy_map, QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
, calc(currency_map) // <<<<<<<<<<<<<<
{
// ...
}
I'm trying to make use of interfaces in Qt/C++, but I keep getting a compile error which makes no sense to me, because I have implemented the virtual functions in the derived class. So I was hoping for some help :) Oh yeah, and the compile error is "cannot declare variable 'w' to be of abstract type 'Widget' because the following virtual functions are pure within 'Widget': startGame(), getBoard(), gameFinished().
Main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
ADTType.h
#ifndef ADTTYPE_H
#define ADTTYPE_H
class ADTType
{
public:
virtual void startGame() = 0;
virtual void getBoard() = 0;
virtual void gameFinished() = 0;
virtual ~ADTType() {}
};
Q_DECLARE_INTERFACE(ADTType, "ADTType")
#endif // ADTTYPE_H
Widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QSignalMapper>
#include <QHBoxLayout>
#include <QPushButton>
#include "ADTType.h"
class Widget : public QWidget,
public ADTType
{
Q_OBJECT
Q_INTERFACES(ADTType)
public:
explicit Widget(QWidget *parent = 0);
~Widget();
private:
QHBoxLayout * mainLayout;
QPushButton * startButton;
QPushButton * buttons[10];
QSignalMapper * map;
};
#endif // WIDGET_H
Widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent) :
QWidget(parent)
{}
Widget::~Widget()
{}
void Widget::startGame() {
for (int i = 0; i < 10; i++) {
buttons[i]->setStyleSheet("QPushButton {background-color: normal}");
}
setButtons(true);
startButton->setDisabled(true);
}
void Widget::getBoard() {
bool * cells = game->getCells();
for (int i = 0; i < 10; i++) {
if (!cells[i]) {
buttons[i]->setStyleSheet("QPushButton {background-color: red}");
buttons[i]->setEnabled(false);
}
}
}
void Widget::gameFinished() {
int answer = game->getAnswer();
buttons[answer]->setStyleSheet("QPushButton {background-color: green}");
setButtons(false);
game->reset();
QMessageBox::information(this,tr("Finito"),tr("You found it."),
QMessageBox::Ok);
startButton->setEnabled(true);
}
class Widget : public QWidget,
public ADTType
So Widget inherits from the abstract class ADTType. However, you don't declare the overrides (startGame() etc) in your Widget class, but you only define them in the Widget.cpp file. You also need to declare them in the Widget.h class header
// need these declarations inside the class Widget in Widget.h
virtual void startGame();
virtual void getBoard();
virtual void gameFinished();
Minimal example here.
You derived ADTType abstract class from the Widget so you need to override pure virtual functions in the Widget class otherwise it also will become abstract.
class Widget : public QWidget,
public ADTType
{
...
void startGame() { ... }
void getBoard() { ... }
void gameFinished() { ... }
};
I want to write an application which consists of several plugins. My idea is that the plugin itself is always just a factory which then can create the required object.
So I created an Interface for the pluginfactory called AbstractFactoryPlugin with a pure virtual method called create. Because of the fact that I want to have several different plugins (factories) with the same interface I can’t put the Q_DECLARE_INTERFACE macro in the AbstractFactoryPlugin header file.
So for a sample plugin I created an Interface which inherits from AbstractFactoryPlugin called IMyObjectFactoryPlugin and declared this interface with the DECLARE macro. Further the MyObjectFactoryPlugin then inherits from QObject and IMyObjectFactoryPlugin.
But when I load the plugin and call the create function, the create function of MyObjectFactoryPlugin seems to be never called. What am I doing wrong?
Many thanx in advance.
Sourcecode:
#ifndef ABSTRACTPLUGINFACTORY_H
#define ABSTRACTPLUGINFACTORY_H
#include "IAnObject.h"
class AbstractFactoryPlugin
{
public:
virtual ~AbstractFactoryPlugin() {}
virtual IAnObject *create(QObject *parent) = 0;
};
#endif // ABSTRACTPLUGINFACTORY_H
#ifndef IMYOBJECTFACTORYPLUGIN_H
#define IMYOBJECTFACTORYPLUGIN_H
#include "AbstractFactoryPlugin.h"
#include <QtPlugin>
class IMyObjectFactoryPlugin : public AbstractFactoryPlugin
{
public:
virtual ~IMyObjectFactoryPlugin() {}
};
QT_BEGIN_NAMESPACE
Q_DECLARE_INTERFACE(IMyObjectFactoryPlugin,
"org.MyObjectFactoryPlugin");
QT_END_NAMESPACE
#endif // IMYOBJECTFACTORYPLUGIN_H
#ifndef MYOBJECTPLUGIN_H
#define MYOBJECTPLUGIN_H
#include <QtPlugin>
#include "IMyObjectFactoryPlugin.h"
#include "AbstractFactoryPlugin.h"
class MyObjectFactoryPlugin : public QObject, IMyObjectFactoryPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.MyObjectFactoryPlugin" )
Q_INTERFACES(IMyObjectFactoryPlugin)
public:
MyObjectFactoryPlugin(QObject *parent = 0);
IAnObject *create(QObject *parent);
};
#endif // MYOBJECTPLUGIN_H
#include "MyObject.h"
#include "MyObjectFactoryPlugin.h"
#include <QDebug>
MyObjectFactoryPlugin::MyObjectFactoryPlugin(QObject *parent) :
QObject(parent)
{
}
IAnObject *MyObjectFactoryPlugin::create(QObject *parent)
{
qDebug() << Q_FUNC_INFO << "was called";
return new MyObject();
}
#ifndef IANOBJECT_H
#define IANOBJECT_H
class IAnObject
{
public:
IAnObject() {isInitialized = false;}
virtual ~IAnObject() {}
virtual bool initialize() = 0;
protected:
bool isInitialized;
};
#endif // IANOBJECT_H
#include "IAnObject.h"
#ifndef MYOBJECT_H
#define MYOBJECT_H
class MyObject : public IAnObject
{
public:
MyObject();
bool initialize();
};
#endif // MYOBJECT_H
#include "MyObject.h"
MyObject::MyObject()
{
}
bool MyObject::initialize()
{
return true;
}
#include <QCoreApplication>
#include <QDir>
#include <QPluginLoader>
#include <QDebug>
#include <E:/QtProjects/_test_PlugIn/MyPlugin/AbstractFactoryPlugin.h>
#include <E:/QtProjects/_test_PlugIn/MyPlugin/IAnObject.h>
#include <E:/QtProjects/_test_PlugIn/MyPlugin/IMyObjectFactoryPlugin.h>
IAnObject *loadPlugin()
{
QDir dir(QCoreApplication::applicationDirPath());
qDebug() << dir;
foreach(QString fileName, dir.entryList(QDir::Files))
{
QPluginLoader pluginLoader(dir.absoluteFilePath(fileName));
QObject *plugin = pluginLoader.instance();
qDebug() << fileName;
if(plugin)
{
qDebug() << "##### Plugin load ok #####";
AbstractFactoryPlugin *abstractFactoryPlugin = reinterpret_cast<AbstractFactoryPlugin *>(plugin);
return abstractFactoryPlugin->create(NULL);
}
}
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qDebug() << "loadPlugin:" << loadPlugin();
return a.exec();
}
Any Qt5 plugin must inherit from QObject, if you want your base class to be independent from QObject you'll have to create an intermediary class that inherits both AbstractFactoryPlugin and QObject (let's call it AbstractMyObjectFactoryPlugin).
#ifndef ABSTRACTMYOBJECTFACTORYPLUGIN_H
#define ABSTRACTMYOBJECTFACTORYPLUGIN_H
#include "AbstractFactoryPlugin.h"
class AbstractMyObjectFactoryPlugin : public QObject, public AbstractFactoryPlugin
{
Q_OBJECT
public:
AbstractMyObjectFactoryPlugin(QObject *parent = 0) : QObject(parent) { }
virtual ~AbstractMyObjectFactoryPlugin() { }
};
Q_DECLARE_INTERFACE(AbstractMyObjectFactoryPlugin,
"org.AbstractFactoryPlugin");
#endif // ABSTRACTMYOBJECTFACTORYPLUGIN_H
To create a plugin, you'll have to inherit from this class and override the create() method:
class MyObjectFactoryPlugin : public AbstractMyObjectFactoryPlugin
{
Q_OBJECT
Q_INTERFACES(AbstractMyObjectFactoryPlugin)
Q_PLUGIN_METADATA(IID "org.MyObjectFactoryPlugin" FILE "MyObjectFactoryPlugin.json")
public:
MyObjectFactoryPlugin(QObject* parent = 0) : AbstractMyObjectFactoryPlugin(parent) { }
virtual IAnObject *create(QObject *parent);
virtual ~MyObjectFactoryPlugin() { }
};
To cast the loaded plugin (a QObject) to AbstractFactoryPlugin safetly, you'll have to cast it to the intermediary class first.
AbstractFactoryPlugin * objectFactoryPlugin = qobject_cast< AbstractMyObjectFactoryPlugin * >(plugin);
The implicit assignment will cast it to the right base class.
Note: You'll have to check if the cast is successful first if you have other inheritance trees.