Say i have the following class :
class A
{
public:
A() {
}
A(int a):_a(a){
}
int _a;
};
And the following function :
void someFunc (A a)
{
cout << a._a;
}
So the following line in the program works fine :
someFunc (5); // Calls A(int a) Constructor.
But the following does not :
someFunc(); //Compile error
One can expect that if it can build A when getting an integer,
why not build one using the default constructor as well, when called with no arguments?
Because someFunc() requires an argument and you have not provided an overload which does not. An implicit conversion from int to A exists, but that doesn't mean you can just ignore the function's signature and call it with no arguments. If you would like to call it with no arguments them assign a default value to a.
void someFunc(A a = A()) {
/* stuff */
}
Because you didn't call the function with an argument that turned out to be convertible, you called the function with no arguments. That's a different overload, one you haven't provided.
Consider these options:
Call the function like this: someFunc(A()).
Define a default value for the function parameter: void someFunc (A a = A()) { ... }.
Provide the no-argument overload: void someFunc() { someFunc(A()); }
This is because the signature of someFunc() does not match that of void someFunc (A a).
According to C++ standard, Section 13.3.2.3:
First, to be a viable function, a candidate function shall have enough parameters to agree in number with the arguments in the list.
A candidate function having more than m parameters is viable only if the (m+1)-st parameter has a default argument
None of this applies in this case, so void someFunc (A a) is not considered viable for the invocation with an empty parameter list.
Nitpick. From the 2003 C++ Standard,
17.4.3.2.1 Global names - ...
- Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace
I would tell you that it's poor practice to start any variable name with _. Especially as you may extend that practice into named variable arguments (int foo(int _a)), or do it with camelcase without thinking (int _MyVar). I personally do things like
int a_;
Will you ever actually have trouble? Probably not. But it's good practice not to start your anything with an underscore. Never with two underscores anywhere in the name, or started by an underscore followed by an uppercase letter, of course, too.
I'm not really providing an answer here, but it's useful information all the same... There are times when you really don't want to allow someFunc(5) to work, because it might lead to incorrect operation, or simply be misleading. In such cases you can declare the constructor as explicit:
class A
{
public:
A() {} // Are you sure you don't want to initialise _a here?
explicit A(int a) :_a(a) {}
int _a;
};
And as others have already said you can specify a default parameter for someFunc:
void someFunc( A a = A() );
Now:
someFunc(); // Calls A() by default
someFunc(5); // Not allowed because of implicit construction
someFunc(A(5)); // Caller must pass an instance of A
Related
Is there another way than manually overloading the corresponding member function and calling the first overload with the member as the argument?
I am trying something along the lines of
class test
{
string t1="test";
testfun( string& val = this->t1 )
{ /* modify val somehow */ }
};
(Test it: http://goo.gl/36p4CF)
Currently I guess there is no technical reason why this should not work.
Is there a solution doing it this way except overloading and setting the parameter manually?
Why is this not working, is there a technical reason for it?
[dcl.fct.default]/8:
The keyword this shall not be used in a default argument of a member function.
This is a special case of a general problem: You cannot refer to other parameters in a default argument of a parameter. I.e.
void f(int a, int b = a) {}
Is ill-formed. And so would be
class A
{
int j;
};
void f(A* this, int i = this->j) {}
Which is basically what the compiler transforms a member function of the form void f(int i = j) {} into. This originates from the fact that the order of evaluation of function arguments and the postfix-expression (which constitutes the object argument) is unspecified. [dcl.fct.default]/9:
Default arguments are evaluated each time the function is called.
The order of evaluation of function arguments is unspecified. Consequently, parameters of a function shall not be used in a default
argument, even if they are not evaluated.
Is there a solution doing it this way except overloading and setting the parameter manually?
No, you'd need an overload if you want a default argument to depend on another parameter, including this. Although, in this case, it doesn't make sense since this is a constructor, and t1 doesn't exist before it's called.
Why is this not working, is there a technical reason for it?
Because the evaluation order of function arguments isn't specified. To allow parameter values in default arguments, you'd need much more complex rules to ensure each parameter was initialised before being used.
You haven't said what you want to achieve. I assume that you need that each of your instances react on a specific way, depending on a certain class variable.
However, if you don't need a per-instance behaviour, then you can use static variables. The following works:
#include <iostream>
using namespace std;
struct test {
static string t1;
void say(const string &val=t1){
cout << val << "!" << endl;
}
};
string test::t1;
int main() {
cout << "Hello World" << endl;
test::t1 = string("asd");
test a;
a.say();
a.say("bla");
test::t1 = string("blahblah");
a.say();
return 0;
}
... which means that all the objects of the class test will use the static string t1 as their default value.
You can "hack" a little bit, and use this as an ugly sentinel:
void say(const string &val=t1){
if (&val == &t1) {
// They are using the default value, so act as you want
} else {
// they are providing a value
}
}
I am faced with a very puzzling issue. I am trying to construct an object using a variable as a parameter.
Have a look at this code please:
#include <iostream>
class A {
public:
A() : val(0) {};
A(int v) : val(v) {};
private:
int val;
};
main() {
int number;
A a; /* GOOD, object of type A, created without arguments */
A b(2); /* GOOD, object of type A, created with one argument */
A c(); /* BAD, C++ thinks this is declaration of
a function returning class A as a type */
A(d); /* GOOD, object of type A again; no arguments */
A(number); /* BAD, tries to re-declare "number" as object of type A */
}
I think I do understand why objects "a", "b" and "d" can be created, whereas the rest can not.
But I would really need the syntax of the last declaration, i.e.
A(number);
to create a temporary object, to pass as an argument to another object.
Any idea how to work around it?
Kind regards
Your intention is to create a temporary object, but this object would also be anonymous : you have no way to refer to it after the semicolon.
There is no point in creating an anonymous temporary object just to discard it. You have to instantiate your temporary directly at the call site of the ctor/method that will consume it.
Solution
To pass an anonymous temporary object to a function, you actually need to instantiate it inside the arguments' list :
functionExpectingA(A(number));
For the line of "c declaration", you are poking at the most vexing parse. If you actually need to pass a default constructed A object as an argument to another object constructor, you need to add another pair of braces to do the trick (so the compiler can distinguish it from a function declaration) :
class OtherClass
{
public:
OtherClass(A a)
{
//...
};
};
OtherClass obj((A()));
^ ^
EDIT #1 : jrok pointed out that the argument given to A constructor is not enough to resolve the ambiguity.
If you need to pass an anonymous temporary object that is built with an argument, there is no ambiguity (so no need for the extra parentheses), you still need the parentheses around the anonymous object construction.:
OtherClass obj((A(number)));
C heritage : a single argument is not enough
EDIT #2 : "why giving a single argument to A constructor does not resolve the ambiguity".
What happens with OtherClass obj(A(number)); ?
This is a declaration for a function named obj, taking an A object as its unique argument. This argument is named number.
i.e: It is exactly equivalent to OtherClass obj(A number);. Of course, you can omit the argument name at function declaration. So it is also sementically equivalent to OtherClass obj(A);
The syntax with parentheses around the object name is inherited from C :
int(a); // declares (and defines) a as an int.
int a; // strictly equivalent.
What with more arguments to the constructor then ?
If you added a ctor to OtherClass taking two (or more) arguments :
OtherClass(A a1, A a2)
{
//...
};
Then this syntax :
A arg1, arg2;
OtherClass obj(A(arg1, arg2));
Would this time actually declare obj as an instance of OtherClass.
This is because A(arg1, arg2) cannot be interpreted as name declaration for an A. So it is actually parsed as the construction of an anonymous A object, using the constructor with 2 parameters.
suppose we have a class
class Foo {
private:
int PARTS;
public:
Foo( Graph & );
int howBig();
}
int Foo::howBig() { return this->PARTS; }
int Foo::howBig() { return PARTS; }
Foo::Foo( Graph &G ) {
<Do something with G.*>
}
Which one of howBig()-variants is correct?
The &-sign ensures that only the reference for Graph object
is passed to initialization function?
In C I would simply do something like some_function( Graph *G ),
but in C++ we have both & and *-type variables, never understood
the difference...
Thank you.
When you've local variable inside a member function, then you must have to use this as:
Foo::MemberFunction(int a)
{
int b = a; //b is initialized with the parameter (which is a local variable)
int c = this->a; //c is initialized with member data a
this->a = a; //update the member data with the parameter
}
But when you don't have such cases, then this is implicit; you need to explicity write it, which means in your code, both versions of howBig is correct.
However, in member initialization list, the rules are different. For example:
struct A
{
int a;
A(int a) : a(a) {}
};
In this code, a(a) means, the member data a is being initialized with the parameter a. You don't have to write this->a(a). Just a(a) is enough. Understand this visually:
A(int a) : a ( a ) {}
// ^ ^
// | this is the parameter
// this is the member data
You can use this-> to resolve the dependent name issue without explicitly having to spell out the name of the base. If the name of the base is big this could arguably improve readability.
This issue only occurs when writing templates and using this-> is only appropriate if they're member functions, e.g.:
template <typename T>
struct bar {
void func();
};
template <typename T>
struct foo : public bar {
void derived()
{
func(); // error
this->func(); // fine
bar<T>::func(); // also fine, but potentially a lot more verbose
}
};
Which one of howBig()-variants is correct?
both in your case, the compiler will produce the same code
The &-sign ensures that only the reference for Graph object is passed to initialization function? In C I would simply do something like some_function( Graph *G ), but in C++ we have both & and *-type variables, never understood the difference...
there is no difference as per the use of the variable inside the method(except syntax) - in the case of reference(&) imagine as if you've been passed an invisible pointer that you can use without dereferencing
it(the &) might be "easier" for clients to use
Both forms of Foo::howBig() are correct. I tend to use the second in general, but there are situations that involve templates where the first is required.
The main difference between references and pointers is the lack of "null references". You can use reference arguments when you don't want to copy the whole object but you want to force the caller to pass one.
Both are correct. Usually shorter code is easier to read, so only use this-> if you need it to disambiguate (see the other answers) or if you would otherwise have trouble understanding where the symbol comes from.
References can't be rebound and can't be (easily) bound to NULL, so:
Prefer references to pointers where you can use them. Since they cannot be null and they cannot be deleted, you have fewer things to worry about when using code that uses references.
Use const references instead of values to pass objects that are large (more than say 16 or 20 bytes) or have complex copy constructors to save copy overhead while treating it as if it was pass by value.
Try to avoid return arguments altogether, whether by pointer or reference. Return complex object or std::pair or boost::tuple or std::tuple (C++11 or TR1 only) instead. It's more readable.
Given the following code:
#pragma once
class B
{
public:
B(void)
{
}
~B(void)
{
}
};
I know I can also write this:
#pragma once
class B
{
public:
B()
{
}
~B()
{
}
};
What is the purpose of having void in the first example? Is it some type of practice that states the constructor take zero parameters?
The two are same, at least in C++. In C, providing an empty pair of parentheses typically means an unspecified parameter list (as opposed to an empty parameter list). C++ does not have this problem.
How can a correct answer get downvoted so many times? Yet another SO bug?
A long time ago you did something like this in C (my pre-ISO C is rusty :) ):
void foo(a, b)
int a,
int b
{
}
while C++ was being created the name mangling required the types of the arguments, so for C++ it was changed to:
void foo(int a, int b)
{
}
and this change was brought forward to C.
At this point, I believe to avoid breaking existing C code this:
void foo()
and this:
void foo(void)
meant two very different things, () means do not check for the argument number or type, and (void) means takes no arguments. For C++ () meaning not to check anything was not going to work so () and (void) mean the same thing in C++.
So, for C++ () and (void) were always the same thing.
At least that is how I remember it... :-)
afaik if you pass void into the constructor or any function as the argument it means that the function dosnt take any argument so example a and b are equal. but i am not sure if any of them change the function signature in any way or make it run faster etc.
I just wanted to add that when you use void after the parameters like function():void it is used to indicate that the function does not return a value.
class C {
T a;
public:
C(T a): a(a) {;}
};
Is it legal?
Yes it is legal and works on all platforms.
It will correctly initialize your member variable a, to the passed in value a.
It is considered by some more clean to name them differently though, but not all. I personally actually use it a lot :)
Initialization lists with the same variable name works because the syntax of an initialization item in an initialization list is as follows:
<member>(<value>)
You can verify what I wrote above by creating a simple program that does this: (It will not compile)
class A
{
A(int a)
: a(5)//<--- try to initialize a non member variable to 5
{
}
};
You will get a compiling error something like: A does not have a field named 'a'.
On a side note:
One reason why you may not want to use the same member name as parameter name is that you would be more prone to the following:
class A
{
A(int myVarriable)
: myVariable(myVariable)//<--- Bug, there was a typo in the parameter name, myVariable will never be initialized properly
{
}
int myVariable;
};
On a side note(2):
One reason why you may want to use the same member name as parameter name is that you would be less prone to the following:
class A
{
A(int myVariable_)
{
//<-- do something with _myVariable, oops _myVariable wasn't initialized yet
...
_myVariable = myVariable_;
}
int _myVariable;
};
This could also happen with large initialization lists and you use _myVariable before initializing it in the initialization list.
One of the things that may lead to confusion regarding this topic is how variables are prioritized by the compiler. For example, if one of the constructor arguments has the same name as a class member you could write the following in the initialization list:
MyClass(int a) : a(a)
{
}
But does the above code have the same effect as this?
MyClass(int a)
{
a=a;
}
The answer is no. Whenever you type "a" inside the body of the constructor the compiler will first look for a local variable or constructor argument called "a", and only if it doesn't find one will it start looking for a class member called "a" (and if none is available it will then look for a global variable called "a", by the way). The result is that the above statment "a=a" will assign the value stored in argument "a" to argument "a" rendering it a useless statement.
In order to assign the value of the argument to the class member "a" you need to inform the compiler that you are referencing a value inside this class instance:
MyClass(int a)
{
this->a=a;
}
Fine, but what if you did something like this (notice that there isn't an argument called "a"):
MyClass() : a(a)
{
}
Well, in that case the compiler would first look for an argument called "a" and when it discovered that there wasn't any it would assign the value of class member "a" to class member "a", which effectively would do nothing.
Lastly you should know that you can only assign values to class members in the initialization list so the following will produce an error:
MyClass(int x) : x(100) // error: the class doesn't have a member called "x"
{
}
if the formal parameter and the member is named same then beware of using this pointer inside constructor to use the member variable
class C {
T a;
public:
C(T a): a(a) {
this->a.sort ;//correct
a.sort();//will not affect the actual member variable
}
};
Legal: yes, as explained by Brian, compiler knows the name to expect in the initializer list must be a member (or a base class), not anything else.
Good style: most likely not - for a lot of programmers (including you, it seems) the result is not obvious. Using a different name for the parameter will keep the code legal and make it a good style at the same time.
I would prefer writing some of:
class C {
T a_;
public:
C(T a): a_(a) {}
};
class C {
T a;
public:
C(T value): a(value) {}
};
The problem with this practice, legal though it may be, is that compilers will consider the variables shadowed when -Wshadow is used, and it will obfuscate those warnings in other code.
Moreover, in a non-trivial constructor, you make make a mistake, forgetting to put this-> in front of the member name.
Java doesn't even allow this. It's bad practice, and should be avoided.
Hey guys this is a great question. If you want to identical names for fields and constructor parameters / methods parameter you have to use scope resolution ( :: ) operator or you can use this ( this-> ) to map the parameter value with member like this please check the code snippet carefully you can understand easyly.
class Student{
private :
string name;
int rollNumber;
public:
Student()
{
// default constructor
}
// parameterized constructor
Student(string name, int rollNumber)
{
this->name = name;
Student::rollNumber = rollNumber;
}
void display()
{
cout<<"Name: "<<name <<endl;
cout<<"Roll Number: "<<rollNumber<<endl;
}
void setName(string name)
{
this->name = name;
}
void setrollNumber(int rollNumber)
{
Student::rollNumber = rollNumber;
}
};