Simplify Two Phase Constructor in Symbian

in

As we know that every time when we declare a class with initial C and derive from CBase we have to provide second phase constructor (NewL and NewLC ) in genral for such classes. There is a way which will give some flexibility to reduce to write NewL and NewLC evey time when you derive a class from CBase and need second phase constructor.

//Define a class which is base class like this:

//Phasebase.h base class for all classes derived from CBase
//and has second phase constructor
#include <e32def.h>
#include <e32base.h>

template <class T>
class CPhaseBase : public CBase
{
public:
  static T* NewL()
          {
          T* self = new (ELeave) T();
        CleanupStack::PushL(self);
        self->ConstructL();
        CleanupStack::Pop(self);
        return self;
          }
          static T* NewLC()
        {
        T* self = new (ELeave) T();
        CleanupStack::PushL(self);
        self->ConstructL();
        return self;
        }
public:
  //All classes derive from CPhasebase must implement   this function
  virtual void ConstructL() = 0 ;
};

and here is an example class which uses this class as base class

//UsePhase.h
#include "Phasebase.h"
class CUsePhase;
class CUsePhase : public CPhaseBase<CUsePhase>
{
private:
        HBufC* iMyBuf;
public:
        void ConstructL();
public:
        CUsePhase()
                {
                }
        ~CUsePhase();
};

//UsePhase.cpp
#include "UsePhase.h"

#define KMaxLength    50

void CUsePhase :: ConstructL()
{
        iMyBuf = HBufC::NewL(KMaxLength);
}

CUsePhase ::~CUsePhase()
{
        if(iMyBuf)
        {
        delete iMyBuf;
        iMyBuf = NULL;
        }
}

To use the class you simply need to do:

CUsePhase *iMyPhase;
iMyPhase = CUsePhase::NewL();

This will call templated NewL of CPhaseBase class and internally calls ConstructL of CUsePhase which is second phase constructor.

Note: if you want parameterized constructors then you must override NewL and NewLC and then from that has to call NewL of CPhaseBase.

:-)
Bhuvan.


Simplify Two Phase Constructor in Symbian

Thanks for the valuable information. Using the trick does cuts down the development time . Girish

Simplify Two Phase Constructor in Symbian

This design forces the default constructor of the CUsePhase class to be public, which should be avoided as users should not be allowed to create objects of this class on stack. ('C' type classes).

-  Vink

Simplify Two Phase Constructor in Symbian

For every class that is derived from the class template, code for a new class type will be generated leading to increased executable size.

Another way of reducing redundant code with out increasing the executable size is to use Macros for the function declarations and definitions.

Simplify Two Phase Constructor in Symbian

I want to comment a small detail in the code listing:

CUsePhase ::~CUsePhase()
{
       if(iMyBuf)
       {
       delete iMyBuf;
       iMyBuf = NULL;
       }
}

There are two things which don't make sense. All you need there is a single row like this:

CUsePhase ::~CUsePhase()
       {
       delete iMyBuf;
       }

...because:

1) In C++ you are allowed to delete NULL. Members of C-based classes are always initialized to NULL during construction. You don't need the IF.

2) There's no need to set the member to NULL after deletion in destructor.

Simplify Two Phase Constructor in Symbian

>>>> 1) In C++ you are allowed to delete NULL. To be more particulare: Not in C++. -----> In Symbian C++...:)

Simplify Two Phase Constructor in Symbian

And to be perfectly accurate, applying delete to a null pointer is valid in C++ as described in the ISO/IEC standard. It results in a no-op.

.f

Simplify Two Phase Constructor in Symbian

if you want parameterized constructors then you must override NewL and NewLC and then from that has to call NewL of CPhaseBase.

This won't work if you have to initialise member references of your class, as they need to be passed in to the class's constructor.

Also you wouldn't be overriding NewL/NewLC from CPhaseBase as CPhaseBase functions take no parameters and therefore have different function signatures. And hey, they're not even virtual anyway.

Simplify Two Phase Constructor in Symbian

Yeah, you would be overloading.

Simplify Two Phase Constructor in Symbian

This design forces the default constructor of the CUsePhase class to be public, which should be avoided as users should not be allowed to create objects of this class on stack. ('C' type classes).

Re: Simplify Two Phase Constructor in Symbian

You can simply make the constructor "protected".

But the provided solution will only be utilized for small subset of the problem. Because it cannot be used for
* Parametrized constructors.
* Exporting NewL and NewLC.
* These NewL functions are inlined. So will be slightly rigid in design (barrier for BC).

So I think a slightly better solution would be to use macros. Instead of creating the template class.

Re: Simplify Two Phase Constructor in Symbian

Something like...

#define declareNewLC(T) static T* NewLC()
#define defineNewLC(T) T* T::NewLC() \
        {\
        T* self = new (ELeave) T();\
        CleanupStack::PushL(self);\
        self->ConstructL();\
        return self;\
        }\

class CMyTest
        {
        public:
                IMPORT_C declareNewLC(CMyTest);
       
        private:
                CMyTest(){};
                void ConstructL(){};
        };

EXPORT_C defineNewLC(CMyTest);

Re: Simplify Two Phase Constructor in Symbian

this information is enough to understand the 2phase construction.
thanks.