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
VirtualConstructors.h
Copyright © 1997-2002 Rodolfo A. Frino. All rights reserved.
#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)
{
}
#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