Regler för att implementera QueryInterface
Det finns tre huvudregler som styr implementeringen av metoden IUnknown::QueryInterface på ett COM-objekt:
- Objekt måste ha identitet.
- Uppsättningen med gränssnitt på en objektinstans måste vara statisk.
- Det måste vara möjligt att fråga efter alla gränssnitt på ett objekt från något annat gränssnitt.
Objekt måste ha identitet
För en viss objektinstans måste ett anrop till QueryInterface med IID_IUnknown alltid returnera samma fysiska pekarvärde. På så sätt kan du anropa QueryInterface- på två gränssnitt och jämföra resultaten för att avgöra om de pekar på samma instans av ett objekt.
Uppsättningen gränssnitt på en objektinstans måste vara statisk
Den uppsättning gränssnitt som är tillgängliga för ett objekt via QueryInterface måste vara statiska, inte dynamiska. Mer specifikt, om QueryInterface- returnerar S_OK för ett visst IID en gång, får det aldrig returnera E_NOINTERFACE vid efterföljande anrop på samma objekt. och om QueryInterface- returnerar E_NOINTERFACE för ett visst IID, får efterföljande anrop för samma IID på samma objekt aldrig returnera S_OK.
Det måste vara möjligt att fråga efter ett gränssnitt på ett objekt från ett annat gränssnitt
Det vill: med följande kod:
IA * pA = (some function returning an IA *);
IB * pB = NULL;
HRESULT hr;
hr = pA->QueryInterface(IID_IB, &pB);
följande regler gäller:
Om du har en pekare till ett gränssnitt på ett objekt måste ett anrop som följande för att QueryInterface- för samma gränssnitt lyckas:
pA->QueryInterface(IID_IA, ...)
Om ett anrop till QueryInterface för en andra gränssnittspekare lyckas måste även ett anrop till QueryInterface från den pekaren för det första gränssnittet lyckas. Om pB har hämtats måste följande också lyckas:
pB->QueryInterface(IID_IA, ...)
Alla gränssnitt måste kunna fråga efter andra gränssnitt på ett objekt. Om pB har hämtats och du har frågat efter ett tredje gränssnitt (IC) med hjälp av den pekaren måste du också kunna fråga efter IC med hjälp av den första pekaren, pA. I det här fallet måste följande sekvens lyckas:
IC * pC = NULL; hr = pB->QueryInterface(IID_IC, &pC); pA->QueryInterface(IID_IC, ...)
Gränssnittsimplementeringar måste ha en räknare med enastående pekarreferenser till alla gränssnitt på ett visst objekt. Du bör använda ett osignerat heltal för räknaren.
Om en klient behöver veta att resurser har frigjorts måste den använda en metod i något gränssnitt på objektet med semantik på högre nivå innan den anropar IUnknown::Release.
Relaterade ämnen