This question already has answers here:
How can I initialize base class member variables in derived class constructor?
(7 answers)
Closed 4 years ago.
I have a mistake I cannot understand when initializing member data in an inherited class with two different methods I thought they should be theoretically identical.
class gSolObject
{
public:
gSolObject();
virtual ~gSolObject(){}
bool isCollisionObject;
};
class gPlanetObject : public gSolObject
{
public:
gPlanetObject();
~gPlanetObject(){};
};
gSolObject::gSolObject():isCollisionObject(1)
{
}
gPlanetObject::gPlanetObject():gSolObject(),isCollisionObject(0)
{
}
I get an error class 'gPlanetObject' does not have any field named 'isCollisionObject'.
However when I put the initialization right into the constructor's brackts {..} instead:
gPlanetObject::gPlanetObject():gSolObject()
{
isCollisionObject=0;
}
It compiles fine. Why would that be?
EDIT: This also does not work
gPlanetObject::gPlanetObject():gSolObject(),gSolObject::isCollisionObject(0)
It writes 'expected class-name before '(' token'
You can't initialize member variables declared in base classes, because the base class constructor has already initialized them. All base constructors execute before member constructors.
You can reassign it. Or you can call a base class constructor that takes an argument and initializes its members with that value.
Edited : You can't call a method of a uninitialized object (here gSolObject) and that's why it works when you execute isCollisionObject(0) in the constructor. Furthermore, if you always set it to 0, then you should use default value in the gSolObject constructor.
Related
This question already has answers here:
How to initialize the reference member variable of a class?
(2 answers)
Closed 2 years ago.
I'm trying to pass a class reference to a field, but I get the error "'mazeGenerator::maze' references must be initialized".
I tried initializing 'maze' above the class constructor.
Why is this happening?
class mazeGenerator {
public:
Maze& maze;
mazeGenerator(Maze& mazeObj) {
maze=mazeObj;
}
}
You must initialize data members of reference type with a member initializer list, like this:
mazeGenerator(Maze& mazeObj) : maze(mazeObj) {}
This is also the case with const data members.
Note that putting the declaration of the data member above the constructor doesn't actually make any difference; it could be declared below as well.
Also, your data members (whether they are of reference type or not), should be private to the class.
This question already has answers here:
Why does decltype not see the member declaration? [duplicate]
(3 answers)
Closed 5 years ago.
Why this code is incorrect?
class Method
{
public:
Method(decltype(info2) info1);
virtual ~Method(){}
protected:
QSharedPointer<info> info2;
};
But this code is correct:
class Method
{
public:
virtual ~Method(){}
protected:
QSharedPointer<info> info2;
public:
Method(decltype(info2) info1);
};
why place of class constructor is important?
I thought that place of definition class constructor isnt important.
I believe this part of the standard is relevant [basic.scope.class]/1.1:
The potential scope of a name declared in a class consists not only of the declarative region following the
name’s point of declaration, but also of all function bodies, default arguments,
exception-specification
s,
and
brace-or-equal-initializers
of non-static data members in that class (including such things in nested
classes).
Note that it only mentions default arguments. So this works since the decltype is referred in a default argument:
Method(QSharedPointer<int> info1 = decltype(info2)())
And this also works since it's inside a body:
Method(<...>)
{
decltype(info2) info3;
}
However your example does not work because such a placement of a decltype is not covered by the paragraph I quoted, thus the name info2 is considered out of scope.
Place of QSharedPointer info2;
is important.
'info2' should be defined before using it into decltype (http://en.cppreference.com/w/cpp/language/decltype).
Next would not work either:
void f() {
d();
}
void d() {
}
This question already has answers here:
When do we need to have a default constructor?
(7 answers)
Closed 8 years ago.
I have the following classes:
class ArithmeticExpression
{
public:
ArithmeticExpression(std::string expr);
}
class Command
{
public:
Command(){};
//this is a virtual class
}
class CommandAssign : public Command
{
private:
ArithmeticExpression expr;
public:
CommandAssign();
CommandAssign(ArithmeticExpression);
}
Now when I try to write the constructor for the CommandAssign class as in:
CommandAssign::CommandAssign(ArithmeticExpression expr)
:Command()
{
this -> expr = ArithmeticExpression(expr.getExpr());
}
I get the error:
no matching function for call to ‘ArithmeticExpression::ArithmeticExpression()’
:Command()
Apparently I can fix that by adding an empty constructor in ArithmeticExpression class that does not do anything. What is it so special about this empty constructor that makes it work? I do not explicitly call anywhere. Do you always need to define an empty constructor in C++?
I wanted to emphasize that although from the title it seems that my question is similar to the one some users suggested as being a duplicate of, the answer I was looking for is NOT there. I was simply trying to understand what happens when a constructor is called and how to avoid defining a useless default constructor, which I knew already is not automatically defined by the compiler in the case where I define one with parameters.
A default constructor will only be automatically generated by the compiler if no other constructors are defined.
EDIT:
The default constructor is needed for object initialization.
All members are initialised before the constructor body begins. If one doesn't have an entry in the initialiser list, then it will be default-initialised; but this is only possible (for a class type) if it has a default constructor.
expr is not initialised in the initialiser list, and doesn't have a default constructor (since declaring any constructor prevents one from being implicitly generated), so it can't be initialised - hence the error.
You should initialise it in the list, rather than reassigning it in the constructor body:
CommandAssign::CommandAssign(ArithmeticExpression expr) :
expr(expr.getExpr())
{}
Note that there's no need to explicitly default-construct the Command sub-object. This also requires the constructor of ArithmeticExpression to be public: it's private in your example code.
This question already has answers here:
Why is there no call to the constructor? [duplicate]
(3 answers)
Most vexing parse
(1 answer)
Closed 9 years ago.
#include <iostream>
class Base
{
public:
int id;
};
int main()
{
Base b();
b.id = 1;
}
What is wrong with the object creation in the code above? What is the difference between Base b() and Base b?
This
Base b();
is parsed as a function declaration of a function called b() that returns a Base object. You need this:
Base b;
This will instantiate a Base object and call its default constructor. Note that this will not zero initialize base::id. You can fix this by providing a default constructor that does that:
class Base
{
public:
Base() : id(0) {}
int id;
};
and instantiate in the same way:
Base b;
The problem is that you are not instantiating an object, but rather declaring a function. This:
Base b(); // Function declaration! (not what you want)
Declares a function b() that returns an object of type Base and accepts no argument. Therefore, when you later try to access the member id, the compiler emits an error, because functions do not have members:
b.id = 1; // ERROR! b is a function, accessing member "id" makes no sense
If you want to create an instance of Base, instead, just remove the parentheses:
Base b; // Object instantiation! (what you want)
Notice that in C++11 you can use the uniform initialization syntax to create an instance of a class pretty much the way you were trying to do, but with curly braces instead of parentheses:
Base b{}; // Object instantiation! (what you want, in C++11)
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C++ initialization lists
class Base
{
public:
int m_nValue;
Base(int nValue=0)
: m_nValue(nValue)
{
}
};
In this code, is the constructor initializing m_nvalue member variable?
I am not sure of this syntax:
Base(int nValue=0) : m_nValue(nValue) {}
We normally write it as:
Base(int nValue) { m_nValue = nValue;}
Can some one explain the above syntax of C++?
This syntax:
Base(int nValue=0)
: m_nValue(nValue)
is called the member initializer. It will initialize m_nValue with given nValue. This syntax is usually preferred in C++ since it is executed before the body of the constructor.
It's called member initializer list.
The member initializer list consists of a comma-separated list of initializers preceded by a colon. It’s placed after the closing
parenthesis of the argument list and before the opening bracket of the function body
Conceptually, these initializations
take place when the object is created and before any code within the brackets is executed.
Note:
You can’t use the member initializer list syntax with class methods other than constructors.
The way of initializing a variable in your code is called as member initializer list.
Generally we use such list to initialize const member variable (normal - non const also) we because at the time of construction we can give some value to const variable.
Second type of Initialization is basically a normal Parametrised constructor. That is used when you are having a object and at the time of creation of object you want to initialize the member variable.