• Advertisement

Archived

This topic is now archived and is closed to further replies.

C++ Constructors

This topic is 5902 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hullo, I''ve had a bit of a problem with my constructors. The following illustrates the issue:
  
  class Foo
  {
    Foo (int x);
    Foo (int x, char *y);
    Foo (int x, double y);
    Foo (int x, Wombat *y);
  }

  Foo::Foo (int x, char *y)
    : Foo(x)
  {
    /* char* specifific stuff */
  }
  
My compiler (VC++) complains that ''Foo(int)'' isn''t a member of ''Foo'', which seems blatently wrong to me. Is my compiler right? If it is, how am I supposed to call one constructor from another. All your bases belong to us (I know. It''s irony.)

Share this post


Link to post
Share on other sites
Advertisement
After the ":" with a constructor implementation,
you initialize VARIABLES with var(value), it''s
not allowed to do function calls *there*.

Just call your overloaded func in the body,
like this:

Foo::Foo(....)
{
Foo(x);
}

Share this post


Link to post
Share on other sites
Shouldn''t that create an temporary instance of Foo() and then throw it away? Or does C++ know to treat calls to a constructor specially if I''m in a constructor at the time?

All your bases belong to us (I know. It''s irony.)

Share this post


Link to post
Share on other sites
Well,I''m not sure if c++ "knows" it,
but I think I did something like this, and
can''t remember that the program did something
I didn''t tell it to do, so I suppose it works.

Well, what are u gonna do?
Do you init some vars, or allocating some mem in
the constructor? Maybe you won''t need to call
that function, but,
however, I think it works.
Just try.

What I wanted to tell you, is only that the
syntax of the constructor implementation is
like I said above, and the "()" after the
name doesn''t have anything to do with a function,
although it may look like that.
It sets a classe''s variable to (value),
nothing more.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
maybe you should make an initialize function. You could then use it for other things.

Share this post


Link to post
Share on other sites
I don''t think that anyone else pointed this out but you don''t have a public, private, or protected section of your class, thats ok, but constructors have to be public and class members are private by default.

Jason Mickela
ICQ : 873518
E-Mail: jmickela@sbcglobal.net
------------------------------
"Evil attacks from all sides
but the greatest evil attacks
from within." Me
------------------------------

Share this post


Link to post
Share on other sites
quote:
Original post by griffenjam
you don''t have a public, private, or protected section of your class, thats ok, but constructors have to be public


Actually, I dont think that constructors have to be public. I''ve seen many instances where there are private constructors. Why, I''m not sure.

Share this post


Link to post
Share on other sites
Mayrel, what your doing is illegal. After the parameter list in a constructor the ":" is fallowed by variables of the class and there initial values. THE EXCEPTION IS BASE CLASSES. You are free to put a call to your base class constructor in the intialization list. However this doesn''t seem to be what you are doing.

The AP had probably the best idea.
To get your desired result, have a funtion called Init(x) that will do everything with the x variable. So the function Foo(int x) simply calls Init(x) and the others, like Foo(int x, char * y) call Init(x) then do their own thing.

Calling a plain constructor is illigal.
This code will not compile.
Foo::Foo(int x, char * y)
{
Foo(x);
}

RUn it in your compiler.

One last thing, there are several good reasons for having private constructors. One is when you want only a handful of classes to be able to make one of your objects, but want all to see it. By declaring the constructors private and haveing classes that can build one as Friends, you can keep others from doing something you don''t want. (if it''s jsut one class that can build, its better just to make it a private declaration in the class).

Anyway thats my little piece.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
quote:
Original post by DanG
Mayrel, what your doing is illegal.


Yeah. Im gonna report him to the FBI.

Share this post


Link to post
Share on other sites
quote:
Original post by masonium

Actually, I dont think that constructors have to be public. I''ve seen many instances where there are private constructors. Why, I''m not sure.




Because you want to control where objects are created. You have a factory method which creates the objects, or a method to obtain a pointer to a singleton (not that much different). Or possibly you don''t want objects to be created on the stack.

If your constructor is private then only your method can create an object of that type. All object creation is bottle-necked and you can choose to create a new object, return an existing poitner or whatever. if your constructor is public you lose this control because a client can create objects in any part of the code.

--

MP3 Dancer

Get A Stripper on your desktop

Share this post


Link to post
Share on other sites
quote:
Original post by Anonymous Poster
Original post by DanG
Mayrel, what you''re doing is illegal.

Yeah. Im gonna report him to the FBI.



You''ll never take me alive, copper!

All your bases belong to us (I know. It''s irony.)

Share this post


Link to post
Share on other sites
Aha. I got a copy of the standard. (Or, rather, the ''96 working paper, which is the nearest I can afford right now.)

quote:
Original post by DanG
Mayrel, what you''re doing is illegal. After the parameter list in a constructor the ":" is fallowed by variables of the class and there initial values. THE EXCEPTION IS BASE CLASSES. You are free to put a call to your base class constructor in the intialization list. However this doesn''t seem to be what you are doing.


Correct, that isn''t what I''m doing. I had expected C++ to be consistent.
quote:

Calling a plain constructor is illigal.
This code will not compile.
Foo::Foo(int x, char * y)
{
Foo(x);
}
Run it in your compiler.


1) Calling a plain constructor is perfectly valid outside of a constructor. [5.2.3]

2) Calling a plain constructor inside a constructor for the same class is probably invalid because that''d result in an infinite loop. [Although I couldn''t see any rule against it in the standard.]

3) As it happens, C++ considers a plain Foo(x) to be a definition of a Foo named x, rather than an instantiation of Foo using x as the parameter. In the middle of an expression, it does the right thing.

All your bases belong to us (I know. It''s irony.)

Share this post


Link to post
Share on other sites
quote:
Original post by Mayrel
1) Calling a plain constructor is perfectly valid outside of a constructor. [5.2.3]

Yeah, but you make it sound like a constructor is just another function, which it''s not. You''re not just calling a function, you''re creating a temporary object too. ''Calling'' a constructor is just creating an object with syntax that looks like a function call.

quote:
2) Calling a plain constructor inside a constructor for the same class is probably invalid because that''d result in an infinite loop. [Although I couldn''t see any rule against it in the standard.]

Yeah, but that''s not the problem in this case. You could be using something other than Foo and it would still not work. The problem here is that you''re simply getting the syntax wrong More specifically, trying to initialise something that isn''t initialisable.

quote:
3) As it happens, C++ considers a plain Foo(x) to be a definition of a Foo named x, rather than an instantiation of Foo using x as the parameter. In the middle of an expression, it does the right thing.

No - it considers ''Foo(x)'' to mean ''initialise the member object or base class called Foo with the value of x, as if the member or base class called Foo had its constructor called with x as the parameter. Since the object in question (the instance of Foo being constructed) has no member or base class called Foo (it IS Foo, it doesn''t contain Foo in any form), then it doesn''t work.

Basically, you can''t ''call'' one constructor from another, because they''re not simple functions like that.

To (pretty much) do what you intended, you need to separate out the construction from initialisation functions. Write one function to initialise the int stuff, one for the char* stuff, and call the relevant initialisers in the relevant constructors. That saves you the code duplication. It won''t save you duplicate constructions (although that won''t be an issue with basic data types as used here).

And to the poster who asked what the point of private constructors was: it stops people declaring instances of that object. You can then control access to creating that object via a static member function. One use of this would be to only create a given number of such objects, and enforce that restriction.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
yeah it might be confusing for someone who learned java first (well it wasn''t for me but I am soooo amazing at everything, and not the slightest bit arrogant either ). In java derived class constructors you are allowed to call base class constructors (but only in the very first line of the derived constructor), if you don''t call one it calls the 0 argument version for you, if there is one. If there isn''t then you have to explicitly call one of the other ones that you have written.

Share this post


Link to post
Share on other sites
quote:
Original post by Kylotan
Yeah, but you make it sound like a constructor is just another function, which it''s not. You''re not just calling a function, you''re creating a temporary object too. ''Calling'' a constructor is just creating an object with syntax that looks like a function call.



You appear to have have misunderstood what I''m refering to in my previous post: I''m talking about "Foo(x)" appearing in the method body of the constructor, rather than in the initialisation list, which I know is not valid (the fact that I noticed it wasn''t valid is what prompted me to post my question in the first place.)

In the method itself, you *can* call Foo(x).

quote:

> 2) Calling a plain constructor inside a constructor for the
> same class is probably invalid because that''d result in an
> infinite loop. [Although I couldn''t see any rule against it in
> the standard.]
Yeah, but that''s not the problem in this case. You could be using something other than Foo and it would still not work. The problem here is that you''re simply getting the syntax wrong More specifically, trying to initialise something that isn''t initialisable.



You probably can''t call Foo(x) in the method body because that''d cause an infinite loop.

quote:

> 3) As it happens, C++ considers a plain Foo(x) to be a
> definition of a Foo named x, rather than an instantiation of
> Foo using x as the parameter. In the middle of an expression,
> it does the right thing.
No - it considers ''Foo(x)'' to mean ''initialise the member object or base class called Foo with the value of x, as if the member or base class called Foo had its constructor called with x as the parameter. Since the object in question (the instance of Foo being constructed) has no member or base class called Foo (it IS Foo, it doesn''t contain Foo in any form), then it doesn''t work.



Again, in the method body, Foo(x) is a declaration of a Foo called x. In the initialisation list, it''s not valid.

quote:

And to the poster who asked what the point of private constructors was: it stops people declaring instances of that object. You can then control access to creating that object via a static member function. One use of this would be to only create a given number of such objects, and enforce that restriction.



A possible useful application of this would be a UniqueString class in which each instance of the class is guaranteed to be unique:

  
UniqueString x = UniqueString::makeString("foo");
UniqueString y = UniqueString::makeString("bar");
UniqueString z = UniqueString::makeString("foo");


After this, z and x point to the same object. Although this would make instantiations of the objects slower, it would allow one to compare two strings in constant time: by keeping all the strings in some form of sorted sequence (whether a list or binary tree) and giving each one a number according to its position within the sequence, you can overload the relational operators to compare the sequence number.

Abolish Software Patents! | freepatents | lpf

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Mayrel: no you''re wrong for the reasons people above have stated. Also stop saying "in the method". Constructors are not methods; they are not functions; they are just special. That Foo(x) example is even more wrong, just wrong, wrong, wrong. Go buy Bjarne Stroustrup''s The C++ Programming Language. It is the best book there is on C++.

Share this post


Link to post
Share on other sites

If I can just sneak a question into this thread.

Is it mandatory for all classes to have constructors/destructors ? I have one that doesn''t
have either of these. Bad practice ? I never included
constructors because of dynamic memory allocation for
objects in the class. The size of these objects can
change over the runtime of the program as they are deleted,
then re-allocated to a different size.

Does a constructor have to know all the sizes of the objects within ?

Guy

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
quote:
Original post by GuyJohnston

If I can just sneak a question into this thread.

Is it mandatory for all classes to have constructors/destructors ?



Not at all, although you should be aware that if you don''t provide any ctors/dtor, the compiler writes a default (no aruguments) ctor and a default (element by element) copy ctor.

quote:

I have one that doesn''t
have either of these. Bad practice ? I never included
constructors because of dynamic memory allocation for
objects in the class. The size of these objects can
change over the runtime of the program as they are deleted,
then re-allocated to a different size.

Does a constructor have to know all the sizes of the objects within ?

Guy



I have no idea what you are doing here, but it sounds like all kinds of trouble. First of all, an object always has a fixed size. You can have a pointer to an array of a variable number of elements, but if your object has any pointers as memebers then you almost always need a ctor a copy ctor an assignment opperator and a destructor.

Share this post


Link to post
Share on other sites

Thank You A.P.

I do have constructors/destructors for those particular pointers.

What I was doing, though do to a recent re-write probably not necessary anymore. Was loading a sprite surface, bitmask. I was allowing the sprite to be destroyed so I could re-load it as a different sprite when the orginal was no longer needed. I did have constructors/destructors for those particular pointers. I destroyed/re-constructed them when when I wanted to reload them.

Guy

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
you can''t make constructors or destructors for pointers, at least I don''t think you can.

Share this post


Link to post
Share on other sites
You can create constructors and destructors for smart-pointers (classes with operator * and operator -> overridden to act like pointers. I use auto_ptr occasionally and CComPtr (part of the ATL) quite a lot.

A key difference between C++ and Java lies herein:
Thou Shalt Not Perform Initialization in Thou''s Constructor
because Construction Shalt Not Fail.

An objective in C++ is to prevent every error you possibly can prevent at compile time - don''t rely on run-time exceptions to catch mistakes (which you must be doing if you''re performing initialization in a constructor). It''s not the C++ way.

Share this post


Link to post
Share on other sites
quote:
Original post by Anonymous Poster
Mayrel: no you're wrong for the reasons people above have stated.


I _was_ wrong for the reasons people, including myself, above have stated.
quote:

Also stop saying "in the method". Constructors are not methods; they are not functions; they are just special.


According to the Standard, a constructor is a special member function . That is the precise term used. If you must insult my intelligence, at least check up on your's first.
quote:

That Foo(x) example is even more wrong, just wrong, wrong, wrong.


Which one? Do you mean the Foo(x) example in the initialiser? If yes, I've already said that I know it's wrong. If you mean the Foo(x) example in the method body , then there's nothing prohibiting that in the Standard.
quote:

Go buy Bjarne Stroustrup's The C++ Programming Language. It is the best book there is on C++.

Shall I get you one whilst I'm there?

Abolish Software Patents! | freepatents | lpf

Edited by - Mayrel on November 24, 2001 4:54:39 AM

Share this post


Link to post
Share on other sites
class Foo
{
Foo (int x);
Foo (int x, char *y);
Foo (int x, double y);
Foo (int x, Wombat *y);
};

Foo::Foo (int x, char *y) : Foo(x)
{
/* char* specifific stuff */
}

or this:
Foo::Foo (int x, char *y)
{
:: Foo(x) ;
/* char* specifific stuff */
}


Try this one... now figure out what you did wrong...!

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
class Foo
{
Foo (int x);
Foo (int x, char *y);
Foo (int x, double y);
Foo (int x, Wombat *y);
};

Foo::Foo (int x, char *y) : Foo(x)
{
/* char* specifific stuff */
}

or this:
Foo::Foo (int x, char *y)
{
:: Foo(x) ;
/* char* specifific stuff */
}


Try this one... now figure out what you did wrong...!

Share this post


Link to post
Share on other sites

  • Advertisement