Friday, 29 November 2013

Where’d my interface go?

One of the joys of modern development is that you get to work in pretty much any language there is.

I’ve been doing a lot of C# development lately (Phone, WinRT and WPF desktop), but occasionally have to drop back to some C++/MFC software.

Yesterday, I had to refactor some code, that made some glaring assumptions about it’s use (yes, I used reinterpret_cast to convert a CWnd derived object to a class derived from CPropertyPage so that I could call one of it’s public members).

So here’s what I did:

First, I declared an interface that represented exactly what I wanted to do:

interface IDoSomethingAwesome
{
public:
virtual void DoSomethingAwesome()=0;
};


Next, I modified my class, which needed to expose the interface


public class MyAwsomePropertyPage : 
public CPropertyPage, IDoSomethingAwesome
{
/// ... etc.
virtual void DoSomethingAwesome() override;
}


and provided an implementation in the class.


Then in an unrelated class, I made a call like this


CChildOfAwsome::SomeEventHander()
{
IDoSomethingAwesome *pInt = dynamic_cast<IDoSomethingAwesome>(GetParent());
if (pInt != NULL)
{
pInt->DoSomethingAwesome();
}
}


Only one problem:  pInt was always NULL!  That was odd, because looking at the pointer returned by GetParent() gave me an object that the debugger knew was of type MyAwesomePropertyPage, yet I couldn’t for the life of me figure out why this wasn’t working.


I started writing this up as a question on StackOverflow, but while doing so, ended up talking to the duck and discovered the error in my ways.


My C# had blinded me to the joys of C++ inheritance.


I had inadvertently declared my IDoSomethingAwesome interface not public.  As a result, asking for the interface dutifully returns null, as private inheritance is an implementation detail, and not visible in the inheritance tree.


So, the correct declaration is

public class MyAwsomePropertyPage : 
public CPropertyPage, public IDoSomethingAwesome
{
/// ... etc.
virtual void DoSomethingAwesome() override;
}

No comments:

Post a Comment