Sign in to follow this  
neverland

question about default constructor

Recommended Posts

neverland    145
consider the following code:
class A {
public:
	A(int i) : i(i) {
	}
		
private:
	int i;
};

int main()
{
	A a;
 
	return 0;
}

The code cannot compile because there is no default constructor of class A, but the book says that "the compiler will generate the default constructor if you don't define it" What's wrong ?

Share this post


Link to post
Share on other sites
ricekrispyw    388
What compiler are you using? Alternatively, it's pretty easy to do:


class A {
public:
A() {} //HERE'S THE DEFAULT CONSTRUCTOR
A(int i) : i(i) {
}

private:
int i;
};

int main()
{
A a;

return 0;
}

Share this post


Link to post
Share on other sites
Deyja    920
That behavior is correct. A Default constructor is generated if no constructor is supplied; but you supplied a constructor, supressing the generation of the default.

Share this post


Link to post
Share on other sites
Deyja    920
Again; the behavior is correct. It should not generate a default constructor.

However, it might also fail because of this: i(i). If that works, it's still extremely poor style.

Share this post


Link to post
Share on other sites
Verg    450
You supplied a constructor, so no default constructor is generated making this:


A a;


un-compile-able

(is that even a word?)

Seems like that would work in Java, however.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
If you define your constructor with a default argument in the parameter list, you can use the constuctor both ways.

Share this post


Link to post
Share on other sites
Zahlman    1682
Quote:
"the compiler will generate the default constructor if you don't define it"


This should read "the compiler will generate the default constructor if you don't define any constructor". Otherwise you will need to specify one. Generally this is not a real problem - as you're surely aware, initializer lists are your friends.

Quote:
Original post by Deyja
However, it might also fail because of this: i(i). If that works, it's still extremely poor style.


It does work (because the scoping rules are different inside and outside the brackets), and there's nothing wrong with it; I've seen it endorsed implicitly by many prominent users around here (including myself).

Share this post


Link to post
Share on other sites
MaulingMonkey    1728
Quote:
Original post by Zahlman
Quote:
Original post by Deyja
However, it might also fail because of this: i(i). If that works, it's still extremely poor style.


It does work (because the scoping rules are different inside and outside the brackets), and there's nothing wrong with it; I've seen it endorsed implicitly by many prominent users around here (including myself).


Agreed, and as a fact I use this method all the time.

The variables named in an initializer list as being initialized must come from the class itself, so the outer i is allways the class member, in this case the integer listed right after the private: label. You can't do:
int unrelated;

struct foo {
foo( int pie )
: unrelated( pie )
{
}
}


Similarly, the i supplied in the constructor's argument list will shadow the member variable as per normal scoping rules. This means that the inner i is allways the argument. It's good style, it's defined behavior by the standard, and it's sexy good. Or something.

Share this post


Link to post
Share on other sites
snk_kid    1312
Quote:
Original post by Anonymous Poster
If you define your constructor with a default argument in the parameter list, you can use the constuctor both ways.


he/she means


struct foo {

int i;

foo(int j = 0)
: i(j) {}

}


[Edited by - snk_kid on July 5, 2005 2:24:44 PM]

Share this post


Link to post
Share on other sites
Deyja    920
Quote:
I've seen it endorsed implicitly by many prominent users around here (including myself).


I haven't; nor would I call you prominent.

Quote:
It's good style, it's defined behavior by the standard, and it's sexy good. Or something.


It's disgusting mental ambiquity and belongs with the same camp that uses 1 as a variable name. Hint for those who don't see the problem: That's a 1, not an l.

Share this post


Link to post
Share on other sites
Jingo    582
The style usually recommended is i_(i).

(if you will forgive the one letter name [smile])

This is what is used in almost all C++ books that I have read, including C++ Coding Standards by Sutter and Alexandrescu.

Share this post


Link to post
Share on other sites
MaulingMonkey    1728
Quote:
Original post by Deyja
Quote:
I've seen it endorsed implicitly by many prominent users around here (including myself).


I haven't; nor would I call you prominent.


And I suppose you are? :-).

Quote:
Quote:
It's good style, it's defined behavior by the standard, and it's sexy good. Or something.


It's disgusting mental ambiquity and belongs with the same camp that uses 1 as a variable name. Hint for those who don't see the problem: That's a 1, not an l.


Dosn't seem ambiguous to me, mental or otherwise. You construct i from the value i, and then i == i, no mater what Is you're talking about. Instead of arguing this point with someone who obviously has no hands on experience with this practice (as evidenced by thinking that this could be causing compiler errors), I'd rather switch topics and point out:

There are instances where 1 has been used as a variable name. Usually slightly decorated, since in most languages you simply cannot use 1 in and of itself as a variable name - it won't let you. But people try to get as close as possible anyways: Boost.Lambda, part of the wonderful C++ library collection that aims and does help set existing practice to be used in molding the future of the C++ standard, uses "_1". Apache, the industry standard HTTP server, has Rule Rewriters using $1 (see example config).

And how much do they really differ? After all, 1 is just a "const int" assigned to some random binary, _1 just a "boost::lambda::placeholder1_type", and $1 is simply a "string".

Quote:
Original post by Jingo
The style usually recommended is i_(i).

I see m_i( i ), i(i_), and i(new_i) used just as often, I'd recon.

[Edited by - MaulingMonkey on July 5, 2005 3:53:35 PM]

Share this post


Link to post
Share on other sites
Jingo    582
Quote:

Quote:
Original post by Jingo
The style usually recommended is i_(i).

I see m_i( i ), i(i_), and i(new_i) used just as often, I'd recon.


Interesting, got any references for those styles? i(i_) in particular is very strange.

Share this post


Link to post
Share on other sites
MaulingMonkey    1728
Quote:
Original post by Jingo
Quote:

Quote:
Original post by Jingo
The style usually recommended is i_(i).

I see m_i( i ), i(i_), and i(new_i) used just as often, I'd recon.


Interesting, got any references for those styles? i(i_) in particular is very strange.


m_i( i ) is usually proported by the same people that recommend m_ prefixes for all member variables. It goes hand in hand with that naming style for obvious reasons... it's similar to your use of i_( i ), but of older vintage AFAIK.

References:
1) The standard library implementation on my computer uses _M_i, as an underscore followed by a capital letter is reserved for "the implementation".
2) Some googling seems to hint this practice stems from the MFC, which uses m_ for members and g_ for globals, etc.

My opinion is that it's an ugly hungarian notation hangover. In the few cases where it isn't obvious or implied that i is a member variable, "this->i" clearly states the fact.

i( i_ ) and i( new_i ) are similar in that they seek to decorate the less commonly used variable to distinguish between what are essentially the same values. There are many other variants, such as i( ii ), i( _i ), i( I ), etc...

No particular reference I have to bring to bear, but I think it's quite silly fluff to add when I type:

template < typename value_t >
struct vector3d {
typedef value_t value_type;
value_type x,y,z;
vector3d( value_type x , value_type y , value_type z )
: x( x ) , y( y ) , z( z )
{
}
};


Not only would xx, _xx, xx_, new_x, etc look rather silly as argument names in autogenerated documentation, intelesense, etc, but it'd serve no purpouse or value.

Share this post


Link to post
Share on other sites
xEricx    572
Also, be careful with constructors that take only 1 parameter, especially of a basic type.

I've seen in a "commercial" game engine a Vector3 that took 1 float and initialized the whole vector with this value.

What can happen if you, by mistake, type something like :

if(myVect == 0.f) // you meant myVect.z

The compiler has the right to create a Vector, initialize it with 0.f, and then compare myVect with this new Vector.

By declaring the 1 param constructor explicit, means that you have to explicitely write something like const Vector3 ZeroVect = Vector3(0.f);

Sorry for being a bit off topic :) and hope this helps...

Eric

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this