Objective Views : Chapter 6 Key Architectural Concepts
Chapter 6 Key Architectural Concepts
Overview of Interface-Based Programming
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 GUID (Globally Unique Identifier) 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 very useful in straight C++ programming. In order 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, which is an important convention to follow for remote DCOM objects, but is not a convenient notation for local C++ objects. It’s also not very convenient or efficient to create your C++ objects using CoCreateInstance(). Mixing C++ objects and COM objects in the same code can also be confusing and potentially dangerous. What’s needed is a mechanism similar to IUnknown for C++ objects that doesn’t interfere with COM.