Monday, September 22, 2008

Exploring Dynamic Binding



A virtual table is a mechanism used for dynamic binding (run-time binding). 
If a class has at least one virtual function a virtual table is created for that class.
Only one virtual table will be created for all instances of that class. 
Each of the instances will have a pointer to that virtual table.

The virtual table pointer is called _vfptr, which will not be directly accessible from the code.
But, we can see that from the watch window while debugging.

class CFooBase
{
private:
int data;

public:
virtual void fun1()
{
printf("fun1 from base\n");
}

virtual void fun2()
{
printf("fun2 from base\n");
}
};

class CFooDerived: public CFooBase
{
private:
int data;

public:
void fun1()
{
printf("fun1 from derived\n");
}
};

CFooDerived obj1, obj2;

The representation of CFooDerived objects will be like the following


























Note: There is no implementation of fun2 in derived class CFooDerived.  So, the virtual table stores the pointer of CFooBase::fun2()  

we can access virtual functions directly from virtual table.

typedef void (*Fun)();

int _tmain(int argc, _TCHAR* argv[])
{
CFooDerived obj;

Fun fun = (Fun)*((int*) (*(int*)(&obj)) + 0);
fun();

fun = (Fun)*((int*) (*(int*)(&obj)) + 1);
fun();

getche();
return 0;
}

we assumed here that the _vfptr placed at the beginning of the class object. but, the C++ standards allows the compailer that the freedom to insert that anywhere in the object.

In case of multiple inheritance, multiple virtual tables will be created corresponds to each base classes, which has at least one virtual function.

class CFooBase1

{
private:
int base1_data;

public:
virtual void fun1_base1()
{
printf("fun1 from base1\n");
}

virtual void fun2_base1()
{
printf("fun2 from base1\n");
}
};


class CFooBase2
{
private:
int base2_data;

public:
virtual void fun1_base2()
{
printf("fun1 from base2\n");
}

virtual void fun2_base2()
{
printf("fun2 from base2\n");
}
};


class CFooDerived: public CFooBase1, public CFooBase2
{
private:
int der_data;

public:
void fun1_base1()
{
printf("fun1_base1 from derived\n");
}

void fun2_base1()
{
printf("fun2_base1 from dervied\n");
}

void fun1_base2()
{
printf("fun1_base2 from derived\n");
}
};

CFooDerived obj;

the representation of obj will be like the following



























Cheers,

Thursday, September 18, 2008

Overloading of new and delete in MFC application

In debug build, MFC defines a preprocessor macro that expand the new and delete operators to the overloaded new and delete operators

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

this will effects two extra parameter for the new and delete operator in the debug build of the MFC application

see the declartion in afx.h
void* AFX_CDECL operator new(size_t nSize, LPCSTR lpszFileName, int nLine);

MFC use this information to report memory leaks. 
in debug mode, DEBUG_NEW keeps the track of file name and line number for each object that allocates.
this information will be displayed when using the function CMemoryState::DumpAllObjectsSince()

Because of this expansion done by the preprocessor, it will affect the usage of new and delete operators.
if any non MFC classes used in this project, their new and delete operators is also expanded, this will make the issue in the overloading of new operator in MFC application

for resolving this issue, overload new and delete operators like the following, for the classes in an MFC application

class CFoo
{
public:
CFoo(void){}
virtual ~CFoo(void){}

// for release mode
void*operator new(size_t nSize);
void operator delete(void* p);

// for debug mode
void* operator new(size_t nSize, LPCSTR lpszFileName, int nLine);
void operator delete(void* p, LPCSTR lpszFileName, int nLine);
};

void* CFoo :: operator new(size_t nSize)
{
return malloc(nSize);
}

void CFoo :: operator delete(void* p)
{
free(static_cast(p));
}

void* CFoo :: operator new(size_t nSize, LPCSTR lpszFileName, int nLine)
{
return malloc(nSize);
}

void CFoo :: operator delete(void* p, LPCSTR lpszFileName, int nLine)
{
free(static_cast(p));
}

Cheers,

Restrict dynamic creation of the objects of a class without effecting static creation of objects.

overload new operator and return NULL
-------------------------
example:
class CFoo
{
public:
CFoo(){}
virtual ~CFoo(){}
// overloaded new operator
void* operator new (size_t size); 

// overloaded new[] operator
void* operator new [] (size_t size);
};

void* CFoo :: operator new (size_t  size)
{
return NULL; 
}

void* CFoo :: operator new [] (size_t size)
{
return NULL; 
}

----------------------------------------
note: don't forget to overload new[] also
otherwise, will allow to create dynamic creation when trying to create arrays.