FAQ 20.12 What is a good way to provide intuitive, multiple constructors for a class?

Use the named constructor idiom.

Constructors always have the same name as the class, so the only way to differentiate between the various constructors of a class is by the parameter list. If there are numerous overloaded constructors, the differences can become somewhat subtle and subject to error.

With the named constructor idiom, all the constructors are declared as private: or protected:, and the class provides public: static member functions that return an object. These static member functions are the so-called named constructors. In general there is one such static member function for each different way to construct an object.

For example, consider a Point class that represents a position on a plane. There are two different constructors corresponding to the two common ways to specify a point on a plane: rectangular coordinates (X and Y) and polar coordinates (radius and angle). Unfortunately the parameters for these two coordinate systems are the same (two numbers), so the overloaded constructors would be ambiguous. For example, if someone created a point using Point(5.7, 1.2), the compiler wouldn't know which coordinate system (that is, which constructor) to use.

One way to solve this ambiguity is to use the named constructor idiom:

 #include <cmath> // To get sin() and cos() #include <iostream> using namespace std; class Point { public:   static Point rectangular(float x, float y) throw();   // Rectangular coordinates   static Point polar(float radius, float angle) throw();   // Polar coordinates   // These static members are the so-called named constructors   // ... private:   Point(float x, float y) throw();  // Rectangular coordinates   float x_, y_; }; inline Point::Point(float x, float y) throw() : x_(x), y_(y) { } inline Point Point::rectangular(float x, float y) throw() { return Point(x, y); } inline Point Point::polar(float radius, float angle) throw() { return Point(radius*cos(angle), radius*sin(angle)); } 

Now the users of Point have a clear and unambiguous syntax for creating Points in either coordinate system:

 int main() {   Point a = Point::rectangular(5.7, 1.2); // Obviously rectangular   Point b = Point::polar(5.7, 1.2);       // Obviously polar } 

Note that the constructor(s) must be in the protected: section, not the private: section, if the class will have derived classes.

The Named Constructor Idiom can also be used to make sure objects are always created via new. In this case the public: static member functions (the named constructors) should allocate the object via new and should return a pointer to the allocated object.



C++ FAQs
C Programming FAQs: Frequently Asked Questions
ISBN: 0201845199
EAN: 2147483647
Year: 2005
Pages: 566
Authors: Steve Summit

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net