Wednesday 21 March 2012

Refactoring your way into a non-working program

Today I was tracking down a bug for a client, and eventually tracked it down to a virtual function call that was not being called.

It took a while to figure out.  First, I’d split my data class into itself and a base class, and I’d split my object performing the work into itself and a base class as well, ending up with the following classes:

class DataBaseClass
{
//...
};

class DataClass : class DataBaseClass
{
//...
};

class ObjectBaseClass
{
// ...
virtual void virt_func(DataBaseClass *pObj);
};

class ObjectClass
{
//...
virtual void virt_func(DataClass *pObj);
}


After discovering which class wasn’t having it’s virt_func called, it became obvious:  The signatures don’t match.  But how can I get the compiler to find these for me, that’s the important question.


I was going to blog about how C# is superior to C++ in this regard, until I discovered that VC++2010 actually supports the override keyword, so to catch the error, simply add the keyword override to the end of the derived virt_func’s as follows.  Alas it’s a non-standard extension, which requires a pragma to get rid of the warnings.


// disable warnings about override
#pragma warning(push)
#pragma warning(disable: 4481)

class ObjectClass
{
//...
virtual void virt_func(DataClass *pObj) override;
}

// ...
#pragma warning(pop)



This now generates an error when compiled, and points out all the places I got it wrong, and will continue to do so if I refactor again!

No comments:

Post a Comment