C++ Builder

La Isla Bonita



How to get Virtual Constructor behavior in C++
How to get Virtual Constructor behavior in C++


Description

Virtual constructors, in languages such as Delphi, are useful, for example, to clone shape objects. Because the C++ language hasn't got virtual constructors, we have to do a little bit of extra work to get a similar behavior. This example shows how to implement the behavior of virtual constructors in C++ through pure virtual functions.

VirtualConstructors.cpp

#include <vcl.h>
#pragma hdrstop

#include "VirtualConstructor.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;

class Shape
{
  public:
    Shape()
    {
        ShowMessage("Shape CONSTRUCTOR");
    }
    virtual Shape* Clone() = 0;            // pure virtual function
    virtual Shape* Create() = 0;           // pure virtual function
    virtual Shape* Create( double r ) = 0; // pure virtual function
    virtual void   Draw() = 0;             // pure virtual function
    virtual double GetRadius() = 0;        // pure virtual function
    virtual ~Shape()                       // virtual destructor
	{}
	
};

Shape* Shape1;
Shape* Shape2;
Shape* Shape3;

class Circle : public Shape
{
  private:
    double radius;

  public:
    Circle()
    {
        ShowMessage("Circle DEFAULT CONSTRUCTOR");
    }
    Circle( double r )
    {
        ShowMessage("Circle ONE ARG CONSTRUCTOR");
        radius = r;
    }
    Shape* Clone()
    {
        // Copy the state of this into the object
        // created of here.
        // (using the Circle's copy constructor)
        return new Circle( *this );
    }
    Shape* Create()
    {
        //Create an Object of the class Circle
        //using the default constructor
        return new Circle();
    }

    Shape* Create( double r )
    {
        //Create an Object of the class Circle
        //using the default constructor
        return new Circle( r );
    }

    void SetRadius( double r )
    {
       radius = r;
    }

    double GetRadius()
    {
       return radius;
    }

    void Draw()
    {
       //Draw here
    }
    ~Circle()
    {
        ShowMessage("Circle DESTRUCTOR");
    }
};


Shape* CloneShapeVirtually( Shape& S )
{
  //Clone the object that is passed on to this function
  //by reference.
  //This function expects a reference to an object
  //and it works for any Shape (Circle, Rectangle, etc.)
  //This function acts as a Virtual constructor
  return S.Clone();
}

Shape* CreateDefaultShapeVirtually( Shape& S )
{
  //This function expects a reference to an object
  //and it works for any Shape (Circle, Rectangle, etc.)
  //This function acts as a Virtual constructor
  return S.Create();
}

Shape* CreateShapeVirtually( Shape& S )
{
  //This function expects a reference to an object
  //and it works for any Shape (Circle, Rectangle, etc.)
  //This function acts as a Virtual constructor
  return S.Create( 1.0 );
}

void DestroyShape( Shape* S )
{
  delete S;
}

void __fastcall TForm1::Button1Click(TObject *Sender)
{
//
  Circle oCircle( 99.0 );                  //Create a Circle Object

  //Clone of oCircle
  Shape1 = CloneShapeVirtually( oCircle );

  //New object created with Circle's default constructor
  //thus radius is not initialized
  Shape2 = CreateDefaultShapeVirtually( oCircle );

  //New object created from Circle's one argument constructor
  //thus its radius is initialized.
  Shape3 = CreateShapeVirtually( oCircle );

  //TEST
  //ShowMessage( "oCircle radius = " + FloatToStr( oCircle.GetRadius()) );

  //Get the value of data member radius for
  //(1) the Cloned object created with the copy constructor,
  //(2) the Created object created with the default constructor,
  //(3) the Created object created with one-argument constructor.
  ShowMessage( "Cloned Object: Shape1->GetRadius() = "
                + FloatToStr( Shape1->GetRadius() )
                + "\n"
                "Default Object: Shape2->GetRadius() = "
                + FloatToStr( Shape2->GetRadius() )
                + "\n"
                "Object: Shape3->GetRadius() = "
                + FloatToStr( Shape3->GetRadius() )  );

  DestroyShape( Shape1 );
  DestroyShape( Shape2 );
  DestroyShape( Shape3 );  
}

__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}

VirtualConstructors.h

#ifndef VirtualConstructorH
#define VirtualConstructorH

#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>

//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:	// IDE-managed Components
        TButton *Button1;
        void __fastcall Button1Click(TObject *Sender);
private:	// User declarations
public:		// User declarations
        __fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif

Homepage

Copyright © 1997-2002 Rodolfo A. Frino. All rights reserved.