I cam from programming in Java and I thought doing as here [my code] could work the definition of temporal constructors, but I am having problems the proper way of writing the code to just work.
PROBLEM: I want to add a Constructor of the class Coomunication for every port I find in a machine and save it into a vector:
ControlCommunication.cpp:
...
QVector<Comunication *> ports;
...
void ControlCommunication::checkPorts(){
qint16 vendorid = cuquito.getVendorID();
qint16 productid = cuquito.getProductID();
const QString blankString = "N/A";
for (const QSerialPortInfo &serialPortInfo : QSerialPortInfo::availablePorts()) {
Comunication com(serialPortInfo.portName());
addPort(com); // <- I do not know how to get this working well
}
}
ControlCommunication.h:
class ControlCommunication : public QObject
{
Q_OBJECT
public:
explicit ControlCommunication(QObject *parent = nullptr);
QVector<Comunication*> getComunicationPorts(){return comunicationports;}
void addPort(Comunication com);
...
Comunication.h:
#ifndef COMUNICATION_H
#define COMUNICATION_H
#include <QObject>
#include <QSerialPort>
#include <QMainWindow>
class Comunication:public QObject{
Q_OBJECT
public:
Comunication( QString serialPortName);
Comunication();
public:
public slots:
void openSerialPort();
void closeSerialPort();
void writeData(const QByteArray &data);
void readData(QByteArray &data);
void handleError(QSerialPort::SerialPortError error);
QString getPortName(){return portname;};
signals:
private:
QSerialPort *m_serial = nullptr;
QString portname;
};
#endif // COMUNICATION_H
The error I get is: call to implicitly-deleted copy constructor of 'Comunication'
comunication.h:8:20: note: copy constructor of 'Comunication' is implicitly deleted because base class 'QObject' has a deleted copy constructor
qobject.h:449:20: note: 'QObject' has been explicitly marked deleted here
controlcommunication.cpp:27:49: note: passing argument to parameter 'com' here
As I understand from the error message, I cannot call a constructor which is gonna be deleted in that function from other statements. How can i get this working?
The error you're getting mean you can't copy Communication. When you're passing com to addPort, you're making a copy of the object which will be passed to the function. But because you're inheriting a QObject you can't make copies of your objects. Which means you can't those objects by value. You can add pointers or (ideally) a reference to use objects.
But in your case, I don't think that's going to work easily, you seem to want a QVector<Communication*> which I'm assuming will be filled by addPort. But you're creating Communication in your loop which will be delted when it exists the loop, and so pointers to it won't work.
I don't have enough information, and I'm not versed with Qt, so please someone correct if I'm wrong, but I would suggest that you build Communication inside addPort and change QVector<Communication*> to QVector<Communication>.
My intuition would be that Communication doesn't need to inherit from QObject, but I could be wrong. But the data from your program should probably be separated from the Qt stuff, to make things easier to manage.
You are passing the Comunication object by value into the addPort function. This will try to create a copy of the object. But QObjects (and anything derived from QObject) are non-copyable. So you should change your function to take a pointer or reference instead.
Also, you probably need to allocate your objects on the heap because they will go out of scope, freeing any stack memory.
void addPort(Communication *com);
...
for (const QSerialPortInfo &serialPortInfo : QSerialPortInfo::availablePorts()) {
// Allocate on the heap
Comunication *com = new Comunication(serialPortInfo.portName());
// Pass pointer to addPort
addPort(com);
}
Related
I have an app were I need to fetch random questions from a database and expose them to qml dynamically.
So I created a class to store each dataset:
class Question : public QObject
{
Q_OBJECT
Q_PROPERTY(int id READ id)
Q_PROPERTY(QString askedQuestion READ askedQuestion)
public:
Question(int id,
QString askedQuestion);
int getId() const;
QString getAskedQuestion() const;
private:
int mId;
QString mAskedQuestion;
};
And fill them in annother class. In reality it is derrived from an SQLDatabaseModel:
class QuestionGenerator : public QObject
{
Q_OBJECT
public:
explicit QuestionGenerator(QObject *parent = nullptr);
Q_INVOKABLE QVector<Question> getRandomQuestions(int count) const
{
// simplified in reality we fetch random questions from a database.
// the point is we need to add Questions to the vector
// but this does not work since QObject based items cannot get copied
QVector<Question> questions;
questions.reserve(count);
// add questions to vector
return questions;
}
};
I want to expose Question to QML to use the data from Question there so I need to derive it from QObject.
When I fetch the Questions randomly in QuestionGenerator it does not work because QVector does net the not supported copy constructor of QObject.
So how can I fix this?
Again what I want:
Fetch n Questions in C++ and expose them to QML so I can use the data to display.
You can't use QVector<Question> because QObjects are not copyable. But you can use a QVector<Question*> (note the pointer). You can make as many copies as you want of a pointer.
There's other ways to solve your problem too. Like a QAbstractListModel. But the easy solution is just a pointer.
C++ novice here.
I'm trying to teach myself C++ by working on a project to create a Robot that gets commands from and sends telemetry back to a remote server.
I have a TcpCom class on the Robot which contains the socket connection and public functions to send messages and receive messages from the server:
#ifndef TCPCOM_H
#define TCPCOM_H
#define BOOST_DATE_TIME_NO_LIB
#include <boost/asio.hpp>
#include <boost/interprocess/sync/interprocess_semaphore.hpp>
#include <deque>
#include <mutex>
#include "COM.h"
class TcpCom : public COM
{
public:
TcpCom() : io_srv(), tcpSocket(io_srv), remoteHost(""), remotePort(""), connectedToRemoteHost(false), outboundMsgQueue(), outboundMsgQueueMutex(),
messagesInOutboundMsgQueue(0), incomingMsgQueue(), incomingMsgQueueMutex()
{}
int initialize();
void connectToRemoteHost(const std::string host, const std::string port);
void disconnectFromRemoteHost();
bool messagesWaitingInIncomingMsgQueue();
SoftwareBusMsg getMsgFromIncomingMsgQueue();
void addMsgToOutboundMsgQueue(SoftwareBusMsg& sbMsg);
bool isConnected();
private:
void writeOutboundMsgToSocket();
void deserializeHeader(std::string headerStr, MsgHeader& msgHdr);
void addMessageToIncomingMsgQueue(SoftwareBusMsg& sbMsg);
void readIncomingMsgHeader(MsgHeader& msgHdr);
std::string readIncomingMsgData(uint32_t msgDataLength);
SoftwareBusMsg readMsgFromSocket();
void incomingMsgThread();
void outboundMsgThread();
void startReadAndWriteThreads();
boost::asio::io_service io_srv;
boost::asio::ip::tcp::socket tcpSocket;
std::string remoteHost;
std::string remotePort;
bool connectedToRemoteHost;
std::deque<std::string> outboundMsgQueue;
std::mutex outboundMsgQueueMutex;
boost::interprocess::interprocess_semaphore messagesInOutboundMsgQueue;
std::deque<SoftwareBusMsg> incomingMsgQueue;
std::mutex incomingMsgQueueMutex;
//boost::interprocess::interprocess_semaphore messagesInIncomingMsgQueue;
};
#endif
I want the other classes, such as those responsible for motor control, to have the capability to send messages to the server for telemetry/error reporting. I may be wrong here, but it seems like it would be poor design to directly pass an instance of the TcpCom class to each class that needs the ability to send messages to the server.
Instead, I tried creating a EventReporter class that has a private member that is a reference to the TcpComclass. This would allow the encapsulation of code for handling different types of events (info, errors) and I could pass an initialized 'EventReporter' object to everything that needs it.
#include "TcpCom.hpp"
class EventReporter
{
public:
EventReporter(TcpCom& tcpComIn) : tcpCom(tcpComIn)
{}
//Will contain call to tcpCom.addMsgToOutboundMsgQueue()
void reportEvent(std::string eventType, std::string message);
private:
TcpCom tcpCom;
};
When I tried compiling this code I got a few errors:
error: use of deleted function 'TcpCom::TcpCom(const TcpCom&)'
error: use of deleted function 'boost::asio::io_service(const boost::asio::io_service&)'
It looks like my new class would be trying to make a copy of TcpCom, which I thought I was avoiding by passing it by reference.
Should I use something like a unique_ptr to avoid copying TcpCom, or is there a better way to make networking functions accessible from other classes?
Thanks!
Kind of tossed up whether to answer this or close as a typo, so I'll post and let the question's Asker tell me.
In
class EventReporter
{
public:
EventReporter(TcpCom& tcpComIn) : tcpCom(tcpComIn)
{}
//Will contain call to tcpCom.addMsgToOutboundMsgQueue()
void reportEvent(std::string eventType, std::string message);
private:
TcpCom tcpCom; //<- this is not a reference
};
TcpCom tcpCom; defines an instance of TcpCom, not a reference to a TcpCom as the Asker stated they wanted, so tcpCom(tcpComIn) in the member initializer list (Good on them for using the list, by the way. Many C++ programmers who think they are no longer learning don't seem to know they exist) performs the copy They are trying to avoid by passing by reference in the parameter list.
The error messages result from members (std::mutex at the very least. Multiple copies of a mutex would be bad) of TcpCom being uncopyable, so you can't copy one even if you want to.
The simple solution is
class EventReporter
{
public:
EventReporter(TcpCom& tcpComIn) : tcpCom(tcpComIn)
{}
//Will contain call to tcpCom.addMsgToOutboundMsgQueue()
void reportEvent(std::string eventType, std::string message);
private:
TcpCom & tcpCom; //<- change made here
};
Unless the Asker has other uncopyable objects also being copied else where in their code or the the EventReporter instance can outlive the source TcpCom they should be good to go.
I wanted to write a pretty simple code which looks for a string and then outputs the variable assigned to it.
I wanted to learn more about the communication between C++ and QML. So I thought of using a hash map in C++ and then use those functions in QML to list out the result.
I had lot of errors so I basically tried everything to make it work and now my code works. But can someone help me in understanding what I have done.
I have few doubts
I was not able to access my functions loadItemList() and findcubby() but as soon as I included the Q_OBJECT Macro it started working why ?
I have seen in some codes online that they often use something like explicit Itemlist(QObject *parent = 0); why and what does this mean?
I have defined my Hash map as public variable which I know is not good, can someone show me how would I go about for a private hash map.
Here is my header file
#ifndef ITEMLIST_H
#define ITEMLIST_H
#include <QObject>
#include <QHash>
class Itemlist : public QObject
{
Q_OBJECT
public:
Itemlist();
Q_INVOKABLE int find_cubby(QString);
QHash<QString, int> my_itemlist;
};
Here is cpp file
#include "itemlist.h"
Itemlist::Itemlist()
{
my_itemlist["aaaa"]=1;
my_itemlist["bb"]=1;
my_itemlist["cc"]=1;
my_itemlist["dd"]=1;
my_itemlist["ee"]=2;
my_itemlist["ff"]=2;
my_itemlist["gg"]=3;
my_itemlist["hh"]=3;
my_itemlist["ii"]=3;
}
int Itemlist::find_cubby(QString Name)
{
if(my_itemlist.contains(Name))
{
return my_itemlist.value(Name);
}
else
{
return 4;
}
}
Q_OBJECT is necessary as it serves as a marker for the moc code generator to create runtime introspection data for the class. Features such as properties or Q_INVOKABLE depend on that mechanism.
explicit is a C++ key word that marks a constructor as not available for implicit type conversions. Generally, constructors that can be called with a single argument can be used by the compiler to convert between the argument type and the class of that constructor.
E.g.
class Foo
{
public:
Foo(int i) {}
};
void doSomething(Foo f) {}
doSomething(5);
The compiler has an integer, 5, and needs a Foo object. There is a constructor for Foo that takes an int, so it can use it for an automatic type conversion.
explicit Foo(int i) {} removes that option, so the compiler will exit with an error, saying that it can't find a doSomething(int) function.
Use a private: section in your class just like you currently do with public:
While investigating a glibc crash I get this valgrind error:
Invalid write of size 8
at 0x43A3D2: DataAudit::DataAudit(DataAuditModel*, QWidget*) (DataAudit.cpp:15)
by 0x42D318: MainWindow::createNewDataAudit(DataAuditModel*) (MainWindow.cpp:191)
by 0x48CA09: MainWindow::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) (moc_MainWindow.cpp:65)
Invalid write of size 8 seems to indicate a heap block overrun.
Here are the two problem classes, pared down for conciseness:
class IAWidgetModelOwner : public IAWidget
{
public:
explicit IAWidgetModelOwner(IAWidgetModel *model, QWidget *parent = 0) :
IAWidget(model, parent),
pointer1(MAIN_WINDOW),
pointer2(MAIN_WINDOW) // See note below
{ }
private:
MainWindow *pointer1;
MainWindow *pointer2; // See note below
};
class DataAudit : public IAWidgetModelOwner, public Ui::DataAudit
{
public:
explicit DataAudit(DataAuditModel *dataAuditModel, QWidget *parent = 0) :
IAWidgetModelOwner(dataAuditModel, parent),
_dataAuditModel(dataAuditModel) // DataAudit.cpp:15
{ ... }
...
private:
QList<RawLog*> _rawLogs;
DataAuditModel *_dataAuditModel;
};
The puzzling thing, is that the valgrind error does not appear if I remove pointer2 from IAWidgetModelOwner by commenting out the indicated lines above. Removing all references to _dataAuditModel also resolves the error.
Since I am not actually calling new or malloc in this class, I don't understand how the automatic heap allocation could cause such an error. I feel like I'm at a dead end in investigating this bug.
What am I doing wrong, or where is a good place to look next?
Note: MAIN_WINDOW is a globally defined MainWindow pointer pulled in from Globals.h
Somehow,MainWindow::createNewDataAudit() is not allocating an object large enough for your DataAudit object. Focus your debugging efforts there.
Since not enough memory is allocated, initializing the pointer member _dataAuditModel causes the overrun. When you remove the member pointer2 from the base class, you are shrinking the size of the DataAudit object to fit in the memory allotted to it by MainWindow::createNewDataAudit().
Surprise surprise, the actual error was in code that I chose not to include:
class IAWidgetModelOwner : public IAWidget
{
Q_OBJECT
public:
I used the Q_OBJECT macro, but it had no signal or slot declarations. Either of the following solved my problem:
Remove Q_OBJECT
Define a slot public slot: mySlot() {}
In reality, I thought I had declared one of the member functions as a slot.
I certainly don't know how to title this question, sorry.
I'm having some problems to design the following system.
I need a class which will make some work, but this work can be done in a bunch of different ways, say that this work will be made through "drivers".
These drivers can have different interfaces and because of that I need to build a wrapper for each driver.
So I got (or I need) this:
Me ---> MainClass ----> Wrapper ----> Drivers
MainClass is the class I will touch and will call the drivers methods through different wrappers.
Here an example of usage:
MainClass worker;
worker.set_driver("driver_0");
worker.start_process(); //Start process calls a wrapper method which calls a driver's method.
To achieve this I made an interface class:
class Driver_Interface : public QObject
{
Q_OBJECT
public:
Driver_Interface(QObject* parent=0) : QObject(parent){}
virtual bool open()=0;
virtual bool close()=0;
virtual bool write()=0;
virtual bool set_config()=0;
};
A driver wrapper has this shape:
class Driver0 : public Driver_Interface
{
Q_OBJECT
public:
Driver0( QObject* parent=0);
Driver0();
bool open();
bool close();
bool write();
bool set_config();
};
Finally here comes the conflicting point, defining the MainClass:
I would like to avoid to create one member for each wrapper, so I tried this, and right now compiler doesn't complains:
class MainClass
{
public:
MainClass();
~MainClass();
void init();
void set_driver( const QString& );
void start_process();
protected:
QString driver_str;
Driver_Interface* driver; //!<--- Here Here!!!
};
When setting the driver chosen, I do this:
if( driver_str.compare("driver_0")==0 )
this->driver = new Driver_0();
Is this a valid C++ configuration or will I have problems sooner or later?
Basically, what worries me is the creation of the driver of a different type from Driver_Interface, I'm seeing that it casts automatically and no one complains...
Actually I have some problems now compiling, the infamous vtables not defined in Driver_0... does this have some relation with what I want to achieve? UPDATED: I fixed this by deleting the *Driver_Interface* constructor.
To me your basic idea seems to be fine. I would consider separating the creation of drivers into a factory (or at least a factory method) though.
This seems reasonable to me. Having a FactoryMethod or class (AbstractFactory) that creates an object of the required concrete subclass based on some config value is a common pattern.
You could consider having the MainClass implement something like
DriverInterface* createDriver(const string& driverType)
instead of encapsulating the resulting concrete DriverInterface subclass in MainClass. But if you only ever want one concrete DriverInterface instance, the above looks fine.
I would pass "driver_0" to the constructor, and call MainClass::set_driver from there. You can then make MainClass::set_driver private unless you need to change drivers.