Consider the following outline of IDL interface definitions:
interface Account { . . . }; interface Savings: Account { . . . };
This outline results in the definition of C++ data types Account
, Savings
, Account_ptr
, Account
, Account_var
, Savings_var
, and Savings_ptr
.
To show the assignment compatibility between the last four of these types, assume the following four definitions:
Account_ptr pa = ...; Account_var va = ...; Savings_ptr psa = ...; SavingsLvar vsa = ...;
As is normal in object-oriented systems, if you have a reference to a Savings
object, you can assign it to a reference of type Account
. Moving from a derived interface to a base interface is termed widening in CORBA (C++ refers to this as upcast).
The following assignments automatically widen a reference from a Savings
reference to an Account
reference (read these assignment statements independently, not as a statement sequence):
pa = psa; //Allowed but no reference count increment. pa = vsa; //Allowed but no reference count increment. va = psa; //Allowed but no reference count increment. //Reference count of va is decremented. va = Account::_duplicate(vsa);
Note:
It is a compile-time error to write va = vsa;
such implicit widening between _var
types is illegal in the CORBA specification.
To increment the reference counts in the first three assignments, the _duplicate( )
function should be used:
pa = Account::_duplicate(psa); // Reference count incremented. pa = Account::_duplicate(vsa); // Reference count incremented. va = Account::_duplicate(psa); // Reference count incremented. // Reference count of object va // previously pointed to is // decremented.
The term narrowing is used in CORBA when moving from a base interface to a derived interface (C++ refers to this as down-cast). If you have a base interface reference, you can assign it to a derived interface, but only if the base reference actually refers to an instance of the derived interface. There is no way to statically determine whether this condition holds, so a runtime test must determine the safety of the assignment.
The following statements narrow a reference from an Account
reference to a Savings
reference (read these if
statements independently, not as a statement sequence):
psa = Savings::_narrow(pa); if (!CORBA::_is_nil(psa)) { /* pa did reference a Savings */ } else { /* the narrow failed */ } psa =Savings::_narrow(va); if (!CORBA::_is_nil(psa)) { /* va did reference a Savings */ } else { /* the narrow failed */ ) vsa = Savings::_narrow(pa); if (!CORBA::_is_nil(vsa)) { /* va did reference a Savings */ } else { /* the narrow failed */ }
Note that the static function _narrow( )
returns a nil object reference if the parameter passed to it is not a reference to an object of the correct interface, or a derived interface. A successful call to _narrow( )
increments the reference count of the target object; a failed call does not.