FAQ 5.13 How can old code call new code?

graphics/new_icon.gif

Through the magic of polymorphism, inheritance, and dynamic binding.

In the traditional software paradigm, it is easy for new code to call old code using subroutine libraries. However, it is difficult for old code to call new code (unless the old code is modified so that it knows about the new code, in which case the old code is no longer old).

With object orientation, old polymorphic functions can dynamically bind to new server code. An object of a derived class can be passed to and used by an existing polymorphic function without modifying the polymorphic function.

When compiling a polymorphic function, it is as if the compiler looks forward in time and generates code that will bind to all the classes that will ever be added. For example, a graphical drawing package might deal with squares, circles, polygons, and various other shapes. Most of the drawing package's services deal with generic shapes rather than a particular kind of shape, like a square (for example, "if a shape is selected by the mouse, the shape is dragged across the screen and placed in a new location"). Polymorphism and dynamic binding allow the drag-and-drop code to work correctly regardless of the kind of shape being manipulated. To implement this approach, class Shape would declare virtual functions for drawing and moving. The derived classes would represent the various kinds of shapes: Square, Circle, and so forth.

 #include <iostream> using namespace std; class Shape { public:   Shape(int x, int y)             throw();   virtual ~Shape()                throw();   virtual void draw() const       throw() = 0;   virtual void move(int x, int y) throw() = 0; protected:   int x_, y_;   void operator= (const Shape& s) throw();   Shape(const Shape& s) throw(); }; Shape::Shape(int x, int y) throw() : x_(x) , y_(y) { } Shape::Shape(const Shape& s) throw() : x_(s.x_) , y_(s.y_) { } Shape::~Shape() throw() { } void Shape::operator= (const Shape& s) throw() {   x_ = s.x_;   y_ = s.y_; } void dragAndDrop(Shape& s) throw()                   <-- 1 {   s.move(42,24);                                     <-- 2   s.draw();                                          <-- 3 } class Square : public Shape { public:   Square(int x, int y, int width) throw();   virtual void draw() const       throw();   virtual void move(int x, int y) throw(); protected:   int width_; }; Square::Square(int x, int y, int width) throw() : Shape(x,y) , width_(width) { } void Square::draw() const throw() { cout << "Square::draw\n"; } void Square::move(int x, int y) throw() {   x_ = x;   y_ = y;   cout << "Square::move\n"; } class Circle : public Shape { public:   Circle(int x, int y, int radius) throw();   virtual void draw() const        throw();   virtual void move(int x, int y)  throw(); protected:   int radius_; }; Circle::Circle(int x, int y, int radius) throw() : Shape(x,y) , radius_(radius) { } void Circle::draw() const throw() { cout << "Circle::draw\n"; } void Circle::move(int x, int y) throw() {   x_ = x;   y_ = y;   cout << "Circle::move\n"; } int main() {   Square s = Square(5, 20, 3);   Circle c = Circle(10, 15, 7);   dragAndDrop(s);   dragAndDrop(c); } 

(1) A polymorphic function

(2) Dynamic binding calls the "right" code

(3) (as if the compiler predicted the future)

This dragAndDrop(Shape&) function properly invokes the right member functions from class Square and Circle, even though the compiler didn't know about Square or Circle when it was compiling dragAndDrop(Shape&). Here is the output of this program.

 Square::move Square::draw Circle::move Circle::draw 

Suppose the function dragAndDrop(Shape&) is compiled on Tuesday, and a new kind of shape say a Hexagon is created on Wednesday. dragAndDrop(Shape&) works with a Hexagon even though the Hexagon class didn't exist when dragAndDrop(Shape&) was compiled.



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