Table of Contents Previous Next
Logo
Slice Metadata Directives : B.2 Metadata Directives for C++
Copyright © 2003-2010 ZeroC, Inc.

B.2 Metadata Directives for C++

cpp:array
cpp:range:array

These directives apply to sequences. They direct the code generator to create zero-copy APIs for passing sequences as parameters. See Section 6.7.4 for details.

cpp:class

This directive applies to structures. It directs the code generator to create a C++ class (instead of a C++ structure) to represent a Slice structure. (See Section 6.7.2.)

cpp:const

This directive applies to operations. It directs the code generator to create a const pure virtual member function for the skeleton class. (See Section 8.4.2.)

cpp:type:wstring

This directive applies to data members of type string as well as to containers, such as structures, classes, and exceptions. It changes the default mapping for strings from std::string to std::wstring. (See Section 6.6.1.)

cpp:header-ext

This global directive allows you to use a file extension for C++ header files other than the default .h extension. (See Section 6.16.)

cpp:include

This global directive allows you inject additional #include directives into the generated code. This is useful for custom types. (See Section 6.7.4.)

cpp:virtual

This directive applies to classes. If the directive is present and a class has base classes, the generated C++ class derives virtually from its bases; without this directive, slice2cpp generates the class so it derives non-virtually from its bases.
This directive is useful if you use Slice classes as servants and want to inherit the implementation of operations in the base class in the derived class. For example:
class Base {
    int baseOp();
};

["cpp:virtual"]
class Derived extends Base {
    string derivedOp();
};
The metadata directive causes slice2cpp to generate the class definition for Derived using virtual inheritance:
class Base : virtual public Ice::Object {
    // ...
};

class Derived : virtual public Base {
    // ...
};
This allows you to reuse the implementation of baseOp in the servant for Derived using ladder inheritance:
class BaseI : public virtual Base {
    Ice::Int baseOp(const Ice::Current&);
    // ...
};

class DerivedI : public virtual Derived,
                 public virtual BaseI {
    // Reuse inherited baseOp()
};
Note that, if you have data member in classes and use virtual inheritance, you need to take care to correctly call base class constructors if you implement your own one-shot constructor. For example:
class Base {
    int baseInt;
};

class Derived extends Base {
    int derivedInt;
};
The generated one-shot constructor for Derived initializes both baseInt and derivedInt:
Derived::Derived(Ice::Int __ice_baseInt,
                 Ice::Int __ice_derivedInt)
    : M::Base(__ice_baseInt),
      derivedInt(__ice_derivedInt)
{
}
If you derive your own class from Derived and add a one-shot constructor to your class, you must explicitly call the constructor of all the base classes, including Base. Failure to call the Base constructor will result in Base being default-constructed instead of getting a defined value. For example:
class DerivedI : public virtual Derived {
public:
    DerivedI(int baseInt, int derivedInt, const string& s)
        : Base(baseInt), Derived(baseInt, derivedInt), _s(s)
    {
    }

private:
    string _s;
};
This code correctly initializes the baseInt member of the Base part of the class. Note that the following does not work as intended and leaves the Base part default-constructed (meaning that baseInt is not initialized):

class DerivedI : public virtual Derived {
public:
    DerivedI(int baseInt, int derivedInt, const string& s)
        : Derived(baseInt, derivedInt), _s(s)
    {
        // WRONG: Base::baseInt is not initialized.
    }

private:
    string _s;
};

Table of Contents Previous Next
Logo