|
||||||||||||||||||
Add Forum to Favorites | Send Topic To a Friend | View Forum FAQ | Track this topic |
Last Thread Next Thread ![]() |
| Pasing Arguements Into A Constructor |
|
![]() Cibressus Member since: 12/11/2003 From: Ajax, Canada |
||||
|
|
||||
| I've seen it done before, were you pass a arguement into a constructor for a class, i just can't remeber do you overload the constructor or just replace it? and also how do you use it? |
||||
|
||||
![]() Mulligan Member since: 2/11/2002 From: Virginia |
||||
|
|
||||
there ya go, overloading! |
||||
|
||||
![]() iNsAn1tY Member since: 12/18/2001 From: Guildford |
||||
|
|
||||
|
||||
|
||||
![]() Cibressus Member since: 12/11/2003 From: Ajax, Canada |
||||
|
|
||||
| oh crap, i acidently rated you down istead of up.. sorry |
||||
|
||||
![]() Fruny Moderator Member since: 11/16/2001 From: Paris, France |
||||
|
|
||||
| You ought to provide one constructor for each 'way' that makes sense for your object to be constructed. For example, if you don't provide a default constructor (the parameterless version) but only constructors with parameters, code like MyClass obj; will not compile. So, whether to replace the default constructor or to overload it is a design decision you must make. Both are legal, both have consequences. There are a number of different 'prototypes' for constructors.
class Foo
{
public:
Foo(); // Default constructor
Foo(int); // Single-parameter (conversion) constructor
Foo(const Foo&); // Copy constructor
Foo(int, int); // 'other' constructor
};The default constructor is called when, as I mentioned before, you don't specify any arguments with your variable definition. The other constructors can be used in several ways. For example, the two-int-parameter constructor: Foo x(1,1); Foo y = Foo(1,1); The other two constructors - the conversion constructor and the copy-constructor, have additional special meaning attached to them. First, the copy constructor, which takes a const reference to an object of the same class, is called whenever you pass a parameter by value, or return a result in the same way - though compilers may optimize that away in some cases. Foo myfunc(Foo x) // Copy constructor is called
{
return x; // Copy constructor is called
}The copy constructor is also called when you initialize one Foo object with another: Foo x; // Default constructor Foo y(x); // Copy constructor Foo z = y; // again, copy constructor x = z; // NOT AN INITIALIZATION, not copy constructor Note the difference in the last line. The x object already existed before, so this is not an initialization, not a copy constructor call. Instead, it is a call to the class' assignment operator, a Foo& operator=(const Foo&) member function. Its semantics are very close to that of the copy constructor, except that, since the object you are copying to already exists, you do not 'construct' it but, instead, may have to clean up the old object (e.g. delete pointers it held) to make room for the new data. When you have a copy constructor, you most often also need an assorted assignment operator, and conversely. Secondly, any constructor with one single parameter is a conversion constructor. It is called whenever the compiler expects a variable of the classe's type, but receives a parameter of the other type instead. For example, if you called myfunc(1), the '1' would be implicitely converted into a Foo before being passed to myfunc. It also allows you to initialize an object with the Foo x = 1 syntax. It can lead to troubles when several conversion paths are available, at which point your program will refuse to compile. You can disable the implicit conversion feature that is associated with single-parameter constructors by marking them explicit : explicit Foo(int); An additional feature constructors have is an initialization list. While novice C++ programmers often write their constructors like this, Foo()
{
x = 1;
y = 2;
}it is in fact wasteful. The code block associated with a constructor isn't run until the object itself, its base classes and member variables, have been fully constructed. Which means that, when the code block is executed, both 'x' and 'y' have already received default values edit Now for basic types it may not seem significant, but if you have member object which have constructors of their own, those constructors may indeed be costly, and there is little point in default-constructing an object if you're going to overwrite it immediately. So instead, you put the parameters you want your members to be constructed with in the initializer lists. This will in turn directly call the proper version of the constructor (the one matching the types of the parameters) Foo() : x(1), y(2) {}. Note that, as a consequence, your constructor code block may very well be empty. The initializer list takes an even greater importance for those members which cannot be default-constructed (e.g. you gave a parameterized constructor, but didn't provide a default constructor), and/or which cannot later be assigned to (e.g. they are references or constants). In such a case, the only place you can initialize them is in the initialization list, not in the code block: class Bar
{
const int constant;
Foo& reference;
NoDefaultConstructor member;
public:
Bar(Foo& f)
: constant(42), reference(f), member(5,5,42)
{}
virtual ~Bar() {} // needed for following example
};Finally, when deriving one class from another, the initializer list is also where you pass parameters to the base class' constructor, something which is once again mandatory if the base object cannot be default-constructed:
class Baz : public Bar
{
public:
Baz(Foo& f)
: Bar(f) // Bar requires an Foo parameter to be constructed
{}
};I think that pretty much sum up the basics about constructors. There are other sensitive issues, such as the construction order (base classes first, then members in order of their declaration in the class body), but that can wait. [Edited by - Fruny on June 21, 2004 9:27:07 PM] |
||||
|
||||
![]() ChaosEngine Member since: 6/9/2000 From: Christchurch, New Zealand |
||||
|
|
||||
| Fruny, that may be the most helpful, complete and well thought response I've seen on these forums. I have only one nit to pick. Quote: I don't think C++ assigns zero as a default value for ints. if you think programming is like sex, you probably haven't done much of either. -------------- - capn_midnight |
||||
|
||||
![]() Fruny Moderator Member since: 11/16/2001 From: Paris, France |
||||
|
|
||||
Quote: You're right, it depends on whether the class is a POD-type or not. Thanks for catching that. |
||||
|
||||
All times are ET (US)![]() |
Last Thread Next Thread ![]() |
|