getter_AddRefs
and friends (Re: nsCOMPtr
questions)
Document Status: Retired.
This document is now obsolete.
Coincidentally, the information in this document is mostly accurate.
The only change is that one can, again,
initialize from or assign raw [XP]COM interface pointers
into an an nsCOMPtr
.
This is a synonym for saying dont_QueryInterface()
.
Please use the
nsCOMPtr
User's Manual
as your reference.
getter_AddRefs
and alternatives.
It is a followup to this message.
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 One thing to note about my previous message is that the examples were slightly simplified for the purpose of expounding on |getter_AddRef|s. In reality, the first two example assignments aren't actually legal. // Good for talking about |AddRef| but not actually legal... nsCOMPtr<X> x1 = aRawX; // ... nsCOMPtr<X> x2 = CreateAnX(); // Oops!... You aren't allowed to assign a raw pointer _directly_ into an |nsCOMPtr| without saying whether you will allow |QueryInterface| to be called. In both these cases, we don't need |QueryInterface| since |aRawX| is supposedly of the exact right type, and |CreateAnX()| produces a value of the exact right type. So we would actually say: nsCOMPtr<X> x1 = dont_QueryInterface( aRawX ); nsCOMPtr<X> x2 = dont_QueryInterface( CreateAnX() ); The functions available for this role are do_QueryInterface( X* ); // the pointer is |QueryInterface|d for the COM correct interface, // and it is |AddRef|ed (by |QueryInterface|) as part of the // assignment. Use this when the type you are assigning is is // different than your |nsCOMPtr|, e.g., Y* y; // ... nsCOMPtr<X> x = do_QueryInterace(y); do_QueryInterface( X*, nsresult* ); // as above, but the error result of |QueryInterface| is available // to you, e.g., nsresult status; nsCOMPtr<X> x = do_QueryInterface(y, &status); if ( NS_SUCCEEDED(status) ) // ... dont_QueryInterface( X* ); // the minimal action: my pointer is exactly the right type, I // PROMISE. So just assign it in. It _will_ be |AddRef|ed, // e.g., X* x; // ... nsCOMPtr<X> x = dont_QueryInterface(x); // Note, this is not appropriate for inheritance, e.g., class X { ... }; class Z : public X { ... }; Z* z; // ... nsCOMPtr<X> x = dont_QueryInterface(z); // Wrong! The |X| that C++ extracts from this instance may not // be the one |QueryInterface| would give you. You must use // |do_QueryInterface| nsCOMPtr<X> x = do_QueryInterface(z); // Right! getter_AddRefs( X* ); // the _really_ minimal action: my pointer is exactly the right // type, I PROMISE. So just assign it in. And by the way, the // thing that made the pointer already |AddRef|ed it for you. // E.g., X* CreateAnX(); // ... nsCOMPtr<X> x = getter_AddRefs( CreateAnX() ); dont_AddRef( X* ); // A deprecated synonym for |getter_AddRefs()| in case you happen // to see it in code. This chart summarizes the calls |AddRef| don't |AddRef| --------------------------------------------- allow QI |do_QueryInterface| ??? don't allow QI |dont_QueryInterface| |getter_AddRefs| So what do you do if you have to apply more than one of these? Well the only combination that you don't get `out of the box' (see the chart above) is when you want to |QueryInterface|, but you _don't_ want to |AddRef|. E.g., in this situation: Z* CreateAZ(); // ... nsCOMPtr<X> x = ??? Well, you can't really mix those two because in COM it is _interfaces_ not objects that are ref-counted. Ergo, you must say: Z* CreateAZ(); // ... nsCOMPtr<Z> z = getter_AddRefs( CreateAZ() ); // nsCOMPtr<X> x = do_QueryInterface(z); ...and in fact, if you don't otherwise need to keep the |Z| around, you can contain its life with nsCOMPtr<X> x; { nsCOMPtr<Z> z = getter_AddRefs( CreateAZ() ); x = do_QueryInterface(z); } ...and if our compilers were better on the marginal platforms, you could even reduce it to nsCOMPtr<X> x = do_QueryInterface( nsCOMPtr<Z>( getter_AddRefs(CreateAZ()) ) ); Hope this helps, ______________________________________________________________________ Scott Collins <http://www.meer.net/ScottCollins?Netscape> -----BEGIN PGP SIGNATURE----- Version: PGP Personal Privacy 6.0.2 Comment: get my key at <http://www.meer.net/ScottCollins/#key> iQA/AwUBNx9wi/GmojMuVn+fEQJ8WgCeJktjSOeFAngObqS2gaX0jM2QrW0AoJSB 7iMGA0my9dV5ZirRmsIKJQ4p =cOVU -----END PGP SIGNATURE-----