15.12 ABSTRACT CLASSES IN C


15.12 ABSTRACT CLASSES IN C++

In Chapter 3, we pointed out the importance of abstract classes in object-oriented programming. This section expands on that discussion for the case of C++. As a follow-up to the earlier discussion, consider the class hierarchy of Figure 15.9 in which the class Shape is abstract. We will use the base class Shape to lend organization to the shape hierarchy; this we will accomplish by making Shape a repository of all things common to all the concrete shape classes.

click to expand
Figure 15.9

Let's say that we want each of the concrete shapes to have the following two functions.

       double area( );       double circumference(); 

and that we wish for the hierarchy to exhibit polymorphic behavior with respect to these two functions. We'll therefore "deposit" these functions in Shape and, to achieve polymorphism with respect to these functions, declare them virtual:

 class Shape { public:     virtual double area();     virtual double circumference();     //.... }; 

But now we run into a problem: C++ syntax demands that a function be defined in the class in which it is declared virtual (see Section 15.7.1). However, it makes no sense to define these two functions for Shape. While we need Shape to tie together all the other classes in the shape hierarchy, this class by itself is a purely abstract concept. We'd never make objects of type Shape. (That's the reason the class does not even need a constructor.)

C++ gives us a way out of this dilemma: declare the functions area() and circumference() to be pure virtual functions in the Shape class. A virtual function is "made pure" by the initializer ‘=0’ shown below:

     class Shape {     public:       virtual double area() = 0;       virtual double circumference() = 0;       //....     }; 

Now the functions area() and circumference() will again be able to act as interfaces to the functions of the same names in the derived classes even though these functions are not defined for the base class Shape. Therefore, now we can write code like

      Shape* shapes [ 3 ];      shapes [0] = new Circle ( ... );      shapes [1] = new Rectangle ( ..... );      shapes [2] = new Rectangle ( ..... );      double total_area = 0;      for (int i=0; i < 3; i++ )        total_area += shapes[i]–>area();                                                        //(A) 

Note polymorphism in action in line (A). At run time, the system will be able to figure out which area() function to invoke for what Shape object. For the Shape object shapes[0], the area() defined for the Circle class will be invoked. For the other two Shape objects, the area() function defined for the Rectangle class will be invoked. The following source code shows this example more fully:

 
//AbstractShape.cc #include <iostream> using namespace std; class Shape { public: virtual double area() = 0; virtual double circumference () = 0; }; class Circle : public Shape { protected: double r; static double PI; public: Circle () { r = 1.0; } Circle( double r ) { this–>r = r; } double area() { return PI*r*r; } double circumference() { return 2 * PI * r; } double getRadius() { return r;} }; double Circle::PI = 3.14159265358979323846; class Rectangle : public Shape { double w, h; public: Rectangle() { w=0.0; h = 0.0; } Rectangle (double w, double h) { this–>w = w; this–>h = h; } double area() { return w * h; } double circumference () { return 2 * (w + h); } double getWidth() { return w; } double getHeight() { return h; } }; int main() { Shape* shapes [ 3 ]; shapes [0] = new Circle (2.0); shapes [1] = new Rectangle (1.0, 3.0); shapes [2] = new Rectangle (4.0, 2.0); double total_area = 0; for (int i=0; i < 3; i++) total_area += shapes [i]–>area(); cout << "Total area = " << total_area << endl; return 0; }

A C++ class is abstract if it has at least one virtual function that is pure. A pure virtual function is also called an abstract method or an abstract function

A pure virtual function that is not defined in a derived class remains a pure virtual function. So, in such a case, the derived class is also an abstract class. This, as was pointed out in Chapter 3, allows us to build an implementation in stages. To illustrate, consider the hierarchy of Figure 15.10. The source code shown below is a partial implementation of this hierarchy. We now include an abstract class Polygon, which is abstract because Polygon is derived from the abstract class Shape and because it does not provide implementations for the abstract methods of Shape. The class Polygon includes two data members, numVertices and starShaped, that are inherited by the classes derived from Polygon. We now also include a class CurvedShape, again abstract for the same reasons that Polygon is abstract, and for the additional reason that it includes a pure virtual function PolygonalApprox(). In computer graphics, curved shapes often have associated with them polygonal approximations. The method polygonalApprox() is supposed to return a polygonal approximation to a curved Shape.

click to expand
Figure 15.10

 
//AbstractShapeIncremental.cc #include <iostream> using namespace std; class Shape { public: virtual double area() = 0; virtual double circumference() = 0; }; class Polygon : public Shape { protected: int numVertices; bool starShaped; }; class CurvedShape : public Shape { public: virtual void polygonalApprox() = 0; }; class Circle : public CurvedShape { protected: double r; static double PI; public: Circle() { r = 1.0; } Circle(double r) { this–>r = r; } double area() { return PI*r*r; } double circumference() { return 2 * PI * r; } double getRadius() {return r;} void polygonalApprox() { cout << "polygonal approximation code goes here" << endl; } }; double Circle::PI = 3.14159265358979323846; class Rectangle : public Polygon { double w, h; public: Rectangle() { w=0.0; h = 0.0; numVertices = 0; starShaped = true; } Rectangle (double w, double h) { this>w = w; this>h = h; numVertices = 4; starShaped = true; } double area() { return w * h; } double circumference () { return 2 * (w + h); } double getWidth() { return w; } double getHeight() { return h; } }; int main() { Shape* shapes [ 3 ]; shapes [0] = new Circle (2.0); shapes [1] = new Rectangle (1.0, 3.0); shapes [2] = new Rectangle (4.0, 2.0); double total_area = 0; for (int i=0; i < 3; i++) total_area += shapes [i]–>area(); cout << "Total area = " << total_area << endl; return 0; }




Programming With Objects[c] A Comparative Presentation of Object-Oriented Programming With C++ and Java
Programming with Objects: A Comparative Presentation of Object Oriented Programming with C++ and Java
ISBN: 0471268526
EAN: 2147483647
Year: 2005
Pages: 273
Authors: Avinash Kak

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