fail to call another constructor from constuctor

C

cmk128

hi

1 #include <stdio.h>
2
3 class A{
4 private:
5 int x;
6 public:
7 A(int x){
8 this->x;
9 }
10
11 A(int x, char *y){
12 A(x); <---------------- may
i know how to fix this line?
13 }
14 };
15
16 int main(){
17 return 1;
18 }

d.cpp: In constructor `A::A(int, char*)':
d.cpp:12: error: declaration of `x' shadows a parameter
d.cpp:12: error: no matching function for call to `A::A()'
d.cpp:3: error: candidates are: A::A(const A&)
d.cpp:11: error: A::A(int, char*)
d.cpp:7: error: A::A(int)

thanks
from Peter ([email protected])
 
S

Steve Pope

laikon said:
just explicitly call constructor A() as follows:
A::A(x); //line 12

That never works when I try it. For example, the following
compiles with gcc but fails to print out a value of "3" --
it prints a garbage value.

I'm sure there's a simple explanation, but pending figuring out
what it is, I avoid calling one constructor from another.

Steve

*******


#include <iostream>

struct A {
int state;
A(int x) {
state = x;
};
A() {
A::A(3);
};
};

int main()
{
using std::cout;
using std::endl;
A z;
cout << z.state << endl;
}
 
S

Sumit Rajan

hi

1 #include <stdio.h>
2
3 class A{
4 private:
5 int x;
6 public:
7 A(int x){
8 this->x;
9 }
10
11 A(int x, char *y){
12 A(x); <---------------- may
i know how to fix this line?
13 }
14 };
15
16 int main(){
17 return 1;
18 }

d.cpp: In constructor `A::A(int, char*)':
d.cpp:12: error: declaration of `x' shadows a parameter
d.cpp:12: error: no matching function for call to `A::A()'
d.cpp:3: error: candidates are: A::A(const A&)
d.cpp:11: error: A::A(int, char*)
d.cpp:7: error: A::A(int)

thanks
from Peter ([email protected])


See:
http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.3

Regards,
Sumit.
 
Z

Zara

hi

1 #include <stdio.h>
2
3 class A{
4 private:
5 int x;
6 public:
7 A(int x){
8 this->x;
9 }
10
11 A(int x, char *y){
12 A(x); <---------------- may
i know how to fix this line?
13 }
14 };
15
16 int main(){
17 return 1;
18 }

The answer is: This is not Java, and such a way to cascade
constructors is not allowed (but it may change in the future...)


Regards,

Zara
 
T

Thomas Tutone

1 #include <stdio.h>
2
3 class A{
4 private:
5 int x;
6 public:
7 A(int x){
8 this->x;
9 }
10
11 A(int x, char *y){
12 A(x); <---------------- may
i know how to fix this line?
13 }
14 };
15
16 int main(){
17 return 1;
18 }

d.cpp: In constructor `A::A(int, char*)':
d.cpp:12: error: declaration of `x' shadows a parameter
d.cpp:12: error: no matching function for call to `A::A()'
d.cpp:3: error: candidates are: A::A(const A&)
d.cpp:11: error: A::A(int, char*)
d.cpp:7: error: A::A(int)

This is an FAQ:

http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.3

Best regards,

Tom
 
K

Kai-Uwe Bux

Steve said:
That never works when I try it. For example, the following
compiles with gcc but fails to print out a value of "3" --
it prints a garbage value.

I'm sure there's a simple explanation, but pending figuring out
what it is, I avoid calling one constructor from another.

Steve

*******


#include <iostream>

struct A {
int state;
A(int x) {
state = x;
};
A() {
A::A(3);

This creates a temporary of type A and initializes it. Then the temporary is
destructed. Pending side effects, this is a null op.
};
};

int main()
{
using std::cout;
using std::endl;
A z;
cout << z.state << endl;
}

You would need to call the constructor for the given object:


#include <iostream>

struct A {
int state;
A(int x)
: state(x)
{}

A() {
new (this) A(3);
}
};

int main()
{
using std::cout;
using std::endl;
A z;
cout << z.state << endl;
}


However, I it might be undefined behavior (I am not sure: 3.8/5 comes to
mind but I am a little too lazy right now to embark on a careful exegesis
right now).


Best

Kai-Uwe Bux
 
S

Salt_Peter

Steve said:
That never works when I try it. For example, the following
compiles with gcc but fails to print out a value of "3" --
it prints a garbage value.

Constructors are not called, they are invoked. If you want the default
state to be initialized to 3, then initialize state via the
initialization list from within a default ctor. Calling A::A(3) simply
creates a temporary which dies immediately.
I'm sure there's a simple explanation, but pending figuring out
what it is, I avoid calling one constructor from another.

Thats what the init list does, instead of creating and then
initializing the state integer:
A::A()
{
state = 3;
}

You call state's ctor directly - instantaneous allocation +
initialization
A::A() : state(3)
{
}
Steve

*******


#include <iostream>

struct A {
int state;
A(int x) {
state = x;
};
A() {
A::A(3);
};
};

int main()
{
using std::cout;
using std::endl;
A z;
cout << z.state << endl;
}

try:

#include <iostream>

struct A
{
A() : state(3) { }
A(int n) : state(n) { }
int getState() const { return state; }
private:
int state;
};

int main()
{
A a; // invoke the default ctor
std::cout << "a = " << a.getState() << std::endl;
A b(101); // invoke the parametized ctor
std::cout << "b = " << b.getState() << std::endl;
}

/*
a = 3
b = 101
*/
 
S

Steve Pope

Kai-Uwe Bux said:
Steve Pope wrote:

This creates a temporary of type A and initializes it. Then the temporary is
destructed. Pending side effects, this is a null op.

Right; if I replace A::A(3) with float(3) I get a "warning statement
has no effect", but A::A(3) issues no warning ... as you point out
it may have a side effect.
You would need to call the constructor for the given object:

#include <iostream>

struct A {
int state;
A(int x)
: state(x)
{}

A() {
new (this) A(3);
}
};

int main()
{
using std::cout;
using std::endl;
A z;
cout << z.state << endl;
}
However, I it might be undefined behavior (I am not sure: 3.8/5 comes to
mind but I am a little too lazy right now to embark on a careful exegesis
right now).

Thanks Kai-Uwe. If in this situations I will separate out
the code common to the two constructors into a member function:


#include <iostream>

struct A {
int state;
void setState(int x) { state = x; };
A(int x) {
setState(x);
};
A() {
setState(3);
};
};

int main()
{
using std::cout;
using std::endl;
A z;
cout << z.state << endl;
}
 
E

Earl Purple

1 #include <stdio.h>
2
3 class A{
4 private:
5 int x;
6 public:
7 A(int x){
8 this->x;
9 }
10
11 A(int x, char *y){
12 A(x); <---------------- may
i know how to fix this line?
13 }
14 };
15
16 int main(){
17 return 1;
18 }
It's meaningless code. this->x doesn't do anything. You should say
this->x( x ) in the initialiser but better not to call the parameter x
at all.

You cannot call one constructor from another but there are two
workarounds:

class A
{
private:
void init ( int x );

public:
/*explicit*/ A( int x )
{
init( x );
}

A( int x, char * y )
{
init ( x );
// do other stuff
}
};

Then you can use private inheritance. That does allow you to call a
constructor from a constructor - the constructor of your base class.
You can have two of your constructors call the base class constructor.
Because the inheritance is private, it is implementation detail of your
class.

class XInit
{
friend class A;

XInit( int x );
};

class A : XInit
{

public:
/*explicit*/ A( int x ) : XInit( x )
{
// do stuff if you want
}

A( int x, char * y )
: XInit( x )
{
// do other stuff
}
};

Here XInit is really only created for the benefit of A and it doesn't
therefore really matter that the two are so tightly coupled. Note that
by making A a friend of XInit and everything in it private, nothing
else at all can use XInit, not even by deriving from it. You might
shove it in a namespace to avoid namespace pollution.
 
R

Ron Natalie

laikon said:
just explicitly call constructor A() as follows:
A::A(x); //line 12

That's not legal either.
You can't call constructors.

If you want to have code common to two constructors you need to
put it in another member function that they both can call.
 
R

Ron Natalie

Steve said:
I'm sure there's a simple explanation, but pending figuring out
what it is, I avoid calling one constructor from another.
The simple explanation is that you can not call constructors.
The constructors are invoked for you by the implementation as
part of object creation. In specifiying arguments you can
affect which overload of the constructor is used, you can not
change the ordering or otherwise alter the process.
 
L

LR

Kai-Uwe Bux said:
Steve Pope wrote:





This creates a temporary of type A and initializes it. Then the temporary is
destructed. Pending side effects, this is a null op.



You would need to call the constructor for the given object:


#include <iostream>

struct A {
int state;
A(int x)
: state(x)
{}

A() {
new (this) A(3);
}
};
However, I it might be undefined behavior (I am not sure: 3.8/5 comes to
mind but I am a little too lazy right now to embark on a careful exegesis
right now).

There may be other worries for other classes.

For example, if your class inherits from a class that has a pointer
where the default ctor allocates memory then I think new (this) might
result in a memory leak..

Can we make a swap member function of A?

void A::swap(A &a) {
std::swap(a.x,x);
}

and rewrite the ctor that we want to call another ctor?
A::A()
:
x()
{
A temp(3);
swap(temp);
}


LR
 
F

Frederick Gotham

Kai-Uwe Bux posted:
A() {
new (this) A(3);
}


I advocate the use of:

::new(p)

instead of:

new(p)

when using placement new. The code should be all right, just so long as no
member objects or base-class objects have constructors which acquire
resources or something of the like. The following is doomed to break
because it will call "str"'s constructor twice... possible resulting in
leaked resource, or perhaps even worse.

#include <string>
#include <new>

class MyClass {
private:

std::string str;

public:

MyClass(int) {}

MyClass(double x) { ::new(this) MyClass(x/3 +5); }
};
 
K

Kai-Uwe Bux

Frederick said:
Kai-Uwe Bux posted:



I advocate the use of:

::new(p)

instead of:

new(p)

when using placement new. The code should be all right, just so long as no
member objects or base-class objects have constructors which acquire
resources or something of the like. The following is doomed to break
because it will call "str"'s constructor twice... possible resulting in
leaked resource, or perhaps even worse.

#include <string>
#include <new>

class MyClass {
private:

std::string str;

public:

MyClass(int) {}

MyClass(double x) { ::new(this) MyClass(x/3 +5); }

};

Correct: that would be bad. However, once you are in a state of sin, why not
try:

#include <string>
#include <new>

class MyClass {
private:

typedef std::string string;
string str;

public:

MyClass(int) {}

MyClass(double x) {
(&str)->~string();
::new(this) MyClass(x/3 +5);
}
};

Note: I am *not* advocating this.


Best

Kai-Uwe Bux
 
B

BobR

Steve Pope wrote in message ...
That never works when I try it. For example, the following
compiles with gcc but fails to print out a value of "3" --
it prints a garbage value.

I'm sure there's a simple explanation, but pending figuring out
what it is, I avoid calling one constructor from another.

Steve
*******

#include <iostream>

struct A {
int state;
A(int x) {
state = x;
};
A() {
A::A(3);
};
};

int main(){
using std::cout;
using std::endl;
A z;
cout << z.state << endl;
}

Hmmm, maybe you just want a default value?

struct A {
int state;
A( int x = 3 ) : state( x ) {};
};

int main(){
using std::cout;
using std::endl;
A z;
cout << z.state << endl;
A y(23);
cout << y.state << endl;
}

// -- output --
3
23
 
F

Frederick Gotham

Kai-Uwe Bux posted:
MyClass(double x) {
(&str)->~string();
::new(this) MyClass(x/3 +5);
}


Now all we need is a compiler that optimises-away a construction followed
immediately by a destruction ; ).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,981
Messages
2,570,187
Members
46,731
Latest member
MarcyGipso

Latest Threads

Top