Instantiation will use the constructor. Declaration and instantiation are technically different things. To 'declare' a variable, you need only state its name and what type it is. Like so...
char c;
int i;
User u;
Initializing a variable with a value gives it 'definition'. You can even define in a single line.
c = 'a';
i = 65;
short s = -1; // single line definition
You can even define
Whilst simple variable types like integers, characters, floats, etc. do not need to be 'instantiated' to be given definition, 'objects' do. Instantiation is simply the creation of an 'instance' of an object. Because we're discussing 'objects', consider it to mirror something physical; you may have the plans for a device that you call a "wheel" but it may not yet exist in the world yet. Your plans define a shape(round), size(diameter), thickness(width), perhaps even material(orphan tears). However, until you physically manifest it, it does not yet actually exist. This process of physical manifestation is considered the 'construction' process. Completing the construction process creates an 'instance' of that object. Multiple instances can be created and each can have their own, unique properties like shape(oval), size(x^2/a^2+y^2/b^2 or some such BS), thickness(different width?) and material(the broken dreams of parents everywhere).
Instantiating an object involves calling the 'constructor'. The constructor is simply a special function, with the same name as the object itself, that is called during the creation process of the object. Just as a simple data type can be declared and defined later, so can an object. Of course, you can also do it at the point of declaration, too.
u = User();
User u2 = User();
Now that you [hopefully] understand what instantiation is, and the basics of how the constructor is used, let's go over your confusion regarding the constructor syntax.
Note first, please, that all private class members MUST have some form of value by the end of the construction process. This means that the constructor, when it is called, should give every member variable a value unless it already has one. A couple examples...
class User {
private:
unsigned int _age;
std::string _name;
public:
User(unsigned int& age, std::string& name) {
_age = age;
_name = name;
}
};
Now the above example is perfectly valid. There are 2 member variables, _age & _name, and they are both given values within the constructor. Thus, all member variables have valid values by the end of the construction process since instantiation calls the constructor. However, have a look at this example, which is invalid:
class User {
private:
unsigned int _age;
std::string _name;
public:
User(std::string& name) {
_name = name;
}
};
Note that in the above example '_age' is left without a value. This is invalid and most compilers will generate a warning if not an error. All member variables should be given a value -- that is, be fully defined -- during the construction process(aka instantiation). However, perhaps we could assign a default value for age so that we needn't provide one.
class User {
private:
unsigned int _age;
std::string _name;
public:
User(std::string& name, int age = 18) {
_name = name;
_age = age;
}
};
// usage as:
User u = User("foo", 25);
User u2 = User("bar"); // 'bar' is 18
Please note that when using default arguments, mandatory arguments should always be listed before optional ones.
Notice how this constructor still ensures that all member variables have assigned values. Whether we specify the 'age' argument or not, the member variable '_age' always has some form of value; be it what we specify or the default, "18". Of course, there is technically another way to ensure that the member variables have values. That method is called an 'initialization list'.
The initialization list directly follows the declaration of the constructor and precedes the body of the constructor. It looks like this...
class User {
private:
unsigned int _age;
std::string _name;
public:
User(std::string& name) : _age(18) {
_name = name;
}
};
The part that directly follows the constructor declaration, what would essentially be considered the basic prototype, is the initialization list. This list has a basic format:
variable_name(variable_value), ..., ...
This works very well for lots of things that need to be given a value but for which you do not wish to actually pass one. It can also be used to initialize pointers to NULL, which is probably one of the better uses, IMHO. Some variable types are easier to use in an initialization list than others. Some, in fact, cannot be used in an initialization list. This is something that you'll just need to figure out on your own as you gain more experience with C++.
Some final code to help bring it all together for you.
#include <iostream>
#include <string>
class User {
private:
unsigned int _age;
std::string _name;
public:
User(std::string&);
unsigned int Age(void) const;
unsigned int Age(unsigned int&);
std::string Name(void) const;
std::string Name(std::string&);
};
User::User(std::string& name) : _age(18) {
_name = name;
}
unsigned int User::Age(void) const {
return _age;
}
unsigned int User::Age(unsigned int& age) {
return (_age = age);
}
std::string User::Name(void) const {
return _name;
}
std::string User::Name(std::string& name) {
return (_name = name);
}
int main(void) {
std::string s[] = {"foo", "bar"};
unsigned int i = 25;
User u1 = User(s[0]);
User u2 = User(s[1]);
u1.Age(i);
if (u1.Age() > u2.Age()) {
std::cout << u1.Name() << " is older than " << u2.Name() << std::endl;
} else {
std::cout << u2.Name() << " is older than " << u1.Name() << std::endl;
}
return 0;
}
I hope that answers your questions on constructors. If you have any more, just speak up.
Good luck && have fun!