Thursday, July 21, 2011

Why don't we have virtual constructors?

A virtual call is a mechanism to get work done given partial information. In particular, "virtual" allows us to call a function knowing only an interfaces and not the exact type of the object. To create an object you need complete information. In particular, you need to know the exact type of what you want to create. Consequently, a "call to a constructor" cannot be virtual.
Techniques for using an indirection when you ask to create an object are often referred to as "Virtual constructors". For example, see TC++PL3 15.6.2.
For example, here is a technique for generating an object of an appropriate type using an abstract class:



struct F 
{
  // interface to object creation functions
  virtual A* make_an_A() const = 0;
  virtual B* make_a_B() const = 0;
};

void user(const F& fac)
{
  A* p = fac.make_an_A(); // make an A of the appropriate type
  B* q = fac.make_a_B(); // make a B of the appropriate type
  // ...
}

struct FX : F 
{
  A* make_an_A() const { return new AX(); } // AX is derived from A
  B* make_a_B() const { return new BX(); } // BX is derived from B
};

struct FY : F 
{
  A* make_an_A() const { return new AY(); } // AY is derived from A
  B* make_a_B() const { return new BY(); } // BY is derived from B
};

int main()
{
  FX x;
  FY y;
  user(x); // this user makes AXs and BXs
  user(y); // this user makes AYs and BYs

  user(FX()); // this user makes AXs and BXs
  user(FY()); // this user makes AYs and BYs
  // ...
}


This is a variant of what is often called "the factory pattern". The point is that user() is completely isolated from knowledge of classes such as AX and AY.

No comments:

Post a Comment