15.2 Inheritance-based Interface Implementation
In the inheritance-based interface implementation approach, the implementation classes are derived from a generated base class based on the OMG IDL interface definition. The generated base classes are known as skeleton classes, and the derived classes are known as implementation classes. Each operation of the interface has a corresponding virtual member function declared in the skeleton class. The generated skeleton class is partially opaque to the programmer, though it will contain a member function corresponding to each operation in the interface. The signature of the member function is identical to that of the generated client stub class.
To implement this interface using inheritance, a programmer must
derive from this skeleton class and implement each of the
operations in the OMG IDL interface. To allow portable
implementations to multiple inheritances from both skeleton classes
and implementation classes for other base interfaces without error
or ambiguity, the Tobj_ServantBase
class must be a
virtual base class of the skeleton, and the
PortableServer::ServantBase
class must be a virtual
base class of the Tobj_ServantBase
class. The
inheritance among the implementation class, the skeleton class, the
Tobj_ServantBase
class, and the
PortableServer::ServantBase
class must all be public
virtual.
The implementation class or servant must only derive directly from a single generated skeleton class. Direct derivation from multiple skeleton classes could result in ambiguous errors due to multiple definitions of the _this()
operation. This should not be a limitation, however, since CORBA objects have only a single most-derived interface. C++ servants that are intended to support multiple interface types can utilize the delegation-based interface implementation approach. See the following code snippet for an example of OMG IDL that uses interface inheritance.
// IDL
interface A
{
short op1() ;
void op2(in long val) ;
};
The following code snippet for an example of Interface Class A.
// C++
class A : public virtual CORBA::Object
{
public:
virtual CORBA::Short op1 ();
virtual void op2 (CORBA::Long val);
};
On the server side, a skeleton class is generated. This class is partially opaque to the programmer, though it does contain a member function corresponding to each operation in the interface.
For the Portable Object Adapter (POA), the name of the skeleton
class is formed by prepending the string
“POA_
” to the fully scoped name of the
corresponding interface, and the class is directly derived from the
servant base class Tobj_ServantBase
. The C++ mapping
for Tobj_ServantBase
is as follows:
// C++
class Tobj_ServantBase
{
public:
virtual void activate_object(const char* stroid);
virtual void deactivate_object (
const char* stroid,
TobjS::DeactivateReasonValue reason
);
}
The activate_object()
and deactivate_object()
member functions are described in detail in the sections Tobj_ServantBase:: activate_object() and Tobj_ServantBase::_add_ref().
The skeleton class for interface A
shown above would appear as shown in the following code snippet.
// C++
class POA_A : public Tobj_ServantBase
{
public:
// ... server-side ORB-implementation-specific
// goes here...
virtual CORBA::Short op1 () = 0;
virtual void op2 (CORBA::Long val) = 0;
//...
};
If interface A
were defined within a module rather
than at global scope (for example, Mod::A
), the
name of its skeleton class would be POA_Mod::A
. This
helps to separate server application skeleton declarations and
definitions from C++ code generated for the client.
To implement this interface using inheritance, you must derive from this skeleton class and implement each of the operations in the corresponding OMG IDL interface. An implementation class declaration for interface A
would take the form shown in the following code snippet.
// C++
class A_impl : public POA_A
{
public:
CORBA::Short op1();
void op2(CORBA::Long val);
...
};
Parent topic: Server Side Mapping