5

Possible Duplicate:
Calling virtual functions inside constructors

I have a class Shape and its subclass Sphere :

//Shape : 

class Shape
{
    public:
        Shape(const string& name);
        virtual ~Shape();

        virtual string getName();

    protected:

        string mName;

};

Shape::Shape(const string& name) : mName(name)
{
   /*Some stuff proper to Shape*/

   /*Some stuff proper to subclass (sphere)*/

   /*Some stuff proper to Shape*/
}

Shape::~Shape(){}

string Shape::getName(){ return mName; }


//Sphere :

class Sphere : public Shape
{
    public:
        Sphere(const string& name, const float radius);
        virtual ~Sphere();

        virtual string getRadius();

    protected:

        float mRadius;
}

Sphere::Sphere(const string& name, const float radius) : Shape(name), mRadius(radius)
{
   /*Some stuff*/
}

Sphere::~Sphere(){}

float Sphere::getRadius(){ return mRadius; }

Now, how can I handle the subclass stuff in the Shape constructor ? I could resort to template method pattern but I would be forced to call a pure virtual function in the constructor; I tried and the compiler didn't like it

Edit :

I chose to move the constructor stuff in a new method, 'init', and the virtual method will be 'subInit':

//Shape : 

class Shape
{
    public:
        Shape(const string& name);
        virtual ~Shape();

        virtual string getName();

        virtual void init();

    protected:

        string mName;

        virtual void subInit() = 0;

};

Shape::Shape(const string& name) : mName(name){}

Shape::~Shape(){}

string Shape::getName(){ return mName; }

void Shape::init()
{
   /*Some stuff proper to Shape*/

   /*Some stuff proper to subclass (sphere)*/
   /*Call to the pure virtual function subInit*/

   subInit();

   /*Some stuff proper to Shape*/
}

//Sphere : 

class Sphere : public Shape
{
    public:
         Sphere(const string& name, const float radius);
         virtual ~Sphere();

         virtual string getRadius();

        protected:

            float mRadius;

            void subInit();
    }

    Sphere::Sphere(const string& name, const float radius) : Shape(name),mRadius(radius)
    {}

    Sphere::~Sphere(){}

    float Sphere::getRadius(){ return mRadius; }

    Sphere::subInit()
    {
       /*Some stuff previously in the constructor*/
    }

It's basicaly the template method pattern

The client will write :

Shape* sphere = new Sphere();
sphere->init();

Then I have my answer : its impossible to apply this pattern in the constructor, at least in C++

Community
  • 1
  • 1
codablank1
  • 6,055
  • 5
  • 19
  • 29
  • 2
    A very good thing to keep in mind in these situations is the old chant "during construction, virtual methods aren't". Because in the constructor of the base class, the object is still considered to be of that base type, and so calls to virtual functions will resolve to the version implemented for that base class. This is seldom what you want, and If it is pure virtual in the base class, it is definitely not what you want. – Agentlien Jan 27 '13 at 21:23
  • @Heisenbug : calling virtual function in the constructor is just a possibility; if there is another better architecture, I'm open to it – codablank1 Jan 27 '13 at 21:28
  • Do I understand correctly that you want new Shape("sphere") to return an object that's actually of type Sphere? I don't know if that's possible, but if so it'll get you into a ton of trouble any time you try to put a shape on the heap and mRadius overlaps the next variable you declare. – dspeyer Jan 27 '13 at 21:35
  • Generally, one doesn't do subclass operations in the base class. Any reasons why you can't do all of your Sphere construction in its constructor? – radical7 Jan 27 '13 at 21:37
  • @radical7 : because there would be a lot of stuff common to all subclasses' constructors I would have to copy/paste each time – codablank1 Jan 27 '13 at 21:41
  • @dspeyer : hum maybe the solution relies on factory method – codablank1 Jan 27 '13 at 21:42
  • @codablank1 The "stuff" that's common is what's supposed to go in the base class constructor. Subclass specific should only occur in subclasses. If your doing lots of copy-n-paste, your design may be flawed. – radical7 Jan 27 '13 at 21:58
  • @radical7 : well, things are interleaved, that's the source of the problem – codablank1 Jan 27 '13 at 22:00

1 Answers1

1
Shape::Shape(const string& name) : mName(name)
{
   /*Some stuff proper to Shape*/

   /*Some stuff proper to subclass (sphere)*/

   /*Some stuff proper to Shape*/
}

The stuff proper to the subclass can't run until the subclass exists, so it should go in the constructor of the subclass. The later stuff can then go in a function called by the subclass constructor.

Shape::Shape(const string& name) : mName(name)
{
   /*Some stuff proper to Shape*/
}

void Shape::finishConstruction()
{   
   /*Some stuff proper to Shape*/
}

Sphere::Sphere(const string& name, const float radius)
: Shape(name), mRadius(radius)
{
    /*Some stuff proper to subclass (sphere)*/

    finishConstruction();
}
Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521
  • Is Sphere::finishConstruction supposed to be Shape::finishConstruction? – dspeyer Jan 27 '13 at 21:53
  • that's a so-so solution : It won't enforce the writer of a new subclass to put finishconstruction() at the end of the constructor; but I guess it's still better then than my first idea – codablank1 Jan 27 '13 at 21:58