Google Groups unterstützt keine neuen Usenet-Beiträge oder ‑Abos mehr. Bisherige Inhalte sind weiterhin sichtbar.

nsCOMPtr<someConcreteClass> -- safe? appropriate? here's the answer

46 Aufrufe
Direkt zur ersten ungelesenen Nachricht

Scott Collins

ungelesen,
23.04.2001, 12:18:2423.04.01
an
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

>Scott, can you declare it safe and appropriate to
>use nsCOMPtr for singly-inheriting concrete XPCOM classes?

Alright, here's my final answer (and I'll add this to the |nsCOMPtr|
guide). I can declare it safe---if the concrete class provides a
default constructor---and I can illustrate at least one case where it
may be appropriate.

Given |nsCOMPtr<T>|, here's what |nsCOMPtr| requires of class |T|:

- |nsCOMTypeInfo<T>::GetIID| must provide an IID

this is satisfied if |T::GetIID| exists or is unambiguously
inherited, or else if |nsCOMPTypeInfo| is specialized for
class |T|; therefore, it is always satisfied by interfaces
and by singly-inheriting concrete classes, and never
(without explicit work by the implementor) satisfied by
multiply-inheriting concrete classes


- querying a reasonable |T*| for that IID must be an identity
operation

this is satisfied by decree with respect to an interface class
by all correct implementations of |QueryInterface|. It is
satisfied by coincidence for singly-inheriting concrete classes


- an instance of class |T| must provide unambiguous access to
|AddRef|, |Release|, and |QueryInterface|

this is always satisfied by interfaces and typically satisfied
by any concrete class, even in the multiple-inheritance case


- a |T*| must be unambiguously convertible to an |nsISupports*|

this is always satisfied by interfaces, typically satisfied by
singly-inheriting concrete classes, and _rarely_ satisfied by
multiply-inheriting concrete classes


- if class |T| is not abstract, then (because of a common compiler
bug) an instance of |T| must be ``default constructable'', i.e.,
|T::T()|, must exist and be accessible

this has actually been a rule in our portability guidelines
forever (since this compiler bug shows up in many different
situations unrelated to |nsCOMPtr|s), therefore, theoretically,
all concrete classes should satisfy this
[jband, I'm cc'ing you just so that you can see this point, as
this is my answer to a question you asked some time ago]


All of the above are easily satisfied by |T| when |T| is a correctly
declared XPCOM interface. Coincidentally, though reliably, it is also
satisfied when |T| is a concrete class that singly-inherits from an
XPCOM interface (or more correctly, singly-inherits from something
that satisfies the above requirements), as long as the derived class
provides a default constructor.

Even the multiple inheritance restriction may be lifted if the author
of the derived class is willing to go to some trouble in their
implementation (including implementing a static |GetIID|,
appropriately implementing |QueryInterface| and solving the
|nsISupports| conversion problem), essentially turning their
implementation into an interface.

If the requirements above are satisfied by a class |T|, it is safe to
use an |nsCOMPtr<T>| to hold an owning reference to an instance that
implements |T|, whether |T| is an |nsI...| interface class, or
something more derived, and even if the object itself is more derived
than |T|.

It is appropriate to do this, I would think, near the creation of that
instance, in particular, to call initialization methods not part of
the abstract |nsI...| interface, and to avoid any concern over the
possibility of failed QIs, e.g.,

nsresult
CreateFoo( nsIFoo** aResult )
{
nsresult status = NS_ERROR_OUT_OF_MEMORY;

nsCOMPtr<nsFooImpl> fooP = new nsFooImpl();
if ( fooP )
{
fooP->InitializeWithBar(aBar);

// pick either

status = CallQueryInterface(fooP, aResult);

// or

status = NS_OK;
*aResult = fooP;
NS_ADDREF(*aResult);

// whichever meets your needs
}
return status;
}

This example is probably better than trying to manage ownership with
an |nsCOMOPtr| to the |nsI...| type, which would require a QI before
ownership was established or else a cast.

Hope this helps,
______________________________________________________________________
Scott Collins http://ScottCollins.net/

-----BEGIN PGP SIGNATURE-----
Version: PGPfreeware 7.0.3 for non-commercial use <http://www.pgp.com>

iQA/AwUBOuRRZfGmojMuVn+fEQLD9ACg0ZJw7Ve46MM5oQwNzcsZwL492bMAoMmg
cBdAgQtLD1hu3HR5FAUA404D
=xKhi
-----END PGP SIGNATURE-----

0 neue Nachrichten