Barber+-+Veal

toc

Source Code Project 3

=//__Project Overview__//= This program is an example of Object Oriented Programming (OOP) using abstract base types, derived types, inheritance, polymorphism, upcasting and virtual functions. The inputs are preset for ease of demonstration. We will demonstrate these features of OOP with a relatively simple program that could actually be converted in to an iphone application for landscapers. We wanted to write a program that has a “real world” use while demonstrating what we have learned throughout OOP I and II. The program will determine area, perimeter, and volume of a shape. Additional shapes could easily be added to expand its usefulness. For example, if you have a flower bed of some set dimension, you will be able to use this program to determine the area, perimeter, and volume of the shape to assist in determining the amount of soil/potting, straw/mulch, and edging it will take to build the flower bed. No more multiple trips to Home Depot and Lowe’s.

=//__Object Oriented Programming (OOP)__//= Object-oriented programming refers to the use of derived classes and virtual functions. One important advantage of object-oriented systems is extensibility. This refers to the ease with which the system can be extended. In C++, the actions are the pure virtual functions, and their methods are their implementations in the concrete derived classes. In this context, the abstract base class is called the system interface and the concrete derived classes are called the system implementation. Extensibility is facilitated by the fact that only the newly added methods need to be compiled.

Alan Kay summarized five basic characteristics of Smalltalk, the first successful object-oriented language and one of the languages upon which C++ is based. These characteristics represent a pure approach to object-oriented programming:

1. **//Everything is an object. //** Think of an object as a fancy variable; it stores data, but you can “make requests” to that object, asking it to perform operations on itself. In theory, you can take any conceptual component in the problem you’re trying to solve (dogs, buildings, services, etc.) and represent it as an object in your program. 2. **//A program is a bunch of objects telling each other what to do by sending messages //****//.//** To make a request of an object, you “send a message” to that object. More concretely, you can think of a message as a request to call a function that belongs to a particular object. 3. **//Each object has its own memory made up of other objects //****//.//** Put another way, you create a new kind of object by making a package containing existing objects. Thus, you can build complexity in a program while hiding it behind the simplicity of objects. 4. **//Every object has a type //****//.//** Using the parlance, each object is an //instance // of a //class //, in which “class” is synonymous with “type.” The most important distinguishing characteristic of a class is “What messages can you send to it?” 5. **//All objects of a particular type can receive the same messages //****//.//** This is actually a loaded statement, as you will see later. Because an object of type “circle” is also an object of type “shape,” a circle is guaranteed to accept shape messages. This means you can write code that talks to shapes and automatically handles anything that fits the description of a shape. This //substitutability // is one of the most powerful concepts in OOP.

=//__Composition/Inheritance__//= We often need to use existing classes to define new classes. One way to do that is through composition. Composition of classes refers to the use of one or more classes within the definition of another class. When the data member of the new class is an object of another class, we say that the new class is a composite of the other objects. Composition is often referred to as a “has-a” relationship because the objects of the composite class “have” objects of the composed class as members. Composition is one way of reusing existing software to create new software.

Inheritance is a form of software reuse in which the programmer creates a class that absorbs an existing class's data and behaviors and enhances them with new capabilities. Software reusability saves time during program development. It also encourages the reuse of proven, debugged, high-quality software, which increases the likelihood that a system will be implemented effectively. When creating a class, instead of writing completely new data members and member functions, the programmer can designate that the new class should inherit the members of an existing class. This existing class is called the base class, and the new class is referred to as the derived class. This is often referred to as an “is-a” relationship because every object of the class being defined “is” also an object of the inherited class. The keyword “public” after the colon specifies public inheritance, which means that public members of the base class become public members of the derived class. Inheritance is said to percolate up through the hierarchy to obtain the attributes of its parent class. An alternative to percolating up is casting down. In casting down, a pointer to a base class is treated as a pointer to a derived class. A derived class represents a more specialized group of objects. Typically, a derived class contains behaviors inherited from its base class plus additional behaviors. As we will see, a derived class can also customize behaviors inherited from the base class. A direct base class is the base class from which a derived class explicitly inherits. An indirect base class is inherited from two or more levels up in the class hierarchy. In the case of single inheritance, a class is derived from one base class. C++ also supports multiple inheritance, in which a derived class inherits from multiple (possibly unrelated) base classes.

=//__Polymorphism and Virtual Functions__//= One of the most powerful features of C++ is that it allows objects of different types to respond differently to the same function call. This is called “polymorphism” and it is achieved by means of “virtual” functions. Polymorphism  enables us to " program in the general " rather than " program in the specific. " In particular, polymorphism enables us to write programs that process objects of classes that are part of the same class hierarchy as if they are all objects of the hierarchy's base class. With polymorphism, we can design and implement systems that are easily extensible. New classes can be added with little or no modification to the general portions of the program, as long as the new classes are part of the inheritance hierarchy that the program processes generically. The only parts of a program that must be altered to accommodate new classes are those that require direct knowledge of the new classes that the programmer adds to the hierarchy.

The purpose of using virtual methods is to use the base class as the reference for all invoked operations. Therefore, derived method calls must be invoked through the parent class virtual method declaration. A “virtual” member function is a member function that can be overridden in a subclass. A pure virtual function is a “virtual” member function that cannot be called directly. Only its overridden functions in a derived class can be called. A pure “virtual” function is identified by the initialization of zero ( = 0). Polymorphism refers to the run-time binding that occurs when pointers to objects are used in classes that have “virtual” functions. Polymorphism promotes extensibility by allowing new subclasses and methods to be added to a class hierarchy without having to modify application programs that already use the hierarchy’s interface.

=//__Project3__//= <span style="font-family: 'Tahoma','sans-serif'; font-size: 14pt; line-height: 150%;">In the main, pBase is the type of its base class and points to the address of class CIRCLE_C. This allows access to height, width, and area of CIRCLE_C through the base class. This example shows the fundamentals of using virtual methods. Class Rectangle and Triangle need their own area call. So, area is defined virtual in the parent class so that the pointers will point to the derived class methods instead of the parent area method.

code format="cpp" // project_3.cpp : Defines the entry point for the console application. //
 * 1) include "stdafx.h"
 * 2) include <stdlib.h>
 * 3) include <stdio.h>
 * 4) include "derived_Circle.h"
 * 5) include "derived_Rectangle.h"
 * 6) include "derived_Square.h"
 * 7) include "derived_cube.h"

int _tmain(int argc, _TCHAR* argv[])//Parameters for each shape are //predefined for ease of demonstration {   CIRCLE_C circle;//instantiating a class of type circle.

circle.setWidth(3);//calling it's methods to get its sizing information circle.setHeight(4); circle.describe_self;

RECTANGLE_C rectangle;

rectangle.setWidth(5); rectangle.setHeight(6); rectangle.describe_self;

SQUARE_C square;

square.setSize(4); square.describe_self;

CUBE_C cube;

cube.setSize(4); cube.describe_self;

base_shape *bs[4];//Upcasting. An array of four entries. //Each entry is capable of pointing to                     //a base shape object.

bs[0] = &circle;//assigning the base shape pointers to   bs[1] = &rectangle;//objects derived from base shape bs[2] = &square; bs[3] = &cube;

for (int i=0; i < 4; i++)//loops through the array and uses bs[i]->describe_self;//upcasting to invoke the correct //derived method

scanf("%s");

return 0; } code

=//__Abstract Base Classes__//= <span style="font-family: 'Tahoma','sans-serif'; font-size: 14pt; line-height: 150%;">The individual classes in a class hierarchy are designated as either “abstract” or “concrete” according to whether they have any pure virtual member functions. An abstract base class is a class that has one or more pure virtual member functions. A concrete derived class is a class that does not have any pure virtual member functions. The existence of a pure virtual member function in a class requires that every one of its concrete derived subclasses implement the function. Abstract base classes cannot be instantiated. An abstract base class is typically defined during the first stages of the process of developing a class hierarchy. It lays out the framework from which the details are derived in the abstract base class’s subclasses. Pure virtual functions prescribe a certain uniformity within the hierarchy. They allow no implementation of the parent class. A well-designed object-oriented program will include a hierarchy of classes whose interrelationships can be described by a tree diagram. In a hierarchy of classes, some functions may be common to all the subclasses of a class. Such functions are declared “virtual” in the base classes, and then overridden in their subclasses for specific implementations. If a “virtual” function is certain to be overridden in all of its subclasses, then there is no need to implement it at all in its base class. This is done by making the “virtual” function “pure”. A pure virtual member function is a virtual function that has no implementation in its class. The syntax for specifying a pure virtual member function is to insert the initializer “ = 0”.

=//__Base Shape__//= <span style="font-family: 'Tahoma','sans-serif'; font-size: 14pt; line-height: 150%;">The class base_shape doesn’t allow any direct implementation of its methods. In this case, the base shape class methods are de-referenced and are able to call the derived class methods because of the virtual methods defined in the base class. Every one of the base class’s methods is assigned to zero (= 0), since all of the derived classes have methods that will override the base class methods. If any of the base class’s methods had a need to be implemented, that method would had remained uninitialized to zero and therefore able to return an output from the base. As such, a new class could be designed to use the base class’s functionality regardless of whether or not its methods are pure or not. All you have to do is declare it a pointer that points to the new class.

<span style="font-family: Tahoma,Geneva,sans-serif; font-size: 120%;"> code format="cpp"
 * Base_Shape.h**
 * 1) pragma once

class base_shape {

public: base_shape {       width = 0; height = 0; }

virtual void setWidth( int inWidth )=0; virtual void setHeight( int inHeight )=0; virtual void describe_self(void)=0; virtual int area( void )=0; int width; int height; int radius;

private: } ; code

=//__Virtual and Multiple Inheritance__//= <span style="font-family: 'Tahoma','sans-serif'; font-size: 14pt; line-height: 150%;">Virtual inheritance allows inheritance of classes through derived classes to the derived class’s base class. For classes that are not directly inheriting from a base class but are inheriting from a class that is inheriting from the base class; inheriting attributes from the base class is still possible by declaring the base class virtual in its inheriting class’s. <span style="font-family: 'Tahoma','sans-serif'; font-size: 14pt; line-height: 150%;">Implementing hierarchies with base classes is simpler if default constructors are used for the base classes. If a base class provides a constructor that requires arguments, the implementation of the derived classes becomes more complicated, because the most derived class must explicitly invoke the virtual base class's constructor to initialize the members inherited from the  base class. Multiple inheritance, simply allows inheritance from more than one class. After a class’s instantiation is declared, that instance can then utilize methods from different classes as long as those classes are declared public to that class.

=//__Header and Source Files__//= <span style="font-family: 'Tahoma','sans-serif'; font-size: 14pt; line-height: 150%;">Virtual base classes allow an object derived from multiple bases that themselves share a common base to inherit just one object of that shared base class. For example, Square allows the implementation of the Base class from Cube. Multiple inheritance describes a class that has more than one immediate base class. As with single inheritance, public inheritance should express an “is-a” relationship. The .h files are for implementation (definition) and the .cpp files are for instantiation (declaration). We are using multiple .h and .cpp files for the different shapes. By doing this, you can include header files in multiple places without the compiler giving you an error. For every shape, there is a .cpp file and header file. For future expansion, you can include only the shapes you think the user will need or supply extra shapes for a fee. The base class implements some very basic functionality. By “dumbing down” the base class, it’s not very useful on its own. Making it abstract will prevent misuse of its code and enable its functionality to be inherited and extended.

<span style="font-family: 'Times New Roman',Times,serif; font-size: 150%;">**derived_Circle.h** code format="cpp"
 * 1) pragma once


 * 1) include <stdio.h>
 * 2) include "base_shape.h"

class CIRCLE_C : public base_shape//derived from base shape(inheritance) {

public: CIRCLE_C; virtual void setWidth( int inWidth ); virtual void setHeight( int inHeight ); virtual void describe_self(void); virtual int area(void);

} ; code **<span style="font-family: 'Times New Roman',Times,serif;">derived_Circle.cpp ** code format="cpp"
 * include "StdAfx.h"
 * 1) include "derived_Circle.h"
 * 2) include "math.h"

CIRCLE_C::CIRCLE_C {   width = 0; height = 0; radius = 0; }

void CIRCLE_C::setWidth( int inWidth )//defines the body of the method {   radius = inWidth; }

void CIRCLE_C::setHeight( int inHeight ) {   height = inHeight; }

void CIRCLE_C::describe_self(void) {   printf("\nI am a circle. My radius %d. My area is: %d\n",              radius, area ); }

int CIRCLE_C::area(void) {   double Pi = 3.1416; return double( (radius * radius) * Pi ); }** code <span style="font-family: 'Times New Roman',Times,serif; font-size: 150%;">**derived_Rectangle.h** code format="cpp"
 * 1) pragma once


 * 1) include <stdio.h>
 * 2) include "base_shape.h"

class RECTANGLE_C : public base_shape {

public: RECTANGLE_C; virtual void setWidth( int inWidth ); virtual void setHeight( int inHeight ); virtual void describe_self(void); virtual int area(void); virtual int perimeter( void ); virtual void setSize( int inSize );

} ; code <span style="font-family: 'Times New Roman',Times,serif; font-size: 150%;">**derived_Rectangle.cpp** code format="cpp"
 * 1) include "StdAfx.h"
 * 2) include "derived_Rectangle.h"

RECTANGLE_C::RECTANGLE_C {   width = 0; height = 0; }

void RECTANGLE_C::setWidth( int inWidth ) {   width = inWidth; }

void RECTANGLE_C::setHeight( int inHeight ) {   height = inHeight; }

void RECTANGLE_C::describe_self(void) {   printf("\nI am a rectangle. My dimensions are %d wide by %d high."           "\nMy area is: %d.  My perimeter is: %d.\n",              width, height, area, perimeter  ); }

int RECTANGLE_C::area(void) {   return( width*height ); }

int RECTANGLE_C::perimeter(void) {   return( 2*( width + height ) ); }

void RECTANGLE_C::setSize( int inSize ) {   width = inSize; height = inSize; } code <span style="font-family: 'Times New Roman',Times,serif; font-size: 150%;">**derived_Square.h** code format="cpp"
 * 1) pragma once


 * 1) include <stdio.h>
 * 2) include "base_shape.h"

class SQUARE_C : public base_shape {

public: SQUARE_C; virtual void setWidth( int inWidth ); virtual void setHeight( int inHeight ); virtual void describe_self(void); virtual int area(void); virtual int perimeter( void ); virtual void setSize( int inSize );

} ; code <span style="font-family: 'Times New Roman',Times,serif; font-size: 150%;">**derived_Square.cpp** code format="cpp"
 * include "StdAfx.h"
 * 1) include "derived_Square.h"

SQUARE_C::SQUARE_C {   width = 0; height = 0; }

void SQUARE_C::setWidth( int inWidth ) {   width = inWidth; }

void SQUARE_C::setHeight( int inHeight ) {   height = inHeight; }

void SQUARE_C::describe_self(void) {   printf("\nI am a square. My dimensions are %d wide by %d high."           "\nMy area is: %d.  My perimeter is: %d.\n",              width, height, area, perimeter  ); }

int SQUARE_C::area(void) {   return( width*height ); }

int SQUARE_C::perimeter(void) {   return( 4 * width ); }

void SQUARE_C::setSize( int inSize ) {   width = inSize; height = inSize; }** code <span style="font-family: 'Times New Roman',Times,serif; font-size: 150%;">**derived_Cube.h** code format="cpp"
 * 1) include <stdio.h>
 * 2) include "derived_Square.h"

class CUBE_C : public SQUARE_C {

public: CUBE_C; virtual void describe_self(void); virtual int volume(void); virtual void setSize( int inSize ) {       setWidth( inSize ); }

} ; code <span style="font-family: 'Times New Roman',Times,serif; font-size: 150%;">**derived_Cube.cpp** code format="cpp"
 * include "StdAfx.h"
 * 1) include <stdio.h>
 * 2) include "derived_Cube.h"

CUBE_C::CUBE_C{};

void CUBE_C::describe_self(void) {   printf("\nI am a cube. The lenght of my side is %d."           " My Volume is: %d\n",            width, volume ); }

int CUBE_C::volume(void) {   return( width * width * width ); }** code
 * <span style="font-family: 'Times New Roman',Times,serif; font-size: 150%;">Solution **

=//__Conclusion__//= <span style="font-family: 'Tahoma','sans-serif'; font-size: 14pt; line-height: 150%;">We wrote this program using the concept of polymorphism so it can easily be extended by providing new objects that conform to the original interface. It is unnecessary to recompile original programs by adding new types. Only re-linking is necessary to exhibit the new changes along with the old application. This is the greatest achievement of C++ object-oriented programming. In programming language, there has always been a need for adding and customizing. By utilizing the concept of polymorphism, time and work effort is reduced in addition to making future maintenance easier. Once a piece of code is written and tested, why re-invent the wheel? Re-use the existing code and don’t introduce the possibility of injecting “buggy” code in to a known, working design.