Interface Pointers and Interfaces

An instance of an interface implementation is actually a pointer to an array of pointers to methods (a function table that refers to an implementation of all of the methods specified in the interface). Objects with multiple interfaces can provide pointers to more than one function table. Any code that has a pointer through which it can access the array can call the methods in that interface.

Speaking precisely about this multiple indirection is inconvenient, so instead, the pointer to the interface function table that another object must have to call its methods is called simply an interface pointer. You can manually create function tables in a C application or almost automatically with C++ (or other object-oriented languages that support COM).

With appropriate compiler support (which is inherent in C and C++), a client can call an interface method through its name, not its position in the array. Because an interface is a type, given the names of methods the compiler can check the types of parameters and return values of each interface method call. In contrast, such type-checking is not available even in C or C++ if a client uses a position-based calling scheme.

Each interface — the immutable contract of a functional group of methods — is referred to at runtime with a globally-unique interface identifier, an "IID". This IID, which is a specific instance of a GUID (a Globally Unique Identifier supported by COM – see the glossary entry Interface Identifier) allows a client to ask an object precisely if it supports the semantics of the interface without unnecessary overhead and without the confusion that could arise in a system from having multiple versions of the same interface with the same name.

To summarize, it is important to understand what an interface is, and is not:

An interface is not a C++ class—the pure virtual definition carries no implementation. If you are a C++ programmer, you can, however, define your implementation of an interface as a class, but this falls under the heading of implementation details, which COM does not specify. An instance of an object that implements an interface must be created for the interface actually to exist. Furthermore, different object classes may implement an interface differently yet be used interchangeably in binary form, as long as the behavior conforms to the interface definition.

An interface is not an object — it is simply a related group of functions and is the binary standard through which clients and objects communicate. The object can be implemented in any language with any internal state representation, as long as it can provide pointers to interface methods.

Interfaces are strongly typed — every interface has its own interface identifier (a GUID), which eliminates the possibility of duplication that could occur with any other naming scheme.

Interfaces are immutable contracts — you cannot define a new version of an old interface and give it the same identifier. Adding or removing methods of an interface, or changing semantics creates a new interface, not a new version of an old interface. Therefore a new interface cannot conflict with an old interface. Objects can, of course, support multiple interfaces simultaneously, and can expose interfaces that are successive revisions of an interface, with different identifiers. Thus, each interface is a separate contract, so system-wide objects need not be concerned about whether the version of the interface they are calling is the one they expect. The interface ID (IID) defines the interface contract explicitly and uniquely.