Placing class constructor [duplicate] - c++

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() {
}

Related

Why can't a nonstatic data member be used as a default argument? [duplicate]

This question already has answers here:
Nonstatic member as a default argument of a nonstatic member function [duplicate]
(9 answers)
Closed 1 year ago.
Chapter 7.6 of the book C++ Primer says the following:
A nonstatic data member may not be used as a default argument because its value is part of the object of which it is a member. Using a nonstatic data member as a default argument provides no object from which to obtain the member’s value and so is an error.
Member functions can access class members, so why is it a problem when a default argument is used by a member function?
The short answer is: There is no a priori reason why it wouldn't be possible, but in C++ there is no mechanism to do it (at least not directly).
Default arguments are substituted at the call site. For example
void foo(int x = 42);
Then
foo();
is actually
foo(42);
With non-static members this doesn't work:
struct bar {
int y;
void moo(int x = y);
};
bar b;
b.moo(); // -> b.moo(y) ?!?
The default argument is replaced at the call site and this is not necessarily in the scope of the class. Outside of the scope of the class you need an instance to access a member.
Surely there could be rules to make it work, but instead C++ just says you cannot do it. However, you don't need it because there is a straightforward workaround:
struct bar {
int y;
void moo(int x);
void moo() { moo(y); }
};

QT : operator after class declaration [duplicate]

This question already has answers here:
What is this weird colon-member (" : ") syntax in the constructor?
(14 answers)
Closed 1 year ago.
Recently I started working on a QT project, but there are more syntax rules than regular C++.
While declaring class and its constructor, in header file, we simply write
class MyObj : public QObject {
Q_OBJECT
public:
explicit MyObj(QObject* parent = nullptr, <params>, ...)
.
.
<some more declarations>
private:
.
.
<some more declarations>
};
In .cpp file, we can define this constructor as
MyObj::MyObj(QObject* parent, <params>) :
QObject(parent),
...
<some more parameter like arguments, that is what I am exactly asking>
{
<regular initializations>
}
I am asking about the parameter like arguments after the : operator in the first line of declaring an initializing the class.
What are they, why QT needs these?
Note: In QT project examples, you can simply find the "Command Line Writer Async" example. In that project, a proper usage of this fact exists. I am using QT 5.15.
That's not an operator. That's a standard c++ feature called member initializer list.
For example
class Test
{
private:
int test_val;
some_type some_test;
public:
Test() :
test_val(7),
some_test()
{}
.
.
//whatever
}
In this example, when an instance of Test is constructed, the members are constructed(or initialized) as shown in the code. test_val is initialized with 7, and some_test is constructed via the call of the default constructor of some_type.
If you written the code above as follows.
class Test
{
private:
int test_val;
some_type some_test;
public:
Test()
{
test_val=7;
some_test=some_type(args...);
}
}
This is equivalent to.
class Test
{
private:
int test_val;
some_type some_test;
public:
Test() :
test_val(),
some_test()
{
test_val=7;
some_test=some_type(args...);
}
}
Which means that every member is constructed(or initialized) by-default, and then is copy-constructed as requested in the body of Test::Test().
The mere purpose for member initialization list is to specify how the members should be initalized
Member initializer list is the place where non-default initialization of these objects can be specified. For bases and non-static data members that cannot be default-initialized, such as members of reference and const-qualified types, member initializers must be specified.

Why do you have to define an empty constructor c++ [duplicate]

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.

does not have field named [duplicate]

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.

Default parameter issue (c++) [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Nonstatic member as a default argument of a nonstatic member function
Why can member variables not be used as defaults for parameters?
Ok I apologize in advance if I am not seeing something very simplistic here or forgetting some fundamental rule of C++ but I am not sure why this does not work as expected.
Here is a example of code that I can't get to work
class Foo
{
private:
Bar *ptrBar;
public:
void doSomething(int x, Bar *p = ptrBar);
}
The compiler is having an issue with the default parameter to this function. Is there some reason why this wouldn't work.
Basically doSomething would do some operation on a Bar object, and I want it to be the one pointed to by ptrBar by default. Everything seems sound unless I am forgetting something?
You're not allowed to use class members as default parameters, nor this.
8.3.6 Default arguments [dcl.fct.default]
[...] Similarly, a non-static member shall not be used in a default argument, even if it is not
evaluated, unless it appears as the id-expression of a class member access expression (5.2.5) or unless it is
used to form a pointer to member (5.3.1). [...]
The best workaround would be to use overloading:
class Foo
{
private:
Bar *prtBar;
public:
void doSomething(int x, Bar *p);
void doSomething(int x)
{
soSomething(x, ptrBar);
}
}
At the time the compiler is evaluating this, ptrBar is not set. Therefore your default parameter has no default value.
Why not use a default of null and if p in doSomething() is null then use the ptrBar member.