Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

curious about polymorphism in C++

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?

Name: Anonymous 2007-01-06 15:13

how does the program "know" array[1] is an AClass object and array[2] is a BClass object

It doesn't know and it can't know. BUT if you call a virtual function, the good type of subclass will be called because of the late-binding created during compile time. That's why there is a huge bug in your code: put all your destructors virtual or it won't be called and your objects won't be properly destroyed if you have this kind of thing:
Base *b = new Derived;
delete b;

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List