Virtual calls in constructors

In CrossNet, we have actually several stages during construction:
  • First, we set the allocated memory to zero (as optimization we actually skip the first 12 bytes as they are going to be overwritten anyway - VTable - Interface map - Flags).
  • Then we construct the object as an usual C++ construction, this initialize the virtual table, default construct the members (which does nothing for primitive types, pointers and as such pretty much all the .NET types).
  • Then we set the interface map.
  • Finally we call the provided constructor (as it is done after the VTable has been set, the result is that it calls the correct function).
  • The constructor will call the base class's constructor or another constructor of the same class as needed.

class TestBaseClass
{
    public TestBaseClass(int foo)
    {
    }
}

class TestBaseClass2 : TestBaseClass
{
    public TestBaseClass2() : base(0)
    {
    }
}


Is generated in C++ as:

void CrossNetUnitTest::OO::TestBaseClass::__ctor__(::System::Int32 foo)
{
::System::Object::__ctor__();
{
}
}
::CrossNetUnitTest::OO::TestBaseClass * CrossNetUnitTest::OO::TestBaseClass::__Create__(::System::Int32 foo)
{
    ::CrossNetUnitTest::OO::TestBaseClass *__temp__ = new ::CrossNetUnitTest::OO::TestBaseClass();
    CROSSNET_ASSERT(__GetInterfaceMap__() != NULL, "Interface map not set correctly!");
    __temp__->m__InterfaceMap__ = __GetInterfaceMap__();
    __temp__->__ctor__( foo);
    return (__temp__);
}

void CrossNetUnitTest::OO::TestBaseClass2::__ctor__()
{
::CrossNetUnitTest::OO::TestBaseClass::__ctor__(0);
{
}
}
::CrossNetUnitTest::OO::TestBaseClass2 * CrossNetUnitTest::OO::TestBaseClass2::__Create__()
{
    ::CrossNetUnitTest::OO::TestBaseClass2 *__temp__ = new ::CrossNetUnitTest::OO::TestBaseClass2();
    CROSSNET_ASSERT(__GetInterfaceMap__() != NULL, "Interface map not set correctly!");
    __temp__->m__InterfaceMap__ = __GetInterfaceMap__();
    __temp__->__ctor__();
    return (__temp__);
}


As you can see, you call Create() to create the object, wchich in return will call the constructor ctor.
The operator new is overriden to let the GC do the allocation as well as zeroing the memory.

Last edited Sep 7, 2007 at 9:58 PM by OlivierNallet, version 1

Comments

No comments yet.