In an inheritance scenario, a parent class is configured to provide its
child with the basic foundation the child needs. Although a child can
implement a new behavior not available on the parent object, sometimes a
child object will need a customized implementation of a behavior that
has already been configured with its parent. That is what happens for
example when inheriting a sphere from a circle class. Both have a
characteristic called Area but the area is calculated differently on
each shape.
 |
Inheritance Review
|
- Create a new C++ Console Application in a folder called Polymorphism
- Save the first file as Main and the project as Polymorphism
- Add a new class and save it as Circle
- Create a TCircle class in the Circle.h file as follows:
//---------------------------------------------------------------------------
#ifndef CircleH
#define CircleH
//---------------------------------------------------------------------------
class TCircle
{
public:
TCircle(double r = 0.00);
~TCircle();
void setRadius(const double r) { Radius = r; }
double getRadius() const { return Radius; }
double Area() const;
void ShowCharacteristics() const;
protected:
double Radius;
};
//---------------------------------------------------------------------------
#endif
|
- Implement the TCircle class in the Circle.cpp file as follows:
//---------------------------------------------------------------------------
#include <iomanip>
using namespace std;
#include "Circle.h"
//---------------------------------------------------------------------------
const double PI = 3.14159;
//---------------------------------------------------------------------------
TCircle::TCircle(double r)
: Radius(r)
{
}
//---------------------------------------------------------------------------
TCircle::~TCircle()
{
}
//---------------------------------------------------------------------------
double TCircle::Area() const
{
return Radius * Radius * PI;
}
//---------------------------------------------------------------------------
void TCircle::ShowCharacteristics() const
{
cout << "Circle Characteristics";
cout << setiosflags(ios::fixed) << setprecision(2);
cout << "\nRadius: " << getRadius();
cout << "\nArea: " << Area();
}
//---------------------------------------------------------------------------
|
- Add a new class and save it as Sphere
- To create a new TSphere class based on the TCircle class, lay its foundation in the Sphere.h file as follows:
//---------------------------------------------------------------------------
#ifndef SphereH
#define SphereH
#include "Circle.h"
//---------------------------------------------------------------------------
class TSphere : public TCircle
{
public:
TSphere(double x);
~TSphere() {}
double Area() const;
double Volume() const;
void ShowCharacteristics() const;
private:
};
//---------------------------------------------------------------------------
#endif
|
- Implement the new class as follows:
//---------------------------------------------------------------------------
#include <iomanip>
using namespace std;
#include "Sphere.h"
//---------------------------------------------------------------------------
const double PI = 3.14159;
//---------------------------------------------------------------------------
TSphere::TSphere(double n)
: TCircle(n)
{
}
//---------------------------------------------------------------------------
double TSphere::Area() const
{
return 4 * PI * Radius * Radius;
}
//---------------------------------------------------------------------------
double TSphere::Volume() const
{
return 4 * PI * Radius * Radius * Radius / 3;
}
//---------------------------------------------------------------------------
void TSphere::ShowCharacteristics() const
{
cout << "Circle Characteristics";
cout << setiosflags(ios::fixed) << setprecision(2);
cout << "\nRadius: " << getRadius();
cout << "\nArea: " << Area();
cout << "\nVolume: " << Volume();
}
//---------------------------------------------------------------------------
|
- To inherit another class, add a new class and save it as Cylinder
- Create the TCylinder class based on TCircle in the Cylinder.h file as follows:
//---------------------------------------------------------------------------
#ifndef CylinderH
#define CylinderH
#include "Circle.h"
//---------------------------------------------------------------------------
class TCylinder : public TCircle
{
public:
TCylinder(double r, double h);
~TCylinder() {}
void setHeight(const double h) { Height = h; }
double getHeight() const { return Height; }
double BaseArea() const;
double LateralArea() const;
double Area() const;
double Volume() const;
void ShowCharacteristics() const;
private:
double Height;
};
//---------------------------------------------------------------------------
#endif
|
- Implement the new class in its source file as follows:
//---------------------------------------------------------------------------
#include <iomanip>
using namespace std;
#include "Cylinder.h"
//---------------------------------------------------------------------------
const double PI = 3.14159;
//---------------------------------------------------------------------------
TCylinder::TCylinder(double x, double y)
: TCircle(x), Height(y)
{
}
//---------------------------------------------------------------------------
double TCylinder::BaseArea() const
{
return TCircle::Area();
}
//---------------------------------------------------------------------------
double TCylinder::LateralArea() const
{
double Circ = Radius * 2 * PI;
return Circ * Height;
}
//---------------------------------------------------------------------------
double TCylinder::Area() const
{
double Base = TCircle::Area();
double Lateral = LateralArea();
return (2 * Base) + Lateral;
}
//---------------------------------------------------------------------------
double TCylinder::Volume() const
{
double Base = TCircle::Area();
return Base * Height;
}
//---------------------------------------------------------------------------
void TCylinder::ShowCharacteristics() const
{
cout << "Circle Characteristics";
cout << setiosflags(ios::fixed) << setprecision(2);
cout << "\nRadius: " << getRadius();
cout << "\nHeight: " << getHeight();
cout << "\nBase Area: " << BaseArea();
cout << "\nLateral Area: " << LateralArea();
cout << "\nArea: " << Area();
cout << "\nVolume: " << Volume();
}
//---------------------------------------------------------------------------
|
- To prepare a test, change the main() function in the Main.cpp file as follows:
//---------------------------------------------------------------------------
#include <iostream>
using namespace std;
//---------------------------------------------------------------------------
#include "Circle.h"
#include "Sphere.h"
#include "Cylinder.h"
int main(int argc, char* argv[])
{
TCircle e(12.55);
TSphere s(22.25);
TCylinder c(34.05, 28.35);
e.ShowCharacteristics();
cout << "\n\n";
s.ShowCharacteristics();
cout << "\n\n";
c.ShowCharacteristics();
return 0;
}
//---------------------------------------------------------------------------
|
- To test the program, press F9.
- We can also dynamically declare the objects and access them as
pointers. To see an example, change the main() function as follows:
//---------------------------------------------------------------------------
#include <iostream>
using namespace std;
//---------------------------------------------------------------------------
#include "Circle.h"
#include "Sphere.h"
#include "Cylinder.h"
int main(int argc, char* argv[])
{
TCircle *e = new TCircle(12.55);
TSphere *s = new TSphere(16.15);
TCylinder *c = new TCylinder(14.25, 10.85);
e->ShowCharacteristics();
cout << "\n\n";
s->ShowCharacteristics();
cout << "\n\n";
c->ShowCharacteristics();
return 0;
}
//---------------------------------------------------------------------------
|
- Test the program.
When studying inheritance, we learned that there is a special bond
between an inherited class and its parent. Not only does the child
object have access to the public members of a class but also the child,
based on this relationship, has direct access to the members of the
protected section (the child is a protégé) of the parent. The program
above shows us that, in order to access a class’ members, we can just
declare an instance of the class and use either the member access
operator “.” or the pointer access operator “->”.
If there is such a good relationship between a class and its children,
is it possible to access a member of a child object using an instance of
the parent? We will declare only an instance of the parent class,
TCircle, and try to access its child using such a variable.
- Change the main() function as follows:
//---------------------------------------------------------------------------
#include <iostream>
using namespace std;
//---------------------------------------------------------------------------
#include "Circle.h"
#include "Sphere.h"
#include "Cylinder.h"
int main(int argc, char* argv[])
{
TSphere *s = new TSphere(15.32);
TCylinder *c = new TCylinder(36.08, 20.24);
TCircle *e = s;
e->ShowCharacteristics();
cout << "\n\n";
e = c;
e->ShowCharacteristics();
return 0;
}
//---------------------------------------------------------------------------
|
- Test the program.
Notice that, although the pointer variable *e has been initialized with
variables *s and *c, only the characteristics of the circle are
displayed.
A virtual function is a function that makes sure that, in an inheritance
scenario, the right function is called regardless of the expression
that calls the function. The last three classes we have used have two
functions called Area() and
ShowCharacteristics() each. Let us consider the member function
ShowCharacteristics() that is present in all three classes. If we need
an instance of the parent class to call the right member function, in
this case Area, we must declare ShowCharacteristics () in the parent
class as virtual.
 |
Declaring a Virtual Function
|
- Click the Circle.h tab and change the declaration of the Area() function as follows:
//---------------------------------------------------------------------------
#ifndef CircleH
#define CircleH
//---------------------------------------------------------------------------
class TCircle
{
public:
TCircle(double r = 0.00);
~TCircle();
void setRadius(const double r) { Radius = r; }
double getRadius() const { return Radius; }
double Area() const;
virtual void ShowCharacteristics() const;
protected:
double Radius;
};
//---------------------------------------------------------------------------
#endif
|
- Test the program again. Notice that, this time, even though an
instance of the TCircle class made the call, the characteristics of the
assigned variables display.
- Return to your programming environment.
- Since the Area() function is present on the parent as well as the
inherited classes, make it virtual in the base class as follows:
//---------------------------------------------------------------------------
#ifndef CircleH
#define CircleH
//---------------------------------------------------------------------------
class TCircle
{
public:
TCircle(double r = 0.00);
~TCircle();
void setRadius(const double r) { Radius = r; }
double getRadius() const { return Radius; }
virtual double Area() const;
virtual void ShowCharacteristics() const;
protected:
double Radius;
};
//---------------------------------------------------------------------------
#endif
|
- Test the program. Notice that the right functions, as far as their
having been assigned to the base class instance goes, are called.
Even though you can use polymorphism to help the compiler identify which
function is being called, if you want to access the same function of
the base class, you can qualify it with the scope resolution operator
“::”.
As you can see, a function with the same name can be declared in both a
base and a derived classes. This allows a derived class to define its
custom definition of the function. Because the derived class “re-writes”
the same function, the derived class is said to override the function. A
function can be overridden only if it is virtual. A function can be
virtual only if carries the same name, the same return type, and the
same
type(s) of argument(s) if any.
Consider a case where you have created a class that is derived from
another class. When you dynamically call the inherited class using an
instance of the base class (as done in the last example), during the
closing of the program, the destructor of the child class is called
first, followed by the destructor of the base class. If you dynamically
declare an instance of the base class and then invoke the children of
the class, you need to make sure that each destructor and the right
destructor of the classes that was used is called to destroy the class;
this is safe measure to avoid memory leak. This aspect of C++
programming is taken care of by declaring the destructor of the base
class as virtual.
Whenever the destructor of the parent class is
declared virtual, the destructor of an inherited class is also virtual.
This ensures that, the program closes, all of the destructors of the
base class and its children that were used are called, providing a safe
claim of the memory that was used.
To declare a destructor as virtual, type the virtual keyword on its left, in the body of the class. Here is an example:
//---------------------------------------------------------------------------
#ifndef CircleH
#define CircleH
//---------------------------------------------------------------------------
class TCircle
{
public:
TCircle(double r = 0.00);
virtual ~TCircle();
void setRadius(const double r) { Radius = r; }
double getRadius() const { return Radius; }
double Area() const;
virtual void ShowCharacteristics() const;
protected:
double Radius;
};
//---------------------------------------------------------------------------
#endif
|
An abstract class is a class whose role is only meant to lay a
foundation for those classes that would need a common behavior or
similar characteristics. Therefore, an abstract class is used only as a
base class for inheritance. A class is made abstract by declaring at
least one its member functions as a “pure” virtual function.
Only a virtual function can be made “pure”. The syntax of declaring a pure function is:
virtual ReturnType FunctionName() = 0;
|
The virtual keyword is required to make sure that a (any) child
of this class can implement this function as it deems fit. The
ReturnType is the data type that the function will return. The
FunctionName is an appropriate name for the function. The = 0 is
required. It lets the compiler know that this function is a pure virtual
function.
When a function has been declared as pure virtual, you do not need to
implement it. Instead, each inherited class of an abstract class must
provide its own implementation of the pure member function.
When creating an abstract class, you can declare all of its member functions as pure. Here is an example:
//---------------------------------------------------------------------------
struct TTent
{
virtual int WhatIsTheCapacity() = 0;
virtual double TentArea() = 0;
virtual double TentVolume() = 0;
virtual char* TextureColor() = 0;
};
//---------------------------------------------------------------------------
|
In this case, the class does not need a source file or any
implementation because none of its member functions will be implemented.
An abstract base class can also have a mix of pure and non-pure functions. Here is an example:
//---------------------------------------------------------------------------
struct TTent
{
virtual int WhatIsTheCapacity() = 0;
virtual double TentArea() = 0;
virtual double TentVolume() = 0;
virtual char* TextureColor() = 0; // Pure virtual function
virtual char* TextureName(); // Virtual function
int ShapeType(); // Regular member function
};
//---------------------------------------------------------------------------
|
In this case, as we have done with the other classes so far, you must
implement the non-pure functions in the base and let the inherited
classes implement their own version(s) of the pure virtual
function(s).
 |
Implementing Abstract Classes
|
- Create a new C++ Console Application and save it in a folder called Polygons
- Save the class as Main and the project as RegPolygons
- Add a new class and save it as Polygon
- On the Status Bar, click the Polygon.h tab and create a regular class as follows:
//---------------------------------------------------------------------------
#ifndef PolygonH
#define PolygonH
//---------------------------------------------------------------------------
namespace Shapes
{
class TPolygon
{
public:
TPolygon(int s = 0, char *n = "", double r = 0.00);
virtual ~TPolygon();
void setNbrOfSides(const int n);
int getNbrOfSides() const { return NbrOfSides; }
void setPolyName(const char *n);
char * getPolyName() const { return PolyName; }
void setRadius(const double r);
double getRadius() const { return Radius; }
double CentralAngle() const;
double InteriorAngle() const;
protected:
int NbrOfSides;
char *PolyName;
double Radius;
};
}
//---------------------------------------------------------------------------
#endif
|
- Click the Polygon.cpp tab and implement the member functions as follows:
//---------------------------------------------------------------------------
#include <iostream>
using namespace std;
#include "Polygon.h"
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
namespace Shapes
{
TPolygon::TPolygon(int s, char *n, double r)
{
//TODO: Add your source code here
NbrOfSides = s;
Radius = r;
setPolyName(n);
}
//---------------------------------------------------------------------------
TPolygon::~TPolygon()
{
//TODO: Add your source code here
delete [] PolyName;
}
//---------------------------------------------------------------------------
void TPolygon::setNbrOfSides(const int n)
{
// Avoid a negative number of sides. It wouldn't make sense.
// This program considers only regular polygons.
// The minimum number of sides is 3, which corresponds to an
// equilateral triangle
if( n < 3 )
NbrOfSides = 0;
else if( n < 4 )
NbrOfSides = 3; // Equilateral Triangle
else if( n == 4 )
NbrOfSides = 4; // Square
else if( n == 5 )
NbrOfSides = 5; // Pentagon
else if( n == 6 )
NbrOfSides = 6; // Hexagon
else if( n == 7 || n == 8 )
NbrOfSides = 8; // Octagon
else if( n == 9 || n == 10 )
NbrOfSides = 10;// Decagon
else //if( n == 11 || n == 12 )
NbrOfSides = 12;// Dodecagon
}
//---------------------------------------------------------------------------
void TPolygon::setPolyName(const char * n)
{
//TODO: Add your source code here
PolyName = new char[strlen(n) + 1];
strcpy(PolyName, n);
}
//---------------------------------------------------------------------------
void TPolygon::setRadius(const double r)
{
//Avoid a negative radius. It wouldn't make sense
if( r < 0 )
Radius = 0.00;
else
Radius = r;
}
//---------------------------------------------------------------------------
double TPolygon::CentralAngle() const
{
return 360 / NbrOfSides;
}
//---------------------------------------------------------------------------
double TPolygon::InteriorAngle() const
{
return (NbrOfSides - 2) * 180 / NbrOfSides;
}
//---------------------------------------------------------------------------
}
//---------------------------------------------------------------------------
|
- Prepare the main() function for a test as follows:
//---------------------------------------------------------------------------
#include <iostream>
#include <iomanip>
using namespace std;
//---------------------------------------------------------------------------
#include "Polygon.h"
int main(int argc, char* argv[])
{
Shapes::TPolygon *Pol = new Shapes::TPolygon;
Pol->setRadius(15.55);
Pol->setNbrOfSides(25);
Pol->setPolyName("Unknown");
cout << "Shape Characteristics";
cout << setiosflags(ios::fixed) << setprecision(2);
cout << "\nName: " << Pol->getPolyName();
cout << "\nSides: " << Pol->getNbrOfSides();
cout << "\nRadius: " << Pol->getRadius();
cout << "\nCentral Angle: " << Pol->CentralAngle() << "*";
cout << "\nInterior Angle: " << Pol->InteriorAngle();
return 0;
}
//---------------------------------------------------------------------------
|
- Test the program. Return to your programming environment.
- To add some pure virtual function and qualify the class as abstract, change the TPolygon class creation as follows:
//---------------------------------------------------------------------------
#ifndef PolygonH
#define PolygonH
//---------------------------------------------------------------------------
namespace Shapes
{
class TPolygon
{
public:
TPolygon(int s = 0, char *n = "", double r = 0.00);
virtual ~TPolygon();
void setNbrOfSides(const int n);
int getNbrOfSides() const { return NbrOfSides; }
void setPolyName(const char *n);
char * getPolyName() const { return PolyName; }
void setRadius(const double r);
double getRadius() const { return Radius; }
double CentralAngle() const;
double InteriorAngle() const;
virtual double Side() = 0;
virtual double Apothem() = 0;
virtual double Perimeter() = 0;
double Area();
virtual void ShapeCharacteristics() = 0;
protected:
int NbrOfSides;
char *PolyName;
double Radius;
};
}
//---------------------------------------------------------------------------
#endif
|
- To implement the newly added Area() member function, add it to the Polygon.cpp file as follows:
//---------------------------------------------------------------------------
#include <iostream>
using namespace std;
#include "Polygon.h"
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
namespace Shapes
{
TPolygon::TPolygon(int s, char *n, double r)
{
. . .
}
//---------------------------------------------------------------------------
. . .
//---------------------------------------------------------------------------
double TPolygon::Area()
{
double p = Perimeter();
double r = Apothem();
return p * r / 2;
}
//---------------------------------------------------------------------------
}
//---------------------------------------------------------------------------
|
- To test the program, press F9.
- Read the errors that you receive. As you can see, you are not allowed to declare an instance of an abstract class:
- Return to your programming environment.
- Add a new class and save it as Triangle
- In the Triangle.h file, derive a new TTriangle class from the TPolygon class as follows:
//---------------------------------------------------------------------------
#ifndef TriangleH
#define TriangleH
#include "Polygon.h"
//---------------------------------------------------------------------------
class TTriangle : public Shapes::TPolygon
{
public:
// We use two constructors so that the user can initialize
// either by not specifying anything or by providing the radius
TTriangle();
TTriangle(double r);
~TTriangle();
virtual double Side();
virtual double Apothem();
virtual double Perimeter();
double Height();
virtual void ShapeCharacteristics();
protected:
private:
};
//---------------------------------------------------------------------------
#endif
|
- Implement the class in the Triangle.cpp source file as follows:
//---------------------------------------------------------------------------
#include <iostream>
#include <iomanip>
#include <math.h>
using namespace std;
#include "Triangle.h"
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
TTriangle::TTriangle()
{
// If the constructor is empty, at least we know the number of sides
// and the name of this polygon
setNbrOfSides(3);
setPolyName("Equilateral Triangle");
setRadius(getRadius());
}
//---------------------------------------------------------------------------
TTriangle::TTriangle(double r)
{
setNbrOfSides(3);
setPolyName("Equilateral Triangle");
setRadius(r);
}
//---------------------------------------------------------------------------
TTriangle::~TTriangle()
{
}
//---------------------------------------------------------------------------
double TTriangle::Side()
{
return Radius * sqrt(3);
}
//---------------------------------------------------------------------------
double TTriangle::Apothem()
{
return Radius / 2;
}
//---------------------------------------------------------------------------
double TTriangle::Perimeter()
{
double S = Side();
return 3 * S;
}
//---------------------------------------------------------------------------
double TTriangle::Height()
{
return Apothem() + Radius;
}
//---------------------------------------------------------------------------
void TTriangle::ShapeCharacteristics()
{
cout << "Shape Characteristics";
cout << "\nName: " << getPolyName();
cout << "\nSides: " << getNbrOfSides();
cout << "\nRadius: " << getRadius();
cout << "\nCentral Angle: " << CentralAngle();
cout << "\nInterior Angle: " << InteriorAngle();
cout << setiosflags(ios::fixed) << setprecision(2);
cout << "\nApothem: " << Apothem();
cout << "\nHeight: " << Height();
cout << "\nPerimeter: " << Perimeter();
cout << "\nArea: " << Area();
}
//---------------------------------------------------------------------------
|
- To prepare a test, change the Main.cpp file as follows:
//---------------------------------------------------------------------------
#include <iostream>
using namespace std;
//---------------------------------------------------------------------------
#include "Triangle.h"
int main(int argc, char* argv[])
{
TTriangle *Tri = new TTriangle;
Tri->setRadius(15.55);
Tri->ShapeCharacteristics();
return 0;
}
//---------------------------------------------------------------------------
|
- Test the program and return to your programming environment.
- Add a new class and save it as Square
- In the Square.h file, create a regular polygon of a square based on the TPolygon class as follows:
//---------------------------------------------------------------------------
#ifndef SquareH
#define SquareH
#include "Polygon.h"
//---------------------------------------------------------------------------
class TPolySquare : public Shapes::TPolygon
{
public:
TPolySquare();
TPolySquare(double r);
~TPolySquare() {}
virtual double Side();
virtual double Apothem();
virtual double Perimeter();
virtual void ShapeCharacteristics();
protected:
private:
};
//---------------------------------------------------------------------------
#endif
|
- Implement the TPolySquare class as follows:
//---------------------------------------------------------------------------
#include <iostream>
#include <iomanip>
#include <math.h>
using namespace std;
//---------------------------------------------------------------------------
#include "Square.h"
//---------------------------------------------------------------------------
TPolySquare::TPolySquare()
{
// If the constructor is empty, at least we know the number of sides
// and the name of this polygon
setNbrOfSides(4);
setPolyName("Square");
setRadius(getRadius());
}
//---------------------------------------------------------------------------
TPolySquare::TPolySquare(double r)
{
setNbrOfSides(4);
setPolyName("Square");
setRadius(r);
}
//---------------------------------------------------------------------------
double TPolySquare::Side()
{
return Radius * sqrt(2);
}
//---------------------------------------------------------------------------
double TPolySquare::Apothem()
{
return sqrt(2) * Radius / 2;
}
//---------------------------------------------------------------------------
double TPolySquare::Perimeter()
{
double S = Side();
return 4 * S;
}
//---------------------------------------------------------------------------
void TPolySquare::ShapeCharacteristics()
{
cout << "Shape Characteristics";
cout << "\nName: " << getPolyName();
cout << "\nSides: " << getNbrOfSides();
cout << "\nRadius: " << getRadius();
cout << setiosflags(ios::fixed) << setprecision(0);
cout << "\nCentral Angle: " << CentralAngle();
cout << "\nInterior Angle: " << InteriorAngle();
cout << setiosflags(ios::fixed) << setprecision(2);
cout << "\nApothem: " << Apothem();
cout << "\nPerimeter: " << Perimeter();
cout << "\nArea: " << Area();
}
//---------------------------------------------------------------------------
|
- Add a new class and save it as Hexagon
- Create a THexagon object derived from the TPolygon class as follows:
//---------------------------------------------------------------------------
#ifndef HexagonH
#define HexagonH
#include "Polygon.h"
//---------------------------------------------------------------------------
class THexagon : public Shapes::TPolygon
{
public:
THexagon();
THexagon(double r);
~THexagon() {}
virtual double Side();
virtual double Apothem();
virtual double Perimeter();
virtual void ShapeCharacteristics();
protected:
private:
};
//---------------------------------------------------------------------------
#endif
|
- Implement the THexagon class as follows:
//---------------------------------------------------------------------------
#include <iostream>
#include <iomanip>
#include <math.h>
using namespace std;
#include "Hexagon.h"
//---------------------------------------------------------------------------
THexagon::THexagon()
{
// If the constructor is empty, at least we know the number of sides
// and the name of this polygon
setNbrOfSides(6);
setPolyName("Hexagon");
setRadius(getRadius());
}
//---------------------------------------------------------------------------
THexagon::THexagon(double r)
{
setNbrOfSides(6);
setPolyName("Hexagon");
setRadius(r);
}
//---------------------------------------------------------------------------
double THexagon::Side()
{
return Radius;
}
//---------------------------------------------------------------------------
double THexagon::Apothem()
{
return sqrt(3) * Radius / 2;
}
//---------------------------------------------------------------------------
double THexagon::Perimeter()
{
double S = Side();
return 6 * S;
}
//---------------------------------------------------------------------------
void THexagon::ShapeCharacteristics()
{
cout << "Shape Characteristics";
cout << "\nName: " << getPolyName();
cout << "\nSides: " << getNbrOfSides();
cout << "\nRadius: " << getRadius();
cout << setiosflags(ios::fixed) << setprecision(0);
cout << "\nCentral Angle: " << CentralAngle();
cout << "\nInterior Angle: " << InteriorAngle();
cout << setiosflags(ios::fixed) << setprecision(2);
cout << "\nApothem: " << Apothem();
cout << "\nPerimeter: " << Perimeter();
cout << "\nArea: " << Area();
}
//---------------------------------------------------------------------------
|
- Before testing the program, change the Main.cpp file as follows:
//---------------------------------------------------------------------------
#include <iostream>
using namespace std;
//---------------------------------------------------------------------------
#include "Triangle.h"
#include "Square.h"
#include "Hexagon.h"
//---------------------------------------------------------------------------
int main(int argc, char* argv[])
{
TTriangle *Tri = new TTriangle;
Tri->setRadius(15.55);
Tri->ShapeCharacteristics();
cout << "\n\nNew Shape";
TPolySquare *Sq = new TPolySquare(22.36);
Sq->ShapeCharacteristics();
cout << "\n\nNew Shape";
clrscr();
THexagon *Hx = new THexagon;
Hx->setRadius(36.08);
Hx->ShapeCharacteristics();
return 0;
}
//---------------------------------------------------------------------------
|
- Test the program and return to your programming environment
|
|
We have been introduced to declaring variables using
specific data types. After declaring a value and initializing it, you may
want the value to change type without redefining it. This is required in
some cases where you already have a value, probably produced by one
variable, while another variable declared with a different data type. This
means that you would need to convert a value from one type into another
type. For example, you may have declared a variable using a double
data type but you need the value of that variable to be used as an int.
Transferring a value from one type to another is referred to as casting.
There are two broad types of casting available in C++:
C's old school of casting and the C++ standards.
|
C, the parent of C++ supports value casting by
specifying the type of value you want an existing one to have. To do this,
you use the following formula:
(DataType)Expression
Based on this formula, in the parentheses, enter the
type of data you want the existing or resulting value to have. The DataType
factor can be any of the data types we saw above. The Expression
factor can be a constant value. Here is an example:
#include <iostream>
using namespace std;
int main()
{
cout << "Number: " << (int)3.14159 << "\n";
return 0;
}
Notice that the value to convert is a floating-point
number. If the conversion is successful, the new value would be conform to
the type in parentheses. For example, the above code would produce:
Number: 3
Here is another version of the above program:
#include <iostream>
using namespace std;
int main()
{
int number;
number = (int)3.14159;
cout << "Number: " << number << "\n";
return 0;
}
The Expression factor can also be the result of
a calculation. In this case, you should include the whole expression is
its own parentheses.
The Expression factor of our formula can also
be the name of a variable that holds a value. Here is an example:
#include <iostream>
using namespace std;
int main()
{
double price = 258.85;
int number;
cout << "Price? $" << price << "\n";
number = (int)price;
cout << "Number: " << number << "\n";
return 0;
}
This would produce:
Price? $258.85
Number: 258
|
C++ provides its own support of value casting using
variable keywords so you can specify the type of conversion you want. One
of the keywords used is static_cast and the formula is:
static_cast<DataType>(Expression)
In this formula, the static_cast keyword, the
<, the >, and the parentheses are required. The DataType
factor should be an existing data type such as those we have reviewed in
this lesson. The Expression factor can be a constant value. Here is
an example that converts a floating-point number to an integer:
#include <iostream>
using namespace std;
int main()
{
cout << "Number: " << static_cast<int>(3.14159) << "\n";
return 0;
}
You can also assign the resulting value to a variable
before using it:
#include <iostream>
using namespace std;
int main()
{
int number = static_cast<int>(3.14159);
cout << "Number: " << number << "\n";
return 0;
}
The value to convert can also be the result of a
calculation. The value can also be originating from an existing variable
whose value you want to convert to a new type. Here is an example:
#include <iostream>
using namespace std;
int main()
{
double PI = 3.14159;
int number;
number = static_cast<int>(PI);
cout << "PI = " << PI << endl;
cout << "Number = " << number << "\n";
return 0;
}
This would produce:
PI = 3.14159
Number = 3
|
In the previous lesson, to declare a variable, we proceeded inside of
the main() function. Such a variable could be used only inside of the
square brackets of main(). In some cases, you may want to declare a
variable that can be accessed from one section of the code. The section of
code in which a variable can be accessed is referred to as its scope.
|
If you declare a variable inside of a function such as
main(), that function can be accessed only from that function. Consider
the following example:
#include <iostream>
using namespace std;
int main()
{
double number = 3.14159;
cout << "Number = " << number << "\n";
return 0;
}
Such a variable is referred to as local because it is
declared in a function. In reality, a local scope is defined by a
beginning opening curly bracket "{" and a closing curly bracket
"}". Everything between these brackets belongs to a local scope.
Once you have declared such a variable, you cannot
declare another variable in the same scope and that bears the same name.
Consider the following example:
#include <iostream>
using namespace std;
int main()
{
double number = 3.14159;
cout << "Number = " << number << "\n";
double number = 2.98;
cout << "Number = " << number << "\n";
return 0;
}
This would produce a "redefinition" error
and the program would not compile, even if the second declaration uses a
different data type. As one type of solution to this kind of problem, C++
allows you to create a "physical" scope. To do this, you can use
curly brackets to delimit the scope of a particular variable. Here is an
example:
#include <iostream>
using namespace std;
int main()
{
{
double number = 3.14159;
cout << "Number = " << number << "\n";
}
double number = 2.98;
cout << "Number = " << number << "\n";
return 0;
}
This would produce:
Number = 3.14159
Number = 2.98
In the code, notice that we delimit only the first
declaration. Indeed, you can delimit each scope if you want:
#include <iostream>
using namespace std;
int main()
{
{
double number = 3.14159;
cout << "Number = " << number << "\n";
}
{
double number = 2.98;
cout << "Number = " << number << "\n";
}
return 0;
}
No comments:
Post a Comment