FAQ 27.10 Given a pointer to an ABC, how can the class of the referent be found?

graphics/new_icon.gif

This is an idea that should be avoided.

The typical reason for trying to find an object's class is to use an algorithm that depends on the object's class. If the algorithm varies depending on the derived class, then the algorithm should be a virtual member function in the class hierarchy. If the algorithm is structurally the same for all derived classes but has little pieces that differ depending on the derived class, then the little pieces should be virtual member functions in the class hierarchy. This technique lets derived classes select the ideal algorithm or algorithm fragments without any additional branch points in the software (see FAQ 27.04).

For example, finding the minimal distance to a mouse click requires different algorithms for circles, squares, lines, and so forth. One might be tempted to write non-OO code such as the following (pretend Position, Shape, Circle, and so forth, are classes).

 int dist_BAD_FORM(Shape& s, Position mouse) throw() {   Circle* cp = dynamic_cast<Circle*>(&s);   Square* sp = dynamic_cast<Square*>(&s);   Line*   lp = dynamic_cast<Line*>(&s);   if (cp != NULL) {     //find the distance from mouse to the Circle, *cp   } else if (sp != NULL) {     //find the distance from mouse to the Square, *sp   } else if (lp != NULL) {     //find the distance from mouse to the Line, *lp   } } 

One problem with this non-OO technique is that adding a new derived class requires working user code to be modified by adding a new else if section. Besides the obvious concern that changing working user code may break it, in large systems it is difficult to find all the places that need to be changed, and in very large systems there is typically a scheduling problem coordinating the changes in diverse teams of developers. In one organization the ripple effect was so bad that it took nine months to add a new gizmo to the system (this was mainly due to a scheduling concern since the entire system was huge in excess of 10 million lines of non-OO code). After a proper OO design of selected subsystems, the same sorts of additions are now routinely done by a single person in a single day.[1]

[1] "Lessons Learned from the OS/400 OO Project,"Communications of the ACM.1995;38(10):54 64.

A proper OO design would move the function dist() into the Shape rather than moving the Shape into the function dist().

 class Position { }; class Shape { public:   virtual ~Shape() throw();   virtual void draw() const throw() = 0;   virtual int  dist(Position mouse) const throw() = 0; }; Shape::~Shape() throw() { } class Circle : public Shape { public:   virtual void draw() const throw();   virtual int dist(Position mouse) const throw(); }; void Circle::draw() const throw() { /*draw a Circle*/ } int Circle::dist(Position mouse) const throw() { /*find the distance from mouse to this Circle*/ } class Square : public Shape { public:   virtual void draw() const throw();   virtual int dist(Position mouse) const throw(); }; void Square::draw() const throw() { /*draw a Square*/ } int Square::dist(Position mouse) const throw() { /*find the distance from mouse to this Square*/ } 

The OO solution greatly reduces the amount of code that needs to be modified when a new class is added. A little extra design work pays large dividends.



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