I have a DB class with several methods. Normally I use them like:
QSqlQuery DB::myfunc(){
QSqlQuery query;
...
return query;
}
I realized i am creating a QSqlQuery object in all methods so I created it in header as private member and want to use same query variable in all my methods. But I am getting:
'QSqlQuery' is deprecated: QSqlQuery is not meant to be copied. Use move construction instead.
:30:5: note: 'QSqlQuery' has been explicitly marked deprecated here
warning when i did this. Anything wrong if i use it like that?
Creating QSqlQuery variable everytime in methods work without any warning.
Obviously, the class is not deprecated but its copy constructor is. See here.
What you want to do is move the object, not copy it, like so:
return std::move(query);
Related
I'm getting an error for what I assume is declaring the incorrect type, but I'm not sure where the issue is or what I need to fix. I'm using two files.
Please tell me if I haven't given enough info, I'm still a newbie. I'd really appreciate the help.
I appreciate you can't change the input for the test, but whoever wrote the test needs to be told it's a bad test.
Data should be initialized through a constructor.
Data members (address and price) should be declared as private not public.
Whoever wrote the test is requiring you to write a bad C++ class.
That said, you can conform with this bad test by adding to the .h file:
HousePrice();
and to the .cpp file
HousePrice::HousePrice():address(""),price(0){}
Thereby giving it the expected default constructor.
Change it to
#include "zillow.h"
HousePrice hp ("1600 Pen. Ave",1561.53);
ASSERT_EQ(hp.price, 1561.53);
Previously you were trying to create your HousePrice object with no constructor parameters, but the only constructor you've written takes address and price.
The error is here:
HousePrice hp;
When you create an object of a class like that, the default constructor of the class is invoked implicitly. But your class definition does not have a default constructor.
Solution:
Since you are not allowed to change the code at the caller's part, you should modify your class definition such that it contains a default constructor. Then it is upto you to decide the initial values or simply leave it empty.
For example:
Add HousePrice() inside the class definition in zillow.h
Add the following into zillow.cpp
HousePrice::HousePrice()
{
address = "";
price = 0.0;
}
The answer is in the error message. You are trying to default-construct an object of HousePrice type, but HousePrice does not have a default constructor.
Add a default constructor (a constructor with no parameters)
Side note: there is no point in having getter or setter functions in this example. Your data members are public and you don't have any constraints on them
I'm reading this Qt doc page about custom types, and it states the following:
The default constructor, copy constructor and destructor are all required, and must be public, if the type is to be integrated into the meta-object system.
Suppose I have an object that needs to be built with some required parameters, because it has no sense to be built using the default constructor, for example:
struct IntPair
{
IntPair(int first, int second);
~IntPair();
};
To make it available in the Qt Meta Object system, as the doc states, it requires the default constructor. But practically, it has no sense to give the opportunity to build an IntPair object without a pair of integer numbers (sorry for the ugly example).
Is there a way to achieve this without implementing the default constructor? I'm thinking about a sort of friendship between my object and the Qt Meta Object system...
Basically, I cannot understand why the default constructor is needed.
There are two parts to the question:
Achieving a custom Meta Object without implementing a default ctor.
Understanding why a default ctor is required by Qt in this case.
Other respondents have addressed (2) already.
I wish to address (1).
I wrote a class, and I intend for users of this class to call a ctor I wrote which requires several arguments. However, because of the Qt-related requirements, I am forced to add a zero-argument constructor.
It would make me happy to at least make the zero-arg ctor private, so that I could enforce that all user code EXCEPT moc-generated "magic" code will be barred from using that ctor.
Hello, happiness! It is possible.
You can indeed use friendship to make the default ctor private and still use Qt Metatype.
It looks something like this:
class MyClass {
Q_GADGET
Q_PROPERTY(QString text READ text)
public:
MyClass(QString text, bool sometruth, int someint);
QString text() const { return text_; }
private:
// Works in my project using Qt 5.12. (see hints below if it fails for you)
friend struct QtMetaTypePrivate::QMetaTypeFunctionHelper<MyClass, true>;
// Prefer the ctor that takes arguments. This ctor only exists to satisfy Qt.
MyClass();
QString text_;
};
There are two ways you can solve the problem of figuring out WHAT to befriend.
You can mark the ctor private, try to recompile, and scrutinize the compiler error to figure out what other type is trying to access the ctor of your class.
Or, you can put an assert(false); in the body of your ctor, create a binary with debug symbols (including Qt debug symbols), then look at the stack in the debugger when the assertion fails. The stack will show the Qt-internal member-function or free function that called into your ctor. Friend whatever that caller is.
This last method (using the debugger) is what worked for me. (I wasn't fluent enough in compiler-ese to discern which type from the output of the gigantic compiler error was what I needed to add as my friend.)
It has to do with QVariant's (templated) implementation.
Look at qvariant.h in the QT5.5 source code tree, and you'll find this:
T t;
if (v.convert(vid, &t))
return t;
return T();
And also:
old->~T();
new (old) T(t); //call the copy constructor
Hence the need for a public constructor/desctructor, and copy-constructor.
The advantage of all of this is being able to use your custom type in signals/slots (and other meta-object magic), but there are drawbacks like in your situation. It's just a trade-off that you have to live with.
As a workaround, you could have some sort of "init()" method that actually initializes the object after it's constructed. Not as safe/elegant, but it works.
As to why, there's a design reason behind it. It involves a "Identity vs Value" discussion that I think is too long to paste here.
As to how, #AlexanderVX commented on using default values in arguments.
Custom data type should have public default constructors because many parts of the Qt framework will call it to avoid returning null pointers. E.g. QVariant and containers accessors (e.g. QHash::value()).
In your case IntPair() : IntPair(0,0) { } should be nice, isn't it ?
In many cases it is convenient to hold data in objects impementing Qt's implicit sharing pattern (see http://doc.qt.io/qt-5/implicit-sharing.html), in which case the default constructor may easily initialize with QSharedDataPointer(0) and every accessor return a default value when pointer is null (e.g. 0 for an int, QString() for a QString, etc.), guess what: every accessor will be able to provide a default value by calling the public default constructor of the data type because it is required to have one :-).
I am new to qt and i have got a question.
I wanted to connect signals and slots.
QObject::connect(_Requests, SIGNAL(newJobsAvailable(const MyClass &)), _Object, SLOT(doSend(const MyClass &)));
The qt complains about not being able to queue MyClass and etc.
How do i declare it correctly with
qRegisterMetaType<const MyClass &>("const MyClass&");
If Qt complains about not being able to queue you class this means that, Qt is unable to copy and put inside QVariant object of your class.
This only means that only direct connection will work. What does it mean? If you are using default value of last argument in connect then connection will not work between threads!
Setting last argument of connect to Qt::DirectConnection should silence the warning, and value Qt::QueuedConnection will not work at all.
Another way to fix it is to register your type. But you should do this without any qualifiers!
qRegisterMetaType<MyClass>("MyClass");
If you are using Qt5 then consider use of Q_GADGET macro in MyClass (just put it in beginning of class definition and add header to HEADERS in pro file).
You need to make sure that MyClass has public default and copy constructors. Because the object might be copied, even if you declare signals and slots with const ref.
If for some reason copy is out of the question then pass pointer as suggested by ratchet
I have several classes (same base class) and only some users allowed to instantiate some. I need to keep allowed classes for a user in a database.
I definitely need some suggestions. Because I think, I should not need to have a list of class names as a string in database and instantiate them in a condition of string comparison. It just does not feel right to me.
Typical scenario is
1. Calling GetAllowedClassesToInstantiate(user) [From Database]
2. Instantiate those classes
Do you have any suggestions?
Regards,
Burak
Make a data structure like this:
class BaseClass;
std::map<std::string, std::function<BaseClass*()> Factories;
and initialize it in the following way:
class One : BaseClass { ... }
void init() {
Factories["One"] = [](){ return new One(); }
}
Basically it will serve as a lookup ClassName -> Constructor.
Keep allowed class names in the database. After you retrieve it, present it to the user and when he chooses an option, look up the proper constructor wrapper function in Factories and use it to instantiate the selected class.
Make sure to keep the database entries up-to-date with the entry keys inFactories.
(I've used some C++11 in the code sample. You can do the same in C++03 with a bit more code, without the lambda expression and std::function, but the idea stays the same.)
I have a C++ class that I need to extend by adding a new private attribute. I also need this to not be tied to a specific class so I'm using define. I've tried to do it the same way I add new methods, but it doesn't seem to have any effect:
%define add_new_attribute(cls)
%extend MyClass {
int new_attribute;
};
%enddef
I don't really care if the new attribute is private or public, even though I'd prefer it be private. The documentation also doesn't say anything about this. Is there another way to do it?
EDIT:
There seems to be no problem with instantiating a new instance attribute from a method however. For example this is possible (which creates a sort of iterator that keeps it's state on the instance):
%pythoncode %{
def mymethod(self):
self.i = self.__dict__.get('i',0)
self.i += 1
print self.i
%}
However I would really need this code to be in C++, because I need to dereference a pointer :).
Not sure why you are using %define. Just appending this to your swig interface file should work (I have not tested it for member variables, but I have used this for member function definitions):
%extend MyClass {
int new_attribute;
}
Note that the last semicolon was redundant.