There are a number of ways to define an interface. Regardless of the technique, an interface definition always reduces to either a C++ abstract base class (a class with nothing but pure virtual function signatures) or a C structure containing pointers to the interface member functions (the vtable) and a second structure containing a pointer to that vtable. The two are entirely equivalent. As examples, here are the entries for the IUnknown interface as taken from the Win32 SDK header file OBJBASE.H:
//This is a convenience for documentation.
#define interface struct
typedef /* [unique] */ IUnknown __RPC_FAR *LPUNKNOWN;
EXTERN_C const IID IID_IUnknown;
#if defined(__cplusplus) && !defined(CINTERFACE)
interface IUnknown
{
public:
virtual HRESULT __stdcall QueryInterface(
/* [in] */ REFIID riid,
/* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject) = 0;
virtual ULONG __stdcall AddRef(void) = 0;
virtual ULONG __stdcall Release(void) = 0;
};
#else /* C style interface */
typedef struct IUnknownVtbl
{
HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
IUnknown __RPC_FAR * This,
/* [in] */ REFIID riid,
/* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
ULONG ( __stdcall __RPC_FAR *AddRef )(
IUnknown __RPC_FAR * This);
ULONG ( __stdcall __RPC_FAR *Release )(
IUnknown __RPC_FAR * This);
} IUnknownVtbl;
interface IUnknown
{
CONST_VTBL struct IUnknownVtbl __RPC_FAR *lpVtbl;
};
#endif /* C style interface */
The text in this book, as well as the original OLE specifications, uses a clean C++ style syntax—without all the platform-specific embellishments and "virtual" keywords—to illustrate an interface's member functions. (Note that the IID to QueryInterface is passed by reference in C++ and passed as a const pointer in C.)
interface IUnknown
{
HRESULT QueryInterface(IID& iid, void **ppv);
ULONG AddRef(void);
ULONG Release(void);
};
When you're working in C++, you can derive one interface definition from another by using C++ inheritance, illustrated in the following syntax example. This is the only place where OLE makes use of such inheritance. Different mechanisms are employed in achieving reusability, as we'll see in "Object Polymorphism and Reusability" later in this chapter.
interface IProvideClassInfo : IUnknown
{
HRESULT GetClassInfo(ITypeInfo **ppTI)
};
From the puzzled look on your face, I know you have a few questions. What is all that extra junk in the Win32 definition about? What is an HRESULT?