| Lesson 3 | What you need |
| Objective | Discover what you need to take this course. |
The Component Object Model (COM) is a binary interface standard for software components introduced by Microsoft in 1993. COM enables interprocess communication and dynamic object creation across any language that supports its binary conventions. COM components can communicate whether they reside in the same process, in separate processes on the same machine, or on different machines via DCOM. The three mechanisms COM provides for building one component on top of another are containment, delegation, and aggregation. Understanding these mechanisms and their constraints is the foundation of Advanced COM development.
Containment is the first method for implementing one COM object in terms of another. The outer object holds the inner object as a private member. The outer object creates its own vtable and implements interfaces that wrap the inner object's functionality. Clients interact only with the outer object; the inner object is completely hidden from client code. The outer object controls which of the inner object's capabilities are exposed to clients and may add, modify, or suppress behavior on a method-by-method basis.
Containment is the simpler of the two primary COM reuse techniques because the outer object always maintains its own IUnknown identity. There is no ambiguity about reference counting or interface identity: the outer object's QueryInterface determines exactly what the client can see. This simplicity makes containment the preferred technique when the outer object needs to filter, extend, or selectively expose the inner object's behavior.
Delegation is the forwarding pattern used within containment. When the outer object does not need to modify the inner object's behavior for a particular method, it forwards the client's call directly to the inner object's implementation rather than reimplementing the behavior itself. The outer object decides on a method-by-method basis whether to handle a call in its own implementation or pass it through unchanged to the inner object.
Delegation is not a separate COM reuse mechanism independent of containment. It is the technique the outer object uses inside its own method implementations to avoid duplicating the inner object's logic. A containment implementation that forwards all calls to the inner object without modification is pure delegation. A containment implementation that handles some calls itself and forwards others is selective delegation.
Aggregation allows the outer object to expose the inner object's interfaces directly to clients as if they were its own. Unlike containment, the outer object does not re-implement the inner interfaces. Instead, it hands the inner object's interface pointer directly to clients via its own QueryInterface. Clients then call the inner object's methods directly through the pointer the outer object provided.
Aggregation requires strict IUnknown pointer exchange rules to be observed correctly. The inner object's constructor must receive the outer object's IUnknown, known as the controlling unknown, as a constructor parameter. When the inner object is being aggregated, it must delegate all QueryInterface, AddRef, and Release calls to the controlling unknown rather than handling them itself. The inner object must also implement a separate non-delegating IUnknown for its own use during construction and teardown, before the controlling unknown relationship is established.
Failure to implement these rules correctly produces circular reference counting, interface identity violations, and memory leaks that are difficult to diagnose at runtime. The ATL macros DECLARE_AGGREGATABLE and DECLARE_NOT_AGGREGATABLE generate the correct controlling unknown plumbing automatically when the ATL COM wizard is used to create a COM server with aggregation support in Visual Studio 2022.
The key constraint distinguishing aggregation from containment is that the outer object cannot modify or filter the inner object's interface behavior. Clients receive the inner object's implementation exactly as it is. The outer object retains control over which of the inner object's interfaces are exposed via its own QueryInterface, but it cannot alter the behavior of any interface it does expose.
This constraint has an important architectural consequence. An architecture that requires a client to access any inner component interface without restriction is incompatible with the aggregation specification. The outer object must always control which inner interfaces are exposed through its QueryInterface. Architectures that need unrestricted access to inner component interfaces should use containment with explicit delegation instead of aggregation.
The three reuse mechanisms differ in how much control the outer object retains over the inner object's behavior and how much complexity the IUnknown implementation requires:
| Technique | Inner object visible to client | Outer object can modify behavior | IUnknown complexity |
|---|---|---|---|
| Containment | No | Yes | Simple: outer object has its own IUnknown |
| Delegation | No | Yes, selectively | Simple: used within containment |
| Aggregation | Yes, directly | No | Complex: controlling unknown required |
ATL in Visual Studio 2022 provides template support for both containment and aggregation. The DECLARE_AGGREGATABLE macro generates the controlling unknown plumbing required for aggregation. The ATL COM wizard enables aggregation support at the time the COM server project is created. Containment is implemented manually: the developer adds the inner object as a member variable and forwards calls to it explicitly in each method implementation.
To complete COM Fundamentals II successfully, install Visual Studio 2022 with the Desktop development with C++ workload. Visual Studio 2022 Community Edition is available at no cost for individual developers and students:
visualstudio.microsoft.com/downloads
During installation, ensure the following components are selected under the Desktop development with C++ workload:
No additional software is required beyond Visual Studio 2022. The course examples use the ATL COM wizard and the MIDL compiler, both of which are included in the Visual Studio 2022 C++ workload.
COM is a Windows binary standard. This course requires a Windows development environment. Windows 11 with Visual Studio 2022 is the recommended platform.
Developers working on non-Windows hardware have two options. The first is to run Windows 11 in a virtual machine using VMware Fusion, Parallels Desktop, or Hyper-V, with Visual Studio 2022 installed inside the virtual machine. The second is to use Windows Subsystem for Linux 2 (WSL2) on a Windows 11 host for command-line build work alongside a Visual Studio 2022 instance running on the Windows side.
Visual Studio for Mac was retired by Microsoft in August 2024 and is no longer available or supported. Visual Studio Code with the C/C++ extension and the MSVC compiler toolchain is available on Windows as a lightweight alternative to the full Visual Studio 2022 IDE, though the ATL COM wizard is only available in the full Visual Studio IDE.