I'm trying to figure out how to use multiple files properly. I made a class in the header file. Then a cpp file that included that header file and implemented everything with Stage::Stage(){} etc. I also made a class called Display that has no default constructor, but requires 2 integer arguments. I made a function in Stage class:
Stage::Stage (Display &display_){
display = display_;
}
But it causes an error "no matching function for call to 'Display::Display()'"
Which is true, it doesn't exist, but it shouldnt need to exist. I'm not trying to create a new Display object here, I'm trying to pass an existing one to the Stage object. (I'm using Dev C++)
Your Stage constructor must default-initialize display before executing the body of the constructor. All class members must be constructed before executing the body of the class's constructor. No exceptions. The shown code, therefore, attempts to default-construct display before using the assignment operator on it.
Since Display does not have a default constructor, this fails, hence the complaint from your compiler that there is no defualt constructor.
In this situation you must explicitly construct display in the initialization section of the constructor:
Stage::Stage (Display &display_) : display{display_}
{
}
or, pre-C++11:
Stage::Stage (Display &display_) : display(display_)
{
}
This explicitly constructs the display member right from the beginning, presumably using its copy-constructor.
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 have to do some changes in a project so I have to change some classes. This code was made by another person and I found a really weird problem doing my task (or at least trying until this wild mushroom appeared )
I have the next ClassA.cpp and I want to remove the m_ElemVar(enumType):
CClassA::CClassA(): m_iIntVariable(0), m_fFloatVar(0.0f), m_ElemVar(enumType1)
{
// more variables initizalized there
otherVariable = value;
...
}
the .h :
#include "CMyElement"
class CClassA
{
public:
CClassA();
virtual ~CClassA();
private:
CMyElement m_ElemVar; // THIS is the var
int m_iIntVariable;
float m_fFloatVar;
...
}
So the thing is that I don't want the m_ElemVar(enumType1) there because I will initialize it in another place, BUT if I remove it, when I build the class or the project it says:
error: no matching function for call to ‘CMyElemnt::CMyElemnt()
candidates are CMyElemnt::CMyElemnt(enumTypeName)
while if I remove the m_fFloarVar for example it doesn't complains.... That confuses me a lot because as you can see in the .h there is nothing declared so I understand that this constructor should not expect anything.
I've clean and build it again, and also searched into google but nothing found so any help would be very appreciated. Thank you so much
Looks like CMyElemnt does not have a parameterless constructor so you have to call one that takes the enum. Maybe you could reassign it later if you cannot change its interface.
The issue you are having is all objects of a class must be constructed in order for the class to be constructed. If you don't construct one of the member explicitly then the compiler will do it for you implicitly using the default constructor. Since CMyElemnt does not have a default constructor you will get an error. The reason not initializing m_fFloatVar works is it is a float and the compiler can default construct a float.
To look at a different way anything you can write as
some_type some_name;
Is default constructable. If you have do include parameters like:
some_type some_name(some_variables)
Then it is not default constructable and you need to initialize it yourself.
I've got a design question concerning classes and their constructors in C++. I'm coming from several years of Java experience. In Java, I would do things like this: I've got a class to manage an SQLite DB as a storage backend. In the constructor of this class, I would hand over the path to the applications data directory as a parameter. Then, I would look for the database file, instatiate a connection, and for example load the most current entry of a table for the purpose of caching.
My Problem now is how to do this in C++. My main problem here is that when execution reaches the first statement of the constructor, all class members were already initialized, either implicitly or explicitly.
My question now is: If I had some computations to do on the constructor parameters before using them to initialize the class members, how would I do that in C++?
I've already found that I can simply use assignment to the members in the constructors, but I've also read you should not do that, because it would mean that the members are first initialized with their default constructors, and then initialized again.
What is the canonical way when you have some computation to do (e.g. loading and parsing a configuration file) before class members can be initialized? I would prefer to simply give a path to the constructor, and then do the loading and parsing an member initialization with the loaded values inside the constructor.
Put the computation part in separate function:
class C {
std::string x;
int y;
C(int xarg, int yarg);
};
std::string computeX(int xarg, int yarg) {
...
return result;
}
C::C(int xarg, int yarg) : x(computeX(xarg, yarg)), y(yarg) {}
As the "initialisation" function you may use a global function, a function defined locally in the source file (e.g. in unnamed namespace), or even invoke a lambda defined in place. You can also use a static member function - also if it is private - or a member function of one of the arguments.
I have a subclass of a class named Entity, and I wan't that subclass to override Entity's constructor, but calling Entity's constructor too. So I declare the constructor like this:
EntitySphere(GLuint shader):Entity(shader){
//Code
}
But that method only works if I implement the function there, in the class definition (or I get a lot of errors). How can I achieve the same, but being able to implement the constructor in the .cpp file?
To implement a constructor (or any method, for that matter) outside the class definition, you need to specify the name of the class before the method name:
EntitySphere::EntitySphere(GLuint shader): Entity(shader) {
// ...
}
Notice the EntitySphere:: part before the rest of the method.
Otherwise, the compiler doesn't know which method you're providing the definition for. (Maybe it could be allowed to guess, but what if it guessed wrong and associated that implementation with some other function in your program?)