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.
Related
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); }
};
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:
Default constructor with empty brackets
(9 answers)
Closed 7 years ago.
I'm pretty new to c++, i'm now trying to learn all the basics,
I know when default constructors are called, but when i tried different syntax it doesn't work like i expected.
Look at the following code:
class a;
class b();
class c(NULL);
'class' is a class i created with default constructor,
for a and c everything works well, but for b it just won't recognize the variable as a class member.
As i see it b and c are basically the same, what's wrong than?
Thanks!
Don't name your class "class", as it is a reserved name.
As for C++, if the constructor takes no parameters, you instantiate it using
Foo a; // note, if you are using c++11, you can do Foo a{};
As opposed to:
Foo b();
Which actually does something totally unexpected*, and declares a function named b that returns a Foo instance.
As for Foo c(null), it won't compile as there is no default constructor that takes an argument.
* It is referred to as "the most vexing parse", though I find that to be an exaggeration. It can certainly catch you by surprise, but just knowing that you can declare a function prototype inside a function, should be enough to remove the "vexing" aspect.
In other words int getMyInt(); is obviously a function prototype when placed outside any function definitions. However, since this is also the case when inside a function definition, int getMyInt(); doesn't do anything it wouldn't normally do... which is to define a function prototype getMyInt that returns an integer.
b is interpreted as a declaration of a function taking no arguments and returning an object of type class.
This is known as the most vexing parse. Edit: This is not the most vexing parse.
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:
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.