5.3. Implementace COM komponenty

COM komponenta tedy musí vždy obsahovat metody rozhraní IUnknown a metody všech dalších rozhraní, která bude poskytovat. Abychom vyhověli požadavkům specifikace COM, musíme tedy pozměnit definici rozhraní naší komponenty pro náhodná čísla a pak náležitě upravit její implementaci.

src/RandomCom/IRandom.h
Příklad 5.1. Rozhraní IRandom.h

Rozhraní komponenty pro generování náhodných čísel začíná direktivou pro zabránění opakovaného vkládání tohoto souboru do textu a pro vložení definice rozhraní IUnknown

#pragma once
#include "unknwn.h"  // Definice rozhraní IUnknown
Dále následuje definice globálního identifikátoru pro rozhraní IRandom. Tento identifikátor získáme voláním programu GUIDGEN.EXE a můžeme si vybrat z několika nabízených formátů. Zvolíme si formát používající makro DEFINE_GUID:
// {CB8DF8CB-3F6C-4c02-A587-18566C28487B}
DEFINE_GUID(IID_IRandom,      
   0xcb8df8cb, 0x3f6c,0x4c02,0xa5,0x87,0x18,0x56,0x6c,0x28,0x48,0x7b);
A nyní již následuje definice rozhraní. Nenechte se zmást klíčovým slovem interface, které samozřejmě není součástí C++, ale jedná se pouze o předefinované klíčové slovo struct. V této definici i ve zbývajících částech programu jsou rovněž použita další makra, která zajišťují větší nezávislost na konkrétní verzi překladače. Zde konkrétně makro STDMETHODCALL zajistí použití správných volacích konvencí.
interface IRandom : IUnknown {
   virtual HRESULT STDMETHODCALLTYPE Start( int seed) = 0;
   virtual HRESULT STDMETHODCALLTYPE Next( int *val) =0;
};

Rozhraní IRandom budeme implementovat třídou CRandomImpl, jejíž rozhraní následuje. Tato třída kromě všech metod rozhraní IUnknown a IRandom obsahuje rovněž konstruktor a dvě instanční proměnné. Proměnná m_refCnt bude sloužit jako počítadlo odkazů, v proměnné m_seed je uložena aktuální zdrojové číslo pro generování dalšího preudonáhodného čísla. Povšimněte si, že všechny metody rozhraní s výjimkou AddRef a Release vracejí jako návratovou hodnotu HRESULT, zbývající výstupní proměnné se předávají odkazem v argumentech.

src/RandomCom/RandomImpl.h
Příklad 5.2. Rozhraní třídy RandomImpl.h
#pragma once
#include "IRandom.h"

class CRandomImpl : public IRandom
{
public:
	CRandomImpl();

	// IUnknown
	STDMETHODIMP QueryInterface(REFIID, void **);
	STDMETHODIMP_(ULONG) AddRef(void);
	STDMETHODIMP_(ULONG) Release(void);
	// IRandom
	STDMETHODIMP Start(int seed);
	STDMETHODIMP Next(int* result);
private:
	ULONG m_refCnt;
	ULONG m_seed;
};