Scenario is I have a function which calls parameterized constructor when I want to initialize. So what I want to do is to call constructor of my choice when I want. But it works when I use A() to call default constructor but it does not work with a constructor with the parameter rather I am getting following error.
Error 1 error C2082: redefinition of formal parameter
'tmp' c:\users\adnan\documents\visual studio
2012\projects\project3\project3\source.cpp 12 1 Project3
class A
{
public:
int id;
void i(int tmp)
{
A(tmp);
}
A()
{
cout<<"default const"<<endl;
}
A(int id)
{
this->id = id;
}
};
int main()
{
A obj[2];
for(int i=0;i<2;i++)
{
obj[i].i(i*2);
}
cout<<"obj[0].id = "<<obj[0].id;
cout<<endl;
cout<<"obj[1].id = "<<obj[1].id;
cout<<endl;
system("pause");
return 0;
}
In your member function i you're trying to call the c'tor of A like this:
void i(int tmp)
{
A(tmp);
}
In fact A(tmp) declares a variable tmp of type A. Since tmp is already declared as int inside the same scope, the compiler complains.
If you want a variable of type A and initialize it via the A::A(int) c'tor then you need to give a name to that variable. E.g.:
A a(tmp);
The line
A(tmp);
doesn't call the constructor, it's declaring an instance of A called "tmp" - it's equivalent to
A tmp;
Since the formal parameter is called "tmp", that's a redefinition.
(Despite what you might expect, A tmp(); is not equivalent to A tmp;- look for "the most vexing parse" to learn more.)
The reason it "works" when you write
A();
is that it creates an anonymous instance (an entirely different one from this) which is immediately thrown away.
In other words, that code doesn't do what you thought it did.
There's no way (in C++03) to explicitly call a constructor except using "placement new", which should not be done unless you know what you're doing.
If you want to delay "initialization" of an object until after it's been constructed, use an initialization function:
class A
{
public:
int id;
void init(int tmp)
{
id = tmp;
}
A()
{
cout<<"default const"<<endl;
init(0); // Avoid accidental undefined behaviour.
}
A(int id)
{
init(id);
}
};
There is an ambiguity in the grammar involving expression-statements
and declarations:
I have cited the C++ Standard.
That is in this code snippet
void i(int tmp)
{
A(tmp);
}
A(tmp); is considered by the compiler as a declaration equivalent to
A tmp;
To distinguish the constructor call from the declaration you could write
void i(int tmp)
{
( A )( tmp );
}
In this case ( A )( tmp ) is a constructor call though there is no any sense in this statement.
Related
Is there a nice way to have a non static value as default argument in a function? I've seen some older responses to the same question which always end up in explicitly writing out the overload. Is this still necessary in C++17?
What I'd like to do is do something akin to
class C {
const int N; //Initialized in constructor
void foo(int x = this->N){
//do something
}
}
instead of having to write
class C {
const int N; //Initialized in constructor
void foo(){
foo(N);
}
void foo(int x){
//do something
}
}
which makes the purpose of the overload less obvious.
One relatively elegant way (in my opinion) would be to use std::optional to accept the argument, and if no argument was provided, use the default from the object:
class C {
const int N_; // Initialized in constructor
public:
C(int x) :N_(x) {}
void foo(std::optional<int> x = std::nullopt) {
std::cout << x.value_or(N_) << std::endl;
}
};
int main() {
C c(7);
c.foo();
c.foo(0);
}
You can find the full explanation of what works/doesn't work in section 11.3.6 of the standard. Subsection 9 describes member access (excerpt):
A non-static member shall not appear in a default argument unless it
appears as the id-expressionof a class member access expression
(8.5.1.5) or unless it is used to form a pointer to member
(8.5.2.1).[Example:The declaration of X::mem1()in the following example
is ill-formed because no object is supplied for the non-static
memberX::a used as an initializer.
int b;
class X {
int a;
int mem1(int i = a);// error: non-static memberaused as default argument
int mem2(int i = b);// OK; useX::b
static int b;
};
Question:
Is there a difference between the following initializations?
(A) What exactly is the second one doing?
(B) Is one more efficient than the other?
int variable = 0;
int variable = int();
This question also applies to other data types such as std::string:
std::string variable = "";
std::string variable = std::string();
Background:
I basically got the idea here (the second code sample for the accepted answer) when I was trying to empty out a stringstream.
I also had to start using it when I began learning classes and realized that member variable initializations had to be done in the constructor, not just following its definition in the header. For example, initializing a vector:
// Header.h
class myClass
{
private:
std::vector<std::string> myVector;
};
// Source.cpp
myClass::myClass()
{
for (int i=0;i<5;i++)
{
myVector.push_back(std::string());
}
}
Any clarity on this will be greatly appreciated!
Edit
After reading again, I realized that you explicitely asked about the default constructor while I provided a lot of examples with a 1 parameter constructor.
For Visual Studio C++ compiler, the following code only executes the default constructor, but if the copy constructor is defined explicit, it still complains because the never called copy constructor can't be called this way.
#include <iostream>
class MyInt {
public:
MyInt() : _i(0) {
std::cout << "default" << std::endl;
}
MyInt(const MyInt& other) : _i(other._i) {
std::cout << "copy" << std::endl;
}
int _i;
};
int main() {
MyInt i = MyInt();
return i._i;
}
Original (typo fixed)
For int variables, there is no difference between the forms.
Custom classes with a 1 argument constructor also accept assignment initialization, unless the constructor is marked as explicit, then the constructor call Type varname(argument) is required and assignment produces a compiler error.
See below examples for the different variants
class MyInt1 {
public:
MyInt1(int i) : _i(i) { }
int _i;
};
class MyInt2 {
public:
explicit MyInt2(int i) : _i(i) { }
int _i;
};
class MyInt3 {
public:
explicit MyInt3(int i) : _i(i) { }
explicit MyInt3(const MyInt3& other) : _i(other._i) { }
int _i;
};
int main() {
MyInt1 i1_1(0); // int constructor called
MyInt1 i1_2 = 0; // int constructor called
MyInt2 i2_1(0); // int constructor called
MyInt2 i2_2 = 0; // int constructor explicit - ERROR!
MyInt2 i2_3 = MyInt2(0); // int constructor called
MyInt3 i3_1(0); // int constructor called
MyInt3 i3_2 = 0; // int constructor explicit - ERROR!
MyInt3 i3_3 = MyInt3(0); // int constructor called, copy constructor explicit - ERROR!
}
The main difference between something like:
int i = int(); and int i = 0;
is that using a default constructor such as int() or string(), etc., unless overloaded/overridden, will set the variable equal to NULL, while just about all other forms of instantiation and declarations of variables will require some form of value assignment and therefore will not be NULL but a specific value.
As far as my knowledge on efficiency, neither one is "better".
I am trying to understand how default constructor (provided by the compiler if you do not write one) versus your own default constructor works.
So for example I wrote this simple class:
class A
{
private:
int x;
public:
A() { std::cout << "Default constructor called for A\n"; }
A(int x)
{
std::cout << "Argument constructor called for A\n";
this->x = x;
}
};
int main (int argc, char const *argv[])
{
A m;
A p(0);
A n();
return 0;
}
The output is :
Default constructor called for A
Argument constructor called for A
So for the last one there is another constructor called and my question is which one and which type does n have in this case?
A n();
declares a function, named n, that takes no arguments and returns an A.
Since it is a declaration, no code is invoked/executed (especially no constructor).
After that declaration, you might write something like
A myA = n();
This would compile. But it would not link! Because there is no definition of the function n.
A n();
could be parsed as an object definition with an empty initializer or a function declaration.
The language standard specifies that the ambiguity is always resolved in favour of the function declaration (§8.5.8).
So n is a function without arguments returning an A.
For the last one NO constructor gets called.
For that matter no code even gets generated. All you're doing is telling (declaring) the compiler that there's a function n which returns A and takes no argument.
No there is not a different constructor.
A n();
is treated as a declaration of function taking no arguments and returning A object. You can see this with this code:
class A
{
public:
int x;
public:
A(){ std::cout << "Default constructor called for A\n";}
A(int x){
std::cout << "Argument constructor called for A\n";
this->x = x;
}
};
int main(int argc, char const *argv[])
{
A m;
A p(0);
A n();
n.x =3;
return 0;
}
The error is:
main.cpp:129: error: request for member ‘x’ in ‘n’, which is of non-class type ‘A()’
Assume I have a class with different constructors:
class A
{
public:
A(char* string)
{
//...
}
A(int value)
{
//..
}
void check() {}
};
Now I want to create an A object on stack, the constructor must be choosed depending on some condition, but there is a problem: the created object is destroyed then we quit {...} block.
bool isTrue() { /*...*/ }
int main()
{
if (isTrue())
{
A a("string");
}
else
{
A a(10);
}
a.check(); //error: 'a' is not defined in this scope
}
Suppose I haven't the copy-constructor or operator= in the A class. So how can solve this issue?
http://ideone.com/YsjmnK
A a = isTrue() ? A("string") : A(10);
And if a.check() is a const member function, an alternative may be better:
const A& a = isTrue() ? A("string") : A(10);
The object will be destroyed when the reference a go out of scope.
Note since C++17, according to the rule of copy elision the copy/move constructor is not required to be accessible for this case; copy elision is guaranteed here.
And since C++17 you can use std::optional, which doesn't cause any dynamic memory allocation. e.g.
std::optional<A> a;
if (isTrue())
{
a.emplace("string");
}
else
{
a.emplace(10);
}
(*a).check();
BTW: A(char* string) is supposed to be A(const char* string).
You can't satisfy all your stated requirements.
If you can get rid of the requirement for the object to be on stack, you could use a pointer.
A *a;
if (isTrue())
a = new A("string");
else
a = new A(10);
a->check();
delete a;
If the type has a default constructor, you can default-construct an object, immediately destruct it, and then construct it again with the appropriate constructor via placement-new:
A a;
a.~A();
if (isTrue())
{
new(&a) A("string");
}
else
{
new(&a) A(10);
}
The C++ standard has several examples similar to the above, just search for .~ and ->~.
Note that this is ultra evil. If your code ever gets reviewed, you are probably going to get fired.
I had the exact same question a while ago and this is what google helped me find:
unique_ptr<A> foo;
if(isTrue())
foo = std::unique_ptr<A>(new A("10"));
else
foo = std::unique_ptr<A>(new A(10));
Its probably too late for the OP but someone else might hopefully find this useful.
You can use the template class:
template<class type> class A
{
protected:
type T;
public:
void A(type t_curr) {T = t_curr;};//e.g.---
void check() {}
};
Hi I want to call an objects function in other function but i can't. Why ?
class class1
{
private:
int var;
public:
class1(int x);
void functionO();
};
class1::class1(int x)
{
var = x;
}
void class1::functionO()
{
cout<<"text";
}
void Callfunction()
{
object1->function0();
}
int main()
{
class1 *object1;
object1 = new class1(x);
Callfunction();
}
Compilator says that
'object1' : undeclared identifier
It seems logical but how can i call that objects function within a function ?
In this code:
void Callfunction()
{
object1->function0();
}
object1 is out-of-scope. That is, the compiler doesn't know about anything named object1 from within the scope of CallFunction().
Note that even if you had defined CallFunction after main(), this would still be true. All variables are local to the scope in which they are declared.
One option is to make object1 a global, and I'm sure that you will be advised to do this. But please don't. Global variables introduce state to your program, and along with it a host of other nasty problems that are hard to fix without tearing your program apart. Don't get in to the habit of using global variables to fix all manner of scoping issues. You will regret it.
Rather, why not just pass a class1 pointer to CallFunction()? Better yet, pass a reference.
void CallFunction(class1& obj1)
{
obj1.function0();
}
int main()
{
class1 *object1;
object1 = new class1(x);
Callfunction(*object1);
}
Your problem has nothing to do with the declaration order (before or after doesn't matter). Your object1 is a local variable of main. This means that it isn't visible outside of main, unless you explicitely pass it to the function needing it or store a pointer to it in a global variable (but please don't). To solve your problem you should therefore pass your object to Callfunction:
void Callfunction(class1& object1)
{
object1.function0();
}
int main()
{
class1 object1(x);//<-- This asumes that you have actually defined x
//somewhere, otherwise replace it with an actual value
Callfunction(object1);
}
Note that I took the liberty of clearing up the unneeded indirection (and the memory leak) by constructing the object on the stack instead of on the heap.
Pass your object as (reference) parameter to your function:
class class1
{
private:
int var;
public:
class1(int x);
void function0();
};
class1::class1(int x)
: var(x) // Note: Use member initializer lists
{}
void class1::function0()
{
std::cout << "text, var = " << var << std::endl;
}
void Callfunction(class1& object)
{
object.function0();
}
int main()
{
class1 object1(10);
class1 object2(42);
Callfunction(object1);
Callfunction(object2);
}
Expected output:
text, var = 10
text, var = 42
NOTE
The declaration order also matters, you might need to use a forward declaration when class1 is declared after the compiler sees Callfunction().