Name: Anonymous 2007-01-06 15:08
I'm curious how polymorphism in C++ ends up being compatible with the way arrays work internally in the language. Here's an example:
//===========================================================
#include <cstdio>
class BaseClass {
public:
int a, b, c;
float d;
BaseClass() : a(5), b(2), c(9), d(1.432) { };
~BaseClass() { };
virtual void print(void) const;
};
void BaseClass::print(void) const
{
printf("I am BaseClass -- a = %d, b = %d, c = %d, d = %f\n", a, b, c, d);
}
// =============================================================================
class AClass : public BaseClass {
public:
int e, f, g;
double zzz, xxx;
AClass() : e(40), f(50), g(60), zzz(154389.432292), xxx(394.9999282) { };
~AClass() { };
virtual void print(void) const;
};
void AClass::print(void) const
{
printf("I am AClass -- a = %d, b = %d, c = %d, d = %f\n", a, b, c, d);
printf(" e = %d, f = %d, g = %d\n", e, f, g);
printf(" zzz = %f, xxx = %f\n", zzz, xxx);
}
class BClass : public BaseClass {
public:
int z;
char *str;
BClass() : z(-5), str("BClass->str...") { };
~BClass() { }
virtual void print(void) const;
};
void BClass::print(void) const
{
printf("I am BClass -- a = %d, b = %d, c = %d, d = %f\n", a, b, c, d);
printf(" z = %d, str = %s\n", z, str);
}
int main(void)
{
BaseClass **array = new BaseClass*[3];
array[0] = new BaseClass();
array[1] = new AClass();
array[2] = new BClass();
printf("sizeof(BaseClass) = %d, (AClass) = %d, (BClass) = %d\n", sizeof(BaseClass),
sizeof(AClass), sizeof(BClass));
printf("sizeof(*array[0]) = %d, (*array[1]) = %d, (*array[2]) = %d\n", sizeof(*array[0]),
sizeof(*array[1]), sizeof(*array[2]));
for (int i = 0; i < 3; i++)
array[i]->print();
}
//============================================================
It outputs as follows:
sizeof(BaseClass) = 20, (AClass) = 48, (BClass) = 28
sizeof(*array[0]) = 20, (*array[1]) = 20, (*array[2]) = 20
I am BaseClass -- a = 5, b = 2, c = 9, d = 1.432000
I am AClass -- a = 5, b = 2, c = 9, d = 1.432000
e = 40, f = 50, g = 60
zzz = 154389.432292, xxx = 394.999928
I am BClass -- a = 5, b = 2, c = 9, d = 1.432000
z = -5, str = BClass->str...
Okay, it seems to Just Work but how? Why doesn't the 48-byte chunk of stuff in array[1] clobber what's in array[2]? I know all BaseClass objects are 20 bytes and it seems to store each object in the array as -that-, but considering it in that perspective, how does the program "know" array[1] is an AClass object and array[2] is a BClass object?
I'm guessing the way it works properly involves storing the data for these objects in a non-contiguous way, no?
I'm just trying to get an idea of what the limits of polymorphism are in C++, by that I mean the technical limits. I mean, for all intents and purposes, I've technically made a heterogenous array, something I thought wasn't possible in C++.
Once again I learn something new every day about this language I've been using for over 6 years. I just wish I knew about this sooner instead of letting my assumptions about internals stop me from trying this. I saw this done in a C# book and I was like, "tomorrow morning I'm going to try that in C++ and see if it works" and sure enough it does.
But... WHY does it work?
//===========================================================
#include <cstdio>
class BaseClass {
public:
int a, b, c;
float d;
BaseClass() : a(5), b(2), c(9), d(1.432) { };
~BaseClass() { };
virtual void print(void) const;
};
void BaseClass::print(void) const
{
printf("I am BaseClass -- a = %d, b = %d, c = %d, d = %f\n", a, b, c, d);
}
// =============================================================================
class AClass : public BaseClass {
public:
int e, f, g;
double zzz, xxx;
AClass() : e(40), f(50), g(60), zzz(154389.432292), xxx(394.9999282) { };
~AClass() { };
virtual void print(void) const;
};
void AClass::print(void) const
{
printf("I am AClass -- a = %d, b = %d, c = %d, d = %f\n", a, b, c, d);
printf(" e = %d, f = %d, g = %d\n", e, f, g);
printf(" zzz = %f, xxx = %f\n", zzz, xxx);
}
class BClass : public BaseClass {
public:
int z;
char *str;
BClass() : z(-5), str("BClass->str...") { };
~BClass() { }
virtual void print(void) const;
};
void BClass::print(void) const
{
printf("I am BClass -- a = %d, b = %d, c = %d, d = %f\n", a, b, c, d);
printf(" z = %d, str = %s\n", z, str);
}
int main(void)
{
BaseClass **array = new BaseClass*[3];
array[0] = new BaseClass();
array[1] = new AClass();
array[2] = new BClass();
printf("sizeof(BaseClass) = %d, (AClass) = %d, (BClass) = %d\n", sizeof(BaseClass),
sizeof(AClass), sizeof(BClass));
printf("sizeof(*array[0]) = %d, (*array[1]) = %d, (*array[2]) = %d\n", sizeof(*array[0]),
sizeof(*array[1]), sizeof(*array[2]));
for (int i = 0; i < 3; i++)
array[i]->print();
}
//============================================================
It outputs as follows:
sizeof(BaseClass) = 20, (AClass) = 48, (BClass) = 28
sizeof(*array[0]) = 20, (*array[1]) = 20, (*array[2]) = 20
I am BaseClass -- a = 5, b = 2, c = 9, d = 1.432000
I am AClass -- a = 5, b = 2, c = 9, d = 1.432000
e = 40, f = 50, g = 60
zzz = 154389.432292, xxx = 394.999928
I am BClass -- a = 5, b = 2, c = 9, d = 1.432000
z = -5, str = BClass->str...
Okay, it seems to Just Work but how? Why doesn't the 48-byte chunk of stuff in array[1] clobber what's in array[2]? I know all BaseClass objects are 20 bytes and it seems to store each object in the array as -that-, but considering it in that perspective, how does the program "know" array[1] is an AClass object and array[2] is a BClass object?
I'm guessing the way it works properly involves storing the data for these objects in a non-contiguous way, no?
I'm just trying to get an idea of what the limits of polymorphism are in C++, by that I mean the technical limits. I mean, for all intents and purposes, I've technically made a heterogenous array, something I thought wasn't possible in C++.
Once again I learn something new every day about this language I've been using for over 6 years. I just wish I knew about this sooner instead of letting my assumptions about internals stop me from trying this. I saw this done in a C# book and I was like, "tomorrow morning I'm going to try that in C++ and see if it works" and sure enough it does.
But... WHY does it work?