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