C++ Programming

Blog about C++ and Zeus-Framework programming.

Inline methods are very useful for to tune your code for performance. Placing the keyword inline before a method tells the compiler to copy the code instead of calling the method over the stack. The effect is similar like a macro, but doesn't need any preprocessor. Anyway this is not a must to the compiler. He will decide himself if he wants and is able to call a method as inline.

There is also a disadvantage using inline: The binary code is getting bigger and has lots of redundancy. Therefore using inline makes sence for small methods, like delegating or simply getting or setting values to a class, without any checks.

Note that inline can be used only in header files!!

Inline methods might be used also for virtual methods. Some programmers see no sence doing this. But because this is just a succestion for the compiler he will even call the virtual method inline if he can. Normaly he won't because of the polymorphism.

Following example shows the use of inline methods:


class TTest : public TZObject
{
  public:
    ...
    inline Int getValue() const 
    { return m_iValue; }
    
    inline void setValue(Int iValue) 
    { m_iValue = iValue; }
  
    Int getInverseValue() const;  
  private:
    Int m_iValue;
};

//Inline can be used even outside of the 
// class declaration But it must stay in 
// the header file
inline Int TTest::getInverseValue() const
{
  return -m_iValue;
}

Some times a template class must have a member variable of type <T>. Following questions are rising up: How do I initialise the member variable, if I don't know if it is a pointer, primitive datatype or even an other object?

Using the memset function will cause memory leaks, if the template is used for complex objects, creating member pointers in their constructors. The member pointer will be set to NULL.

Most C++ compilers has an undocumented function to initialize even primitive datatypes using their standard constructor T(). This feature is used in following example:


template <class TKeyType, class T> class TMap
 : public TZObject, public IMap<TKeyType, T>
{
  public:
    TMap() : m_tEmpty(T())
    {
      // DO NOT USE MEMSET. 
      // This causes memory leaks on complex objects
      //memset(&m_tEmpty, 0, sizeof(T));
    }
  
  private:
    ///Empty item
    T m_tEmpty;
};

If your compiler is not supporting this feature, there is an other way how to solve this problem. We are writing a static method returning a static local variable of the type <T>. The static variable will be initialized by the compiler with 0 (zero) for primitive datatypes.


template <class TKeyType, class T> class TMap
 : public TZObject, public IMap<TKeyType, T>
{
  public:
    TMap() : m_tEmpty(getDefaultEmpty())
    {
      // DO NOT USE MEMSET. 
      // This causes memory leaks on complex objects
      //memset(&m_tEmpty, 0, sizeof(T));
    }
  
  private:
    ///Empty item
    T m_tEmpty;

    static const T& getDefaultEmpty()
    {
        static const T Empty; // is initialized by compiler
        return Empty;
    }
};

Still this will fail if we want to store references.

The Zeus-Framework uses STL as base library. Many classes or STL are wrapped in a Zeus container class. The reason to this wrapping is the interface concept. The main reason why we need those wrappers is given at Interfaces - Interface Methods.