ZUnknown interface overview

Declared in: API\zinterface.h
Included by: zmodeler.h
class ZUnknown
{
public:
  virtual DWORD AddRef(void) = 0;
  virtual DWORD Release(void) = 0;
  virtual ZRESULT QueryInterface(LPCSTR uid, void**) = 0;
  virtual ZUnknown* GetControllingUnknown() = 0;
};

Description

ZUnknown is a pure virtual base class for interfaces. Any interface which is not direvied from another interface is derived from this class. ZUnknown is very similar to IUnknown interface, but it uses a bit different QueryInterface function and has additional GetControllingUnknown function.

ZUnknown is designed to control interface references count and managing access to different interfaces within one class implementation. References count is controlled with AddRef and Release functions. Interfaces are identified by fully-qualified string names and obtained via QueryInterface function.

GetControllingUnknown function was added to interface (in contrast to IUnknown interface) and allows to get "root" ZUnknown interface from any interface instantly, without quering it and without additional references count. This helps to compare interfaces and used by some implementations widely.

Multiple inheritance

Multiple inheritance in ZModeler is a very common situation. For example, almost all class in ZModeler being inherited from some interface are also inherit core::IErrorInfo interface to support error reporting. Thus, the class comes up with several ZUnknown interfaces (one is the base of an interface, another is a base of IErrorInfo interface). In such a case, the first ZUnknown is used and called a Controlling unknown. Even if you have a pointer to the second interface and perfrom AddRef/Release on it, controlling unknown's refereces are altered.

//
// just an example
#include <zmodeler.h>
#include <scene/IMeshNode.h>

class CMyMeshNode : public scene::IMeshNode,  //->scene::INode -> ZUnknown
                    public core::INamed,      //->ZUnknown
                    public core::IErrorInfo   //->ZUnknown
{
public:
  //
  // some implementation.
  //
};

In an example above class CMyMeshNode has three ZUnknown interfaces in declaration, so it's impossible to call CMyMeshNode->AddRef() due to ambiguity. Instead, only one ZUnknown interface (the first one, that comes from scene::IMeshNode) is used. It's called a controlling unknown and it's functions implementations is used. Thus, for example, when you've queried an core::IErrorInfo interface on this class (and interface pointer points to this class, rather than to CMyMeshNode) AddRef, Release and QueryInterface will call virtual functions implementation from scene::INode.

This SDK, like an ATL provides set of macros that implements all required semantic for this to work properly, so, in general, you don't need to care about reference counting and techniques of query interfaces.

Helper implementation and declaration macros for interfaces.

If you are familiar with COM/ATL, you can skimm this paragraph and check just the semantic and arguments for ZModeler-styled interface macros (they are very silimar to ATL).

If you are familiar with MFC, consider that the class you implement which supports multiple interfaces have to declare these interfaces like a message map in MFC. ZModeler provides delarative macros of interfaces and implementation macros which are similar to BEGIN_MESSAGE_MAP..END_MESSAGE_MAP. This also includes several macros for declaring interfacecs inside "this pair" of begin-end macros.

Just in case you have never coded COM/ATL/MFC classes, follow the some basic rules. First of all: declare interface map inside your class (in a header file) with, preferable a INTERFACE_DECLAREMAP macro. Second, create a block of INTERFACE_BEGINMAP and INTERFACE_ENDMAP in implementation (.cpp) file with respect to namespace. Declare all interfaces you class supports (directly or indirectly) with INTERFACE_ENTRY macro (between begin-end map macros) with fully-qualified interface names. Always add virtual destructor to you class: at least you could place a brakepoint in it to be sure your class get's properly released.

IID_( ) Interface Identifier macro.
INTERFACE_DECLARE* Interface mapping declaration macros.
INTERFACE_MAP* Interface mapping implementation macros.
See Also:
References overview