c++: passing class pointers into constructors

Started by
16 comments, last by way2lazy2care 13 years, 11 months ago
I'm just having trouble understanding whats going on here. When I try to compile this code I get the following error error C2040: 'cfg' : 'Wrapper' differs in levels of indirection from 'Cfg *' Could someone please explain what's happening?

class Cfg{
	int stuff;
};

class Wrapper{
	public:
		Wrapper(Cfg *cfg){}
		Wrapper(){
			Cfg *cfg = new Cfg();
			Wrapper(cfg);
		}
};


Advertisement
I'm guessing that you're trying to have one constructor call another one?

What's happening is that your code is (almost) creating a temporary Wrapper object inside the constructor.
class Wrapper{	public:		Wrapper(Cfg *cfg){ ... }		Wrapper(){			Cfg *cfg = new Cfg;			Wrapper newTemporaryWrapperObject(cfg);		}};
In C++, if you want two (or more) constructors to share some code, you've got to do it yourself. e.g.
class Wrapper{	public:		Wrapper(Cfg *cfg){ Init(cfg); }		Wrapper(){ Init(new Cfg); }	private:		void Init(Cfg *cfg){ ... }};
Or in this case you can merge them into one constructor using default arguments:
class Wrapper{	public:		Wrapper(Cfg *cfg=0)		{			if( !cfg )				cfg = new Cfg;			...		}};
Ah that fixes it, didn't realize you couldn't call other constructors like that in c++.

If you know though, why exactly does that "differs in levels of indirection" error come up?
hmm, my guess is its trying to create a temporary object using the default copy sontructor, which expects (reference to) another Wrapper object as a parameter and not a *Cfg.

Could be wrong though, maybe someone can knows why exactly it is that you can't call constructors from constructors in C++?
In GCC 4.4 I get the slightly more helpful error messages:
main.cpp: In constructor 'Wrapper::Wrapper()':main.cpp:10: error: conflicting declaration 'Wrapper cfg'main.cpp:9: error: 'cfg' has a previous declaration as 'Cfg* cfg'

So it seems like it ignores the parenthesis on "Wrapper(cfg);", and parses it as "Wrapper cfg;" instead. I'm actually a bit surprised at this, since this only seems to be the case if the constructor takes one argument that is a variable. But I guess no one is surprised that C++ isn't always consistent... I'm sure that there's some weird syntax one can use to call the constructor in the way you tried. Anyway, if you would call the constructor with for example "Wrapper(new Cfg());" instead, then it works, but doesn't really do what you want it to as it just creates a temporary instance of your class as Hodgman explained.
Quote:Original post by michaweyel
Could be wrong though, maybe someone can knows why exactly it is that you can't call constructors from constructors in C++?

You can't call constructors at all in C++. They are not functions.

You can construct an object in C++, which will invoke one of the class's constructors as a part of that process. You can not call the constructor directly.

Do not be confused the the syntax.

Stephen M. Webb
Professional Free Software Developer

Sharing constructor code is only added with C++0x and I am not sure if Visual Studio 10 supports this but g++ 4.5 does not.
Quote:Original post by Perost
In GCC 4.4 I get the slightly more helpful error messages:
*** Source Snippet Removed ***
So it seems like it ignores the parenthesis on "Wrapper(cfg);", and parses it as "Wrapper cfg;" instead. I'm actually a bit surprised at this, since this only seems to be the case if the constructor takes one argument that is a variable. But I guess no one is surprised that C++ isn't always consistent... I'm sure that there's some weird syntax one can use to call the constructor in the way you tried. Anyway, if you would call the constructor with for example "Wrapper(new Cfg());" instead, then it works, but doesn't really do what you want it to as it just creates a temporary instance of your class as Hodgman explained.


I think it's actually interpreting that as a c-style cast. It's kind of fortunate too because otherwise there would have been no error at all and jamesd128 would have been left with the more confusing problem of why his default constructor wasn't doing anything.
[size=2]
Quote:Original post by wild_pointer
Quote:Original post by Perost
In GCC 4.4 I get the slightly more helpful error messages:
*** Source Snippet Removed ***
So it seems like it ignores the parenthesis on "Wrapper(cfg);", and parses it as "Wrapper cfg;" instead. I'm actually a bit surprised at this, since this only seems to be the case if the constructor takes one argument that is a variable. But I guess no one is surprised that C++ isn't always consistent... I'm sure that there's some weird syntax one can use to call the constructor in the way you tried. Anyway, if you would call the constructor with for example "Wrapper(new Cfg());" instead, then it works, but doesn't really do what you want it to as it just creates a temporary instance of your class as Hodgman explained.


I think it's actually interpreting that as a c-style cast. It's kind of fortunate too because otherwise there would have been no error at all and jamesd128 would have been left with the more confusing problem of why his default constructor wasn't doing anything.

Actually, I think GCCs error message is quite clear that it interprets the line as a declaration.
Quote:Original post by Bregma
You can't call constructors at all in C++. They are not functions.

Actually they are functions and are one instance of the special member (drum roll) functions.
Quote:
You can construct an object in C++, which will invoke one of the class's constructors as a part of that process.
True
Quote: You can not call the constructor directly.

You can create an unnamed temporary "Foo();" for example.
Quote:Do not be confused the the syntax.

I won't :)

This topic is closed to new replies.

Advertisement