Stingray® Foundation : Chapter 3 Interface‑Based Programming
Chapter 3 Interface‑Based Programming
Introduction
Interface-based programming is a popular and convenient technique frequently used in object-oriented software development. An interface is a collection of pure-virtual or abstract functions that provide related functionality. An interface has no implementation and no data members. An interface defines a contract or protocol between the user of the interface and objects that implement the interface. Interfaces make a design more flexible because they reduce coupling between client code and an object's implementation. The same client code can manipulate objects that are completely unrelated in the class hierarchy, as long as the objects provide the client with an interface it understands.
Interface-based programming is the cornerstone of Microsoft's Component Object Model (COM). Everything in COM is an interface. All COM interfaces are derived from the root interface IUnknown, which provides the basic services required by all interfaces. Lifetime management is the first service required by COM interfaces, and is provided through the IUnknown functions AddRef() and Release(). Run-time discovery of interfaces is the other service required by COM interfaces, and is provided through the IUnknown function QueryInterface(). The QueryInterface() function is used to interrogate an object for another interface. QueryInterface() takes a Globally Unique Identifier (GUID) and returns a pointer to an interface. It is similar to the dynamic_cast operator in C++, although it is more flexible and efficient.
The same techniques that are used by COM are also useful in standard C++ programming. To do interface-based programming in C++, the same basic services — reference counting and run-time interface discovery — are required. It is possible to use IUnknown to provide these services for C++ interfaces, but that results in some confusion if the C++ interfaces and the classes that implement them don’t follow COM conventions. One such convention is that all functions in a COM interface must have a return type of HRESULT. This is an important convention to follow if your application uses remote Distributed Component Object Model (DCOM) objects, but it is not a convenient notation for local C++ objects. It is also inconvenient and inefficient to create your C++ objects with CoCreateInstance(). Mixing C++ objects and COM objects in the same code can be confusing and potentially dangerous. You need a mechanism similar to IUnknown for C++ objects that doesn’t interfere with COM.