-----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-----

Reply via email to