Originally Posted by
zackKidd
Very interesting, thanks for the help. Had no idea that you could have multiple constructors.
I just need to clear something up. This line:
Code:
protected:
Tile board[3][3];
I thought this was just initialising an array which could store Tile objects, and therefore has no need to access the constructor. Is this actually creating Tile objects and filling the array?
As iMalc mentioned, that declaration reserves a 3x3 array of objects, and each object is of type Tile. The thing is, each element of the array has to have an actual value; since each element is of type Tile, it has to call some Tile constructor or another.
It's different with primitive types like int. If you said
then you'd have an uninitialized array of integers (unless it was global or something, in which case everything would be initialized to zero). But you can't have an uninitialized object in C++. This is why the new operator automatically calls the constructor, and why C++ doesn't use malloc() like C does. It would be very difficult to write code if some object might not have been initialized.
To expand on this a little: let's say I had the following class declaration.
Code:
class Data {};
class Test {
private:
int x;
Data d;
public:
Test();
};
Suppose I try to write the Test() default constructor. I might write something like this:
Code:
Test::Test() {
x = 0;
d = Data();
}
The fact is, the "d = Data()" line would be redundant. The Data object has already been initialized by the time the code in the constructor executes! (The same is not true of the int, of course: had we not set this to some value, it would be uninitialized.)
Actually, what I did in that constructor was member assignment, just ordinary variable assignment. Suppose I used this strange syntax instead:
Code:
Test::Test() : x(0), d() {
// doesn't have to do anything more
}
Now x is initialized to 0, and d is initialized to a Data with the default constructor. If I had a Data(int, int) constructor, I could use it like so:
Code:
Test::Test() : x(0), d(1, 2) {
// doesn't have to do anything more
}
This is initializing member variables, instead of assigning to them later. This lets you catch the variables before they've been initialized and say how you want them to be initialized.
Incidentally, this is the only way to initialized const variables. This doesn't work, for example:
Code:
class Something {
private:
const int x;
public:
Something() { x = 42; }
};
The compiler will tell you that you're trying to assign a value to a constant variable. If you use this it won't complain.
Code:
class Something {
private:
const int x;
public:
Something() : x(42) {}
};
It's like the difference between
Code:
const int x = 5; // initialization
and
Code:
const int x;
x = 5; // assignment
The first works, the second doesn't. Incidentally, if we used
Code:
SomeClass x;
x = SomeClass(3, 2);
then x would first be assigned a SomeClass() created with the default constructor, and then later on assigned to the SomeClass(3, 2) created with a SomeClass(int, int) constructor.
Anyway, I think that's enough verbosity for now . . . .