I am new to c++ and I have the following code in VS2010 using Qt:
// test.h
#pragma once
#include <QtWidgets/QMainWindow>
#include "ui_test.h"
#include "testDevice.h"
#include "testControl.h"
class test : public QMainWindow
{
Q_OBJECT
public:
test(QWidget *parent = 0) : control(device,0) {}
~test();
private:
Ui::testClass ui;
testDevice device;
testControl control;
};
// test.cpp
#include "test.h"
test::test(QWidget *parent) : QMainWindow(parent)
{
ui.setupUi(this);
device.start();
control.start();
}
test::~test()
{
}
// testControl.h
#pragma once
#include <QThread>
#include "testDevice.h"
class testControl : public QThread
{
Q_OBJECT
public:
testControl(testDevice& device, QObject *parent = 0);
protected:
void run(void);
private:
testDevice device;
~testControl(void);
};
// testControl.cpp
#include "testControl.h"
testControl::testControl(testDevice& thisDevice, QObject *parent) : QThread(parent)
{
}
void testControl::run(void)
{
}
testControl::~testControl(void)
{
}
VS2010 is saying "no appropriate default constructor available" and it marks:
test::test(QWidget *parent) : QMainWindow(parent)
{
and
test::~test()
as the error source. I have tried to use testControl as a pointer and as a reference but I got many other errors...could someone please help me out with this one and explain to me whats going on?
You are providing an implicitly inline definition of test's constructor in the test class definition in the header:
test(QWidget *parent = 0) : control(device,0) {}
This is most likely what the compiler is complaining about. Besides that, you go on to provide a different definition in the .cpp file. You can only have one definition.
There are two ways to fix this.
1) implicitly inline definition of the constructor in the class definition. Modify your existing header code to call the appropriate QMainWindow constructor in the initialization list. And remove the constructor definition from the .cpp file:
// in test.h
test(QWidget* parent = 0) : QMainWindow(parent), control(device, 0)
{
ui.setupUi(this);
device.start();
control.start();
}
2) Declare the constructor in the header, and define it in the .cpp:
// in test.h
test(QWidget* parent = 0); // declaration, no definition
// in test.cpp
test::test(QWidget* parent = 0) : QMainWindow(parent), control(device, 0)
{
ui.setupUi(this);
device.start();
control.start();
}
Either of these solutions should work. What you can't have is a combination of the two, which is what your code sample exhibits.
You may also need a definition of test::~test(). In your code sample you only show a declaration.
You have two major issues ongoing:
1) You should probably write this constructor leaving the definition for the constructor in the header behind.
You ran into the trap of two definitions provided, one in the header, and the other in the source file.
You either need to have the declaration in the header, and definition in the source, or the declaration and definition in the header. You cannot have one declaration and two definitions distributed in the header and source files!
You had the empty definition in the header by {} and the other definition with { .... } in the source file. How would the compiler know which one you really wanted? It cannot reliably... even if it picks up either version.
2) Also, your testControl destructor seems to be private. That is not a good idea. Change that destructor to public!
test.h
#pragma once
#include <QtWidgets/QMainWindow>
#include "ui_test.h"
#include "testDevice.h"
#include "testControl.h"
class test : public QMainWindow
{
Q_OBJECT
public:
// Only declare, do not define it here
// Also, for completeness: you should use the "explicit" keyword in here.
explicit test(QWidget *parent = 0);
~test();
private:
Ui::testClass ui;
testDevice device;
testControl control;
};
test.cpp
#include "test.h"
test::test(QWidget *parent = 0)
: QMainWindow(parent)
, control(device,0)
{
ui.setupUi(this);
device.start();
control.start();
}
test::~test()
{
}
testControl.h
#pragma once
#include <QThread>
#include "testDevice.h"
class testControl : public QThread
{
Q_OBJECT
public:
testControl(testDevice& device, QObject *parent = 0);
// Change this to being _public_ rather than _private_ as in your code.
~testControl(void);
protected:
void run(void);
private:
testDevice device;
};
When a class is constructed, all the data members are constructed as well. If there is a default constructor for a particular data member, that one is executed.
If you need to execute a specific non-default constructor, you must use the member initialisation list in order to construct that particular data member.
I suspect that your problem is with either your
testDevice device;
testControl control;
data members, or both.
What are the available constructors for both these classes? If there are no default constructors available, you must initialise them in the members' initialisation list, supplying appropriate parameter arguments.
Related
could you take a look and explain, what am I doing wrong in code below?
#ifndef BACKEND_H
#define BACKEND_H
#include <QObject>
#include <QDebug>
#include <QtQml>
class BackEnd : public QObject
{
Q_OBJECT
Q_PROPERTY(int player READ player WRITE player_change)
QML_ELEMENT
int player;
public:
explicit BackEnd(QObject *parent = nullptr);
signals:
int player_changed(int player);
public slots:
int player_change(int player);
};
#endif // BACKEND_H
cpp:
#include "backend.h"
BackEnd::BackEnd(QObject *parent)
: QObject{parent}
{
}
int BackEnd::player_change(int player)
{
return (player == 1) ? 2 : 1;
}
Error:
Expression cannot be used as a function
Error appears in auto-edited moc file...
Removing Q_PROPERTY makes it fine...
The error says that the Q_PROPERTY macro can't use the member player as a function.
A READ accessor function is required if no MEMBER variable was
specified. It is for reading the property value. Ideally, a const
function is used for this purpose, and it must return either the
property's type or a const reference to that type. e.g.,
QWidget::focus is a read-only property with READ function,
QWidget::hasFocus().
You need to create a getter and use it as the READ function. Or you use MEMBER.
A MEMBER variable association is required if no READ accessor function
is specified. This makes the given member variable readable and
writable without the need of creating READ and WRITE accessor
functions. It's still possible to use READ or WRITE accessor functions
in addition to MEMBER variable association (but not both), if you need
to control the variable access.
Have a look here.
#ifndef BACKEND_H
#define BACKEND_H
#include <QDebug>
#include <QObject>
#include <QtQml>
class BackEnd : public QObject
{
Q_OBJECT
Q_PROPERTY(int foo READ foo WRITE setFoo NOTIFY fooChanged)
Q_PROPERTY(int bar MEMBER bar NOTIFY barChanged)
QML_ELEMENT
public:
explicit BackEnd(QObject *parent = nullptr) : QObject{parent} {}
int foo() const { return m_foo; }
void setFoo(int val) { m_foo = val; emit fooChanged(); }
signals:
void fooChanged();
void barChanged();
private:
int m_foo;
int bar;
};
#endif // BACKEND_H
this is the problem given to me
create a project called datamanager and its base class should be QWidget
add a new class called controller inherited from QObject
and 2 slots called sensordatarecived and startdatacollection in controller
add another class called commonreader class inherited from QObject
define 2 signals called readingStarted() and readCompleted() in commonreader class
add a slot called sendData()
declare a virtual function called monitor() in the commonreader class
add 5 new sensor classes which inherit from the commonreader class
in all of the above classes reimplement the common Monitor() function
using QTimer object implement emit readingStarted() from the monitor() function of each of the 5 classes defined
implement the sendData() slot
emit signal called readcompleted inside the send dataslot()
create the object of each of the above sensor classes in the constructor of the controller
call monitor() function of the method sensor objectfrom startDataCollection()
connect readComplete() signal of each object to sensordatarecieved() of the controller.
these are the steps i have to follow for a project.i am stuck in the 14 th step and i need help.
//controller.h
class controler : public QObject
{
Q_OBJECT
public:
explicit controler(QObject *parent = nullptr);
signals:
public slots:
void sensorDataRecived();
void startDataCollection();
};
//controller.cpp
#include "controler.h"
#include <QDebug>
#include "heart_1_sensor.h"
#include "eye_2_sensor.h"
#include "brain_3_sensor.h"
#include "ear_5_sensor.h"
#include "head_4_sensor.h"
#include "commonreaderclass.h"
controler::controler(QObject *parent) : QObject(parent)
{
commonReaderClass *h1=new heart_1_Sensor;
commonReaderClass *e2=new eye_2_Sensor;
commonReaderClass *b3=new brain_3_sensor;
commonReaderClass *e5=new ear_5_sensor;
commonReaderClass *h4=new head_4_sensor;
}
void controler::sensorDataRecived()
{
qDebug()<<Q_FUNC_INFO<<endl;
}
void controler::startDataCollection()
{
}
//commonreaderclass.h
#ifndef COMMONREADERCLASS_H
#define COMMONREADERCLASS_H
#include <QObject>
class commonReaderClass : public QObject
{
Q_OBJECT
public:
explicit commonReaderClass(QObject *parent = nullptr);
virtual void monitor();
signals:
void readingStarted();
void readCompleted();
public slots:
void sendData();
};
#endif // COMMONREADERCLASS_H
//commonreaderclass.cpp
#include "commonreaderclass.h"
#include <QDebug>
#include <QTimer>
commonReaderClass::commonReaderClass(QObject *parent) : QObject(parent)
{
}
void commonReaderClass::sendData()
{
qDebug()<<"sending data has started"<<endl;
emit readCompleted();
}
//sensor1.h
#ifndef HEART_1_SENSOR_H
#define HEART_1_SENSOR_H
#include "commonreaderclass.h"
class heart_1_Sensor:public commonReaderClass
{
public:
heart_1_Sensor();
virtual void monitor();
};
#endif // HEART_1_SENSOR_H
//sensor 1.cpp
#include "heart_1_sensor.h"
#include <QDebug>
#include <QTimer>
heart_1_Sensor::heart_1_Sensor()
{
}
void heart_1_Sensor::monitor()
{
qDebug()<<"monitoring the heart"<<endl;
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(sendData()));
timer->start(2000);
emit readingStarted();
}
//and another 4 sensors of the same implementation
I agree with #molbdnilo that you should make h1, e2, ... members of the class, instead of local variables in the constructor. But in this case, there is one more consideration: the lifetime of QObject instances is special, because the parent/children relationship between them so the children can be automatically destroyed when the parent is destroyed. I recommend you this book (paper printed versions also available). Specially chapter 2 about classes and chapter 8 about QObject and other important Qt classes. This book is a curriculum, you should follow it from start to end, and also read other books.
controller.h
class Controller : public QObject
{
Q_OBJECT
public:
explicit Controller(QObject *parent = nullptr);
~Controller(); // the destructor
// ... more public members
signals:
// ...
public slots:
// ...
private:
commonReaderClass *m_h1;
commonReaderClass *m_e2;
// ...
};
I've renamed variables h1 to m_h1 and e2 to m_e2, following a common convention for member variable names, and the Controller class name starting with uppercase is another common naming convention.
controller.cpp (the classic C++ way)
Controller::Controller(QObject *parent) : QObject(parent)
{
m_h1 = new heart_1_Sensor;
m_e2 = new eye_2_Sensor;
// ...
}
Controller::~Controller()
{
delete m_h1;
delete m_e2;
// ...
}
controller.cpp (the Qt way)
Controller::Controller(QObject *parent) : QObject(parent)
{
m_h1 = new heart_1_Sensor(this);
m_e2 = new eye_2_Sensor(this);
// ...
}
Controller::~Controller()
{ }
The second version of controller.cpp is generally preferred when writing Qt based programs. You should remember that in C++ every pointer initialized with a new operation should have a corresponding delete operation. There is not automatic "garbage collection" in C++, but QObject provides a fairly comfortable mechanism to automatically delete children objects, so the destructor in this second version may be empty or you can omit entirely.
I've been following a simple QT tutorial and came up with a weird noob question.
https://www.youtube.com/watch?v=F56fSKoNCtk&list=PLS1QulWo1RIZiBcTr5urECberTITj7gjA&index=5
this is the tutorial.
Here's the my_window.h
#ifndef MY_WINDOW_H
#define MY_WINDOW_H
#include <QMainWindow>
namespace Ui {
class MyWindow;
}
class MyWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MyWindow(QWidget *parent = nullptr);
~MyWindow();
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
private:
Ui::MyWindow *ui;
};
#endif // MY_WINDOW_H
and my_window.cpp.
#include "my_window.h"
#include "ui_mywindow.h"
MyWindow::MyWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MyWindow)
{
ui->setupUi(this);
connect(ui->horizontalSlider,SIGNAL(valueChanged(int)),
ui->progressBar,SLOT(setValue(int)));
}
MyWindow::~MyWindow()
{
delete ui;
}
void MyWindow::on_pushButton_clicked()
{
ui->label->setText("Clicked!");
}
void MyWindow::on_pushButton_2_clicked()
{
ui->label->setText("Why...?");
}
In my_window.cpp, the definition of the constructor,
it does the tasks via the member pointer, 'ui' which is a pointer of 'MyWindow type' instance.
I thought 'this' pointer is also a 'MyWindow' class type pointer so i thought i can access the horizontalSlider and progressBar with this pointer too.
But i couldn't.
what makes the difference between two of them?
Your class MyWindow that you define in my_window.h and implement in my_window.cpp is ::MyWindow. Then you have ::Ui::MyWindow which is a totally separate class, and is defined and implemented in auto-generated files by Qt and the Qt tools.
You can have many symbols with the same name, as long as they are defined in different scopes. These symbols can even be different types, like one could be a class, one could be a variable, one could be a function, etc.
I am new in C++ Qt and struggling with the correct use of forward declarations and #include.
What I want to do:
I have a Qt Gui (Class Ui::Gui) where we can set values.
I want to save these values in Gui Class variables.
As soon as a button (Generate Xml) is clicked, I want to pass the object
'ui' to the XmlGeneratorClass, So i can use the values to generate a Xml.
gui.h
#ifndef GUI_H
#define GUI_H
#include <QMainWindow>
#include <QDebug>
#include "xmlgeneratorqobject.h"
namespace Ui {
class Gui;
}
class Gui : public QMainWindow
{
Q_OBJECT
public:
explicit Gui(QWidget *parent = nullptr);
~Gui();
qint8 testvalue = 1;
signals:
void transmitToXmlGen(Ui::Gui*);
private slots:
void on_pushButtonGenerateXml_clicked();
private:
Ui::Gui *ui;
XmlGeneratorQObject *xmlgenerator = new XmlGeneratorQObject();
};
#endif // GUI_H
gui.cpp
#include "gui.h"
#include "ui_gui.h"
Gui::Gui(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Gui)
{
ui->setupUi(this);
connect(this,SIGNAL(transmitToXmlGen(Ui::Gui*)),xmlgenerator,SLOT(receiveFromGui(Ui::Gui*)));
}
Gui::~Gui()
{
delete ui;
}
void Gui::on_pushButtonGenerateXml_clicked()
{
emit transmitToXmlGen(ui);
}
xmlgeneratorqobject.h
#ifndef XMLGENERATORQOBJECT_H
#define XMLGENERATORQOBJECT_H
#include <QObject>
#include <QDebug>
namespace Ui {
class XmlGeneratorQObject;
class Gui;
}
class XmlGeneratorQObject : public QObject {
Q_OBJECT
public:
explicit XmlGeneratorQObject(QObject * parent = nullptr);
private slots:
void receiveFromGui(Ui::Gui*);
};
#endif // XMLGENERATORQOBJECT_H
xmlgeneratorqobject.cpp
#include "xmlgeneratorqobject.h"
XmlGeneratorQObject::XmlGeneratorQObject(QObject *parent){}
void XmlGeneratorQObject::receiveFromGui(Ui::Gui* objectFromGui)
{
qDebug() << objectFromGui->testvalue; // ERROR member access into incomplete type 'Ui::Gui'
}
Expected result:
Access to public variables from passed gui-object should be possible
Actual result:
member access into incomplete type 'Ui::Gui'
Can you please help me learn forward declaration / include?
Is my approach in general okay?
Your xmlgeneratorqobject.cpp needs the line
#include "ui_gui.h"
This gives it the details of the ui widgets. This file is generated by the Qt build system.
I wanted to create a window from a mainwindow, and send it a pointer to my main window. I did it one time, and i would do it again, but the second time, I always have this error at compilation "no appropriate default constructor available"
The main window:
#include "costsimulator.h"
#include "ui_costsimulator.h"
#include "stonepricewindow.h"
CostSimulator::CostSimulator(AionEnhancingSimulator *parent) : ui(new Ui::CostSimulator)
{
ui->setupUi(this);
parentPtr = parent;
stonePrice = createStonePrice();
connect(ui->aionEnhancingSimulator, SIGNAL(clicked()), this, SLOT(showAionEnhancingSimulatorWindow()));
connect(ui->stonePriceButton, SIGNAL(clicked()), this, SLOT(showStonePriceWindow()));
}
CostSimulator::~CostSimulator()
{
delete ui;
}
void CostSimulator::showAionEnhancingSimulatorWindow()
{
this->hide();
parentPtr->show();
}
QStringList *createStonePrice()
{
QStringList *tmp = new QStringList();
tmp->push_back(QString("80-30000000"));
return (tmp);
}
void CostSimulator::showStonePriceWindow()
{
StonePriceWindow *stonepricewindow = new StonePriceWindow(this);
stonepricewindow->show();
}
QStringList *CostSimulator::getStonePrice()
{
return (stonePrice);
}
and the header:
#ifndef COSTSIMULATOR_H
#define COSTSIMULATOR_H
#include <QDialog>
#include "aionenhancingsimulator.h"
namespace Ui {
class CostSimulator;
}
class CostSimulator : public QDialog
{
Q_OBJECT
public:
AionEnhancingSimulator *parentPtr;
explicit CostSimulator(AionEnhancingSimulator *parent);
~CostSimulator();
QStringList *stonePrice;
QStringList *createStonePrice();
QStringList *getStonePrice();
void showStonePriceWindow();
public slots:
void showAionEnhancingSimulatorWindow();
private:
Ui::CostSimulator *ui;
};
#endif // COSTSIMULATOR_H
and the window that cause the problem:
#include "stonepricewindow.h"
#include "ui_stonepricewindow.h"
#include <QStringListModel>
#include <QStandardItemModel>
#include <QtGui>
StonePriceWindow::StonePriceWindow(CostSimulator *parent) : ui(new Ui::StonePriceWindow)
{
ui->setupUi(this);
displayStonePriceList(parent);
}
StonePriceWindow::~StonePriceWindow()
{
delete ui;
}
void StonePriceWindow::displayStonePriceList(CostSimulator *parent)
{
// To do
}
the header
#ifndef STONEPRICEWINDOW_H
#define STONEPRICEWINDOW_H
#include <QDialog>
#include "costsimulator.h"
namespace Ui {
class StonePriceWindow;
}
class StonePriceWindow : public QDialog
{
Q_OBJECT
public:
explicit StonePriceWindow(CostSimulator *parent = 0);
~StonePriceWindow();
void displayStonePriceList(CostSimulator *parent);
private:
Ui::StonePriceWindow *ui;
};
#endif // STONEPRICEWINDOW_H
if I had this " StonePriceWindow() {}" to the header of StonePriceWindow, I have the following error: "multiple default constructors specified" and always the "no appropriate etc .."
Thanks for any help, I can't understand why.
Sorry, but I could not add a comment on the best answer..
I had a similar problem too, it appeared that there was a mismatch between the classname of the code I created and the dialogs' objectName property value in the Qt .ui file.
I opened the .ui file in QtDesigner, and changed the objectName property value to the classname I had used in my code. Afterwards compilation was going fine.
Try adding StonePriceWindow(){} and removing the default parameter for the other constructor.
When you write code like
StonePriceWindow x;
how does compiler know whether you call the parameterless constructor or another one with default value for parent?
You need to either remove the other one, or remove the default value from it.
I found the problem.
In the StonePrinceWindow.ui, there was an obsolete name of the UI, so the auto-generated ui_stonepricewindow keep the obsolete name (even after a clean) and the compiler never find the ctor.
The solution is to change the strings
#ifndef COSTSIMULATOR_H
#define COSTSIMULATOR_H
in either of the files costsimulator.h and ui_costsimulator.h
Qt places the same #ifndef #define expression in auto generated ui_costsimulator.h