devxlogo

Using Prototypes Rather than RTTI

Using Prototypes Rather than RTTI

In some situations, you may want a certain data member of two different objects to be identical. For example, suppose you are writing a graphics program that will render a 3D scene, you need to store material properties (such as reflection coefficients) for different objects in the scene. The simplest way to do this to define an abstract base class called Material that is derived from to define different concrete classes of materials.

 class Material{..   // one or more pure virtual functions};class MaterialType1 : public Material{..  // a concrete class};class MaterialType2 : public Material{..  // a concrete class};

Now objects may contain a pointer to a material object:

 class Object{private:Material *mtrl;..public:void SetMaterial(Material *m) { mtrl = m;}Material *GetMaterial() const { return mtrl; }..};

Suppose you want two objects to have exactly the same material properties, but you don’t want to share the material object between them. The first object’s material is set as follows:

 Object obj1, obj2;obj1.SetMaterial(new MaterialType1);.. // set various material properties

To set the material of obj2 to the same material as of obj1, you can’t use this code:

 obj2.SetMaterial(new Material(obj1.GetMaterial()));

This is because Material is an abstract class and cannot be instantiated with ‘new’. You need to know the dynamic type of obj1’s material. Using run-time type information (RTTI) is an inelegant and inflexible solution:

 if (typeid(obj1.GetMaterial()) == typeid(MaterialType1))  obj2.SetMaterial(new MaterialType1(obj1.GetMaterial());else if (typeid(obj1.GetMaterial() == typeid(MaterialType2))  obj2.SetMaterial(new MaterialType2(obj1.GetMaterial());

Not only does the caller need to know the dynamic type of the material, but if you now add other classes to the Material class hierarchy, the if-statement will need to be changed to accommodate the new types as well. This is clearly not desirable.
A better way is to use the Prototype design pattern. First, define a Clone function for each class in the Material hierarchy:

 class Material{public:virtual Material *Clone() const = 0;..};class MaterialType1 : public Material{public:virtual MaterialType1 *Clone() const{ return new MaterialType1(*this); }..};class MaterialType2 : public Material{public:virtual MaterialType2 *Clone() const{ return new MaterialType2(*this); }..};

To add a new class to this hierarchy, just make sure that it defines the Clone function. To set obj2’s material properties to the same as obj1’s, simply say:

 obj2.SetMaterial(obj1.GetMaterial()->Clone());

The existing material object in obj1 functions as a prototype, replicating itself and returning the result. The caller need never know the dynamic type of the material, and you don’t need to change this code if the Material class hierarchy changes.

devxblackblue

About Our Editorial Process

At DevX, we’re dedicated to tech entrepreneurship. Our team closely follows industry shifts, new products, AI breakthroughs, technology trends, and funding announcements. Articles undergo thorough editing to ensure accuracy and clarity, reflecting DevX’s style and supporting entrepreneurs in the tech sphere.

See our full editorial policy.

About Our Journalist