A common technique used to create programs with various objects consists of declaring one object inside of another. Once you have or know the object to use, you can declare it like a regular member of the object. Like another member variable, you can initialize the object and even manipulate its members.
Using an Enumerator as an Object Member |
|
The enumerators we have used so far were intended to simply carry a list of constant integers. This is useful for conditional statements where a switch or an if…else statements would need to perform comparisons. As an example, suppose we create the following class:
//---------------------------------------------------------------------------
#ifndef LabelTypeH
#define LabelTypeH
//---------------------------------------------------------------------------
#include <iostream.h>
#include <system.hpp>
//---------------------------------------------------------------------------
enum TPrintCategory { pcInkjet = 1, pcLaser, pcMultiPurpose, pcUnspecified };
//---------------------------------------------------------------------------
class TLabelType
{
public:
__fastcall TLabelType();
__fastcall TLabelType(Cardinal m, string n, string c, Integer t);
__fastcall TLabelType(const TLabelType& Label);
__fastcall ~TLabelType();
void __fastcall setModelNumber(const Cardinal m) { ModelNumber = m; }
void __fastcall setName(const string n) { Name = n; }
void __fastcall setColor(const string c) { Color = c; }
void __fastcall setPrintType(const Integer i) { PrintType = i; }
Cardinal __fastcall getModelNumber() const;
string __fastcall getName() const;
string __fastcall getColor() const;
string __fastcall getPrintType() const;
private:
Cardinal ModelNumber;
string Name;
string Color;
Integer PrintType;
};
//---------------------------------------------------------------------------
#endif
|
To demonstrate the use of this new enumerator, we could implement the getPrintType() function as follows:
//---------------------------------------------------------------------------
#pragma hdrstop
#include "LabelType.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
//---------------------------------------------------------------------------
__fastcall TLabelType::TLabelType()
: ModelNumber(0),
Name("None"),
Color("White"),
PrintType(3)
{
}
//---------------------------------------------------------------------------
__fastcall TLabelType::TLabelType(Cardinal m, string n, string c, Integer t)
: ModelNumber(m),
Name(n),
Color(c),
PrintType(t)
{
}
//---------------------------------------------------------------------------
__fastcall TLabelType::TLabelType(const TLabelType& Label)
: ModelNumber(Label.ModelNumber),
Name(Label.Name),
Color(Label.Color),
PrintType(Label.PrintType)
{
}
//---------------------------------------------------------------------------
__fastcall TLabelType::~TLabelType()
{
}
//---------------------------------------------------------------------------
Cardinal __fastcall TLabelType::getModelNumber() const
{
return ModelNumber;
}
//---------------------------------------------------------------------------
string __fastcall TLabelType::getName() const
{
return Name;
}
//---------------------------------------------------------------------------
string __fastcall TLabelType::getColor() const
{
return Color;
}
//---------------------------------------------------------------------------
string __fastcall TLabelType::getPrintType() const
{
string PrintingType;
switch( PrintType )
{
case pcInkjet:
PrintingType = "Injet";
break;
case pcLaser:
PrintingType = "Laser";
break;
case pcMultiPurpose:
PrintingType = "Multi-Purpose";
break;
default:
PrintingType = "Unspeficied";
}
return PrintingType;
}
//---------------------------------------------------------------------------
|
We can test our object using the main() function as follows:
//---------------------------------------------------------------------------
#include <iostream.h>
#pragma hdrstop
//---------------------------------------------------------------------------
#include "LabelType.h"
//---------------------------------------------------------------------------
#pragma argsused
int main(int argc, char* argv[])
{
TLabelType Label;
cout << "A label with default characteristics";
cout << "\nModel Number: " << Label.getModelNumber();
cout << "\nModel Name: " << Label.getName();
cout << "\nMain Color: " << Label.getColor();
cout << "\nPrinting Type: " << Label.getPrintType();
cout << "\n\n";
Label.setModelNumber(475832);
Label.setName("Blanc d'Azure");
Label.setColor("Old Sand");
Label.setPrintType(2);
cout << "Custom Label";
cout << "\nModel Number: " << Label.getModelNumber();
cout << "\nModel Name: " << Label.getName();
cout << "\nMain Color: " << Label.getColor();
cout << "\nPrinting Type: " << Label.getPrintType();
cout << "\n\nPress any key to continue...";
getchar();
return 0;
}
//---------------------------------------------------------------------------
|
Besides representing a list of constant integers, an enumerator can also behave like a small object, making it one of the most commonly used members of objects in C++ Builder applications. As a semi-complete data type, an enumerator can be used to create an integer data type and make it a member of another object. The advantage of using an enumerator is that, unlike a regular integer, an enumerator and its members names are a little more explicit. You will see this technique used on many objects of the Visual Component Library.
We have learned that, when defining an enumerator, we can supply the names of its members. Here is an example:
enum TAdhesive { adNone, adRemovable, adNonRemovable };
|
Once the enumerator is defined, we can declare it as a member of an object where needed. The enumerator becomes a data type. It can be declared as a variable:
It can also be passed as an argument:
__fastcall TLabelType(long m, string c, string n, TAdhesive a);
|
Or it can de used as a return type of a function or a method:
TAdhesive __fastcall getAdhesive();
|
These characteristics of an enumrator are exemplified in the new version of the TLabelType object as follows:
//---------------------------------------------------------------------------
#ifndef LabelTypeH
#define LabelTypeH
//---------------------------------------------------------------------------
#include <iostream.h>
#include <system.hpp>
//---------------------------------------------------------------------------
enum TPrintCategory { pcInkjet = 1, pcLaser, pcMultiPurpose, pcUnspecified };
enum TAdhesive { adNone, adRemovable, adNonRemovable };
//---------------------------------------------------------------------------
class TLabelType
{
public:
__fastcall TLabelType();
__fastcall TLabelType(Cardinal m, string n, string c,
Integer t, TAdhesive a);
__fastcall TLabelType(const TLabelType& Label);
__fastcall ~TLabelType();
void __fastcall setModelNumber(const Cardinal m) { ModelNumber = m; }
void __fastcall setName(const string n) { Name = n; }
void __fastcall setColor(const string c) { Color = c; }
void __fastcall setPrintType(const Integer i) { PrintType = i; }
void __fastcall setAdhesive(TAdhesive a) { Adhesive = a; }
Cardinal __fastcall getModelNumber() const;
string __fastcall getName() const;
string __fastcall getColor() const;
string __fastcall getPrintType() const;
TAdhesive __fastcall getAdhesive() const;
private:
Cardinal ModelNumber;
string Name;
string Color;
Integer PrintType;
TAdhesive Adhesive;
};
//---------------------------------------------------------------------------
#endif
|
When implementing the object, if you want to initialize a variable identified by an enumerator, make sure you use a valid name as one of the members of the enumerator. An example would be:
Adhesive = adNonRemovable;
You could be tempted to use a constant integer to initialize such a variable. Here is an example:
Adhesive = 1;
But this is a bad idea. First the use of the enumerator would appear pointless and unprofessional because this would deceive the purpose of using an enumerator. Second, if you initialize the variable using a valid name, the compiler would have the responsibility of finding the corresponding value of the member; if you decide to use a (random) integer, no matter how confident you are, you are running the risk of using a value unrecognized by the enumerator. Thirdly, most compilers would display a warning; and you shold not neglect warnings.
To implement the functions whose return type or arguments are enumerator, proceed as you would for other regular data types. Here is the source file of the TLabelType object:
//---------------------------------------------------------------------------
#pragma hdrstop
#include "LabelType.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
//---------------------------------------------------------------------------
__fastcall TLabelType::TLabelType()
: ModelNumber(0),
Name("None"),
Color("White"),
PrintType(3),
Adhesive(adNone)
{
}
//---------------------------------------------------------------------------
__fastcall TLabelType::TLabelType(Cardinal m, string n, string c,
Integer t, TAdhesive a)
: ModelNumber(m),
Name(n),
Color(c),
PrintType(t),
Adhesive(a)
{
}
//---------------------------------------------------------------------------
__fastcall TLabelType::TLabelType(const TLabelType& Label)
: ModelNumber(Label.ModelNumber),
Name(Label.Name),
Color(Label.Color),
PrintType(Label.PrintType),
Adhesive(Label.Adhesive)
{
}
//---------------------------------------------------------------------------
. . .
//---------------------------------------------------------------------------
TAdhesive __fastcall TLabelType::getAdhesive() const
{
return Adhesive;
}
//---------------------------------------------------------------------------
|
Using the main() function, a test of the program would be as follows:
//---------------------------------------------------------------------------
#include <iostream.h>
#pragma hdrstop
//---------------------------------------------------------------------------
#include "LabelType.h"
//---------------------------------------------------------------------------
#pragma argsused
int main(int argc, char* argv[])
{
TLabelType Label;
cout << "A label with default characteristics";
cout << "\nModel Number: " << Label.getModelNumber();
cout << "\nModel Name: " << Label.getName();
cout << "\nMain Color: " << Label.getColor();
cout << "\nPrinting Type: " << Label.getPrintType();
cout << "\nAdhesive Type: " << Label.getAdhesive();
cout << "\n\n";
Label.setModelNumber(475832);
Label.setName("Blanc d'Azure");
Label.setColor("Old Sand");
Label.setPrintType(2);
Label.setAdhesive(adRemovable);
cout << "Custom Label";
cout << "\nModel Number: " << Label.getModelNumber();
cout << "\nModel Name: " << Label.getName();
cout << "\nMain Color: " << Label.getColor();
cout << "\nPrinting Type: " << Label.getPrintType();
cout << "\nAdhesive Type: " << Label.getAdhesive();
cout << "\n\nPress any key to continue...";
getchar();
return 0;
}
//---------------------------------------------------------------------------
|
|
Using Enumerators and Classes |
- Start Borland C++ Builder. Create a new C++ based Console Application using the Console
Wizard
- Save the project in a new folder called Student2. Save the unit1 as Main and the project as ROSH
- Create a new unit and save it as Students
- Create the header file as follows:
//---------------------------------------------------------------------------
#ifndef StudentsH
#define StudentsH
#include <iostream.h>
//---------------------------------------------------------------------------
enum TStudentGender { sgUnspecified, sgMale, sgFemale };
//---------------------------------------------------------------------------
class TStudents
{
public:
__fastcall TStudents();
__fastcall TStudents(string fn, string ln,
int DOB, int MOB, int YOB, int g);
__fastcall TStudents(string fn, string ln);
__fastcall TStudents(int DOB, int MOB, int YOB);
__fastcall TStudents(const TStudents& S);
__fastcall ~TStudents();
void __fastcall setFirstName(const string f) { FirstName = f; }
string __fastcall getFirstName() const { return FirstName; }
void __fastcall setLastName(const string l) { LastName = l; }
string __fastcall getLastName() const { return LastName; }
void __fastcall setDayOfBirth(const int d) { DayOfBirth = d; }
int __fastcall getDayOfBirth() const { return DayOfBirth; }
void __fastcall setMonthOfBirth(const int m) { MonthOfBirth = m; }
int __fastcall getMonthOfBirth() const { return MonthOfBirth; }
void __fastcall setYearOfBirth(const int y) { YearOfBirth = y; }
int __fastcall getYearOfBirth() const { return YearOfBirth; }
void __fastcall setGender(const int g) { Gender = g; }
string __fastcall getGender() const;
private:
string FirstName;
string LastName;
int DayOfBirth;
int MonthOfBirth;
int YearOfBirth;
int Gender;
};
//---------------------------------------------------------------------------
#endif
|
- Implement the source file as follows:
//---------------------------------------------------------------------------
#pragma hdrstop
#include "Students.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
__fastcall TStudents::TStudents()
: FirstName("John"),
LastName("Doe"),
DayOfBirth(5),
MonthOfBirth(10),
YearOfBirth(1988),
Gender(0)
{
}
//---------------------------------------------------------------------------
__fastcall TStudents::TStudents(string fn, string ln,
int DOB, int MOB, int YOB, int g)
: FirstName(fn), LastName(ln),
DayOfBirth(DOB), MonthOfBirth(MOB), YearOfBirth(YOB), Gender(g)
{
}
//---------------------------------------------------------------------------
__fastcall TStudents::TStudents(string fn, string ln)
: FirstName(fn), LastName(ln),
DayOfBirth(1), MonthOfBirth(1), YearOfBirth(1990)
{
}
//---------------------------------------------------------------------------
__fastcall TStudents::TStudents(int DOB, int MOB, int YOB)
{
FirstName = "Peter";
LastName = "Mukoko";
DayOfBirth = DOB;
MonthOfBirth = MOB;
YearOfBirth = YOB;
}
//---------------------------------------------------------------------------
__fastcall TStudents::TStudents(const TStudents& Stud)
: FirstName(Stud.FirstName), LastName(Stud.LastName),
DayOfBirth(Stud.DayOfBirth), MonthOfBirth(Stud.MonthOfBirth),
YearOfBirth(Stud.YearOfBirth), Gender(Stud.Gender)
{
}
//---------------------------------------------------------------------------
__fastcall TStudents::~TStudents()
{
}
//---------------------------------------------------------------------------
string __fastcall TStudents::getGender() const
{
if( Gender == sgMale )
return "Male";
else if( Gender == sgFemale )
return "Female";
else
return "Unspecified";
}
//---------------------------------------------------------------------------
|
- To prepare a test of the program, change the content of the Main.cpp file as follows:
//---------------------------------------------------------------------------
#include <iomanip.h>
#include <conio.h>
#pragma hdrstop
//---------------------------------------------------------------------------
#include "Students.h"
#pragma argsused
//---------------------------------------------------------------------------
int main(int argc, char* argv[])
{
TStudents S;
string FN, LN;
int Day, Month, Year, Gdr;
cout << "Enter the student's information\n";
cout << "First Name: "; cin >> FN;
cout << "Last Name: "; cin >> LN;
cout << "Day of Birth: "; cin >> Day;
cout << "Month of Birth: "; cin >> Month;
cout << "Year of Birth: "; cin >> Year;
cout << "Gender: ";
cout << "\n1 - Male"
<< "\n2 - Female"
<< "\n3 - Unspecified"
<< "\nYour Choice: ";
cin >> Gdr;
S.setFirstName(FN);
S.setLastName(LN);
S.setDayOfBirth(Day);
S.setMonthOfBirth(Month);
S.setYearOfBirth(Year);
S.setGender(Gdr);
system("cls");
cout << "=======================================";
cout << "\nStudent Registration";
cout << "\nFull Name: "
<< S.getFirstName() << " "
<< S.getLastName();
cout << "\nDate of Birth: "
<< S.getDayOfBirth() << "/"
<< S.getMonthOfBirth() << "/"
<< S.getYearOfBirth();
cout << "\nGender: " << S.getGender();
cout << "\n\nPress any key to continue...";
getchar();
return 0;
}
//---------------------------------------------------------------------------
|
- To test the program, on the main menu, click Run -> Run.
- After testing the program, return to Bcb.
Direct Access of a Member of Another Object |
|
The most basic technique of making one object a member of another is to simply declare it as if it were a (regular) member variable, using the same technique you would for another variable. Suppose you add the following class to the label project:
//---------------------------------------------------------------------------
#ifndef LabelDimensionsH
#define LabelDimensionsH
#include <system.hpp>
//---------------------------------------------------------------------------
class TDimensions
{
public:
__fastcall TDimensions(Double L = 0.00, Double W = 0.00);
__fastcall ~TDimensions();
void __fastcall setDimensions(const Double L, const Double H);
Double __fastcall getLength() const { return Length; }
Double __fastcall getHeight() const { return Height; }
Double __fastcall Area() const;
private:
Double Length;
Double Height;
};
//---------------------------------------------------------------------------
#endif
|
And suppose you implement the class as follows:
//---------------------------------------------------------------------------
#pragma hdrstop
#include "LabelDimensions.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
//---------------------------------------------------------------------------
__fastcall TDimensions::TDimensions(Double L, Double W)
: Length(L), Height(H)
{
//TODO: Add your source code here
}
//---------------------------------------------------------------------------
__fastcall TDimensions::~TDimensions()
{
//TODO: Add your source code here
}
//---------------------------------------------------------------------------
void __fastcall TDimensions::setDimensions(const Double L, const Double H)
{
Length = L;
Height = H;
}
//---------------------------------------------------------------------------
Double __fastcall TDimensions::Area() const
{
return Length * Height;
}
//---------------------------------------------------------------------------
|
Here is an example of making it a member of the TLabelType class:
//---------------------------------------------------------------------------
#ifndef LabelTypeH
#define LabelTypeH
//---------------------------------------------------------------------------
#include <iostream.h>
#include <system.hpp>
#include "LabelDimensions.h"
//---------------------------------------------------------------------------
enum TPrintCategory { pcInkjet = 1, pcLaser, pcMultiPurpose, pcUnspecified };
enum TAdhesive { adNone, adRemovable, adNonRemovable };
//---------------------------------------------------------------------------
class TLabelType
{
public:
. . .
TDimensions Dim;
private:
. . .
};
//---------------------------------------------------------------------------
#endif
|
|
When an object B is made a member of another object A, you can access the member variables of the member object B using the member access operator (.). As a result, you would be using two period operators. After declaring the main object, the first operator is used to access the members of the main object, usually the constructor. The second operator, if used, allows accessing a member of the dependent object. Here is an example:
//---------------------------------------------------------------------------
#include <iomanip.h>
#pragma hdrstop
//---------------------------------------------------------------------------
#include "LabelType.h"
#include "LabelDimensions.h"
//---------------------------------------------------------------------------
#pragma argsused
int main(int argc, char* argv[])
{
TLabelType LblType;
string AdhesiveType;
cout << "A label with default characteristics";
cout << setiosflags(ios::fixed) << setprecision(2);
cout << "\n Dimensions: "
<< LblType.Dim.getLength() << " * " << LblType.Dim.getHeight();
cout << "\n Area: " << LblType.Dim.Area();
cout << "\n Model Number: " << LblType.getModelNumber();
cout << "\n Model Name: " << LblType.getName();
cout << "\n Main Color: " << LblType.getColor();
cout << "\n Printing Type: " << LblType.getPrintType();
cout << "\n Adhesive Type: " << LblType.getAdhesive();
cout << "\n\n";
LblType.Dim.setDimensions(4.25, 2.50);
LblType.setModelNumber(38946);
LblType.setName("Coast Layer");
LblType.setColor("Bone White");
LblType.setPrintType(2);
LblType.setAdhesive(adRemovable);
if( LblType.getAdhesive() == adRemovable )
AdhesiveType = "Removable";
else if( LblType.getAdhesive() == adNonRemovable )
AdhesiveType = "Non-Removable";
else
AdhesiveType = "None";
cout << "Customer Defined Label";
cout << "\n Dimensions: "
<< LblType.Dim.getLength() << " * " << LblType.Dim.getHeight();
cout << "\n Area: " << LblType.Dim.Area();
cout << "\n Model Number: " << LblType.getModelNumber();
cout << "\n Model Name: " << LblType.getName();
cout << "\n Main Color: " << LblType.getColor();
cout << "\n Printing Type: " << LblType.getPrintType();
cout << "\n Adhesive Type: " << AdhesiveType;
cout << "\n\nPress any key to continue...";
getchar();
return 0;
}
//---------------------------------------------------------------------------
|
The period operator can also be used when allowing the user to provide the properties of the object. Using this ability, you can design a program to request the needed values.
|
An Object as a Member Variable |
- Add a new unit and save it as Grades
- To declare one object as a member of another object, add a new unit saved as Grades and create its TGrades class as follows:
//---------------------------------------------------------------------------
#ifndef GradesH
#define GradesH
#include "Students.h"
//---------------------------------------------------------------------------
class TGrades
{
public:
__fastcall TGrades();
__fastcall TGrades(double e, double s, double h,
double g, double c, double o,
double m, double p, double r, double t);
__fastcall ~TGrades();
void __fastcall setEnglish(const double e) { English = e; }
double __fastcall getEnglish() const { return English; }
void __fastcall setSecondLng(const double s) { SecondLng = s; }
double __fastcall getSecondLng() const { return SecondLng; }
void __fastcall setHistory(const double h) { History = h; }
double __fastcall getHistory() const { return History; }
void __fastcall setGeography(const double g) { Geography = g; }
double __fastcall getGeography() const { return Geography; }
void __fastcall setChemistry(const double c) { Chemistry = c; }
double __fastcall getChemistry() const { return Chemistry; }
void __fastcall setSociology(const double o) { Sociology = o; }
double __fastcall getSociology() const { return Sociology; }
void __fastcall setMath(const double m) { Math = m; }
double __fastcall getMath() const { return Math; }
void __fastcall setCompSc(const double p) { CompSc = p; }
double __fastcall getCompSc() const { return CompSc; }
void __fastcall setMorale(const double a) { Morale = a; }
double __fastcall getMorale() const { return Morale; }
void __fastcall setSports(const double t) { Sports = t; }
double __fastcall getSports() const { return Sports; }
double __fastcall CalcTotal() const;
double __fastcall CalcMean() const;
TStudents Identification;
private:
double English;
double SecondLng;
double History;
double Geography;
double Chemistry;
double Sociology;
double Math;
double CompSc;
double Morale;
double Sports;
};
//---------------------------------------------------------------------------
#endif
|
- Implement the TGrades class as follows:
//---------------------------------------------------------------------------
#pragma hdrstop
#include "Grades.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
__fastcall TGrades::TGrades()
{
English = 0.00;
SecondLng = 0.00;
History = 0.00;
Geography = 0.00;
Chemistry = 0.00;
Sociology = 0.00;
Math = 0.00;
CompSc = 0.00;
Morale = 0.00;
Sports = 0.00;
}
//---------------------------------------------------------------------------
__fastcall TGrades::TGrades(double e, double s, double h,
double g, double c, double o,
double m, double p, double r, double t)
{
English = e;
SecondLng = s;
History = h;
Geography = g;
Chemistry = c;
Sociology = o;
Math = m;
CompSc = p;
Morale = r;
Sports = t;
}
//---------------------------------------------------------------------------
__fastcall TGrades::~TGrades()
{
//TODO: Add your source code here
}
//---------------------------------------------------------------------------
double __fastcall TGrades::CalcTotal() const
{
double Total = English + SecondLng + History +
Geography + Chemistry + Sociology +
Math + CompSc + Morale + Sports;
return Total;
}
//---------------------------------------------------------------------------
double __fastcall TGrades::CalcMean() const
{
return CalcTotal() / 10;
}
//---------------------------------------------------------------------------
|
- To prepare a test of the program, change the Main.cpp file as follows:
//---------------------------------------------------------------------------
#include <iomanip.h>
#include <conio.h>
#pragma hdrstop
//---------------------------------------------------------------------------
#include "Grades.h"
#pragma argsused
//---------------------------------------------------------------------------
int main(int argc, char* argv[])
{
TGrades G;
string FN, LN;
int Day, Month, Year, Gdr;
cout << "Enter the student's information\n";
cout << "First Name: "; cin >> FN;
cout << "Last Name: "; cin >> LN;
cout << "Day of Birth: "; cin >> Day;
cout << "Month of Birth: "; cin >> Month;
cout << "Year of Birth: "; cin >> Year;
cout << "Gender: ";
cout << "\n1 - Male"
<< "\n2 - Female"
<< "\n3 - Unspecified"
<< "\nYour Choice: ";
cin >> Gdr;
G.Identification.setFirstName(FN);
G.Identification.setFirstName(FN);
G.Identification.setLastName(LN);
G.Identification.setDayOfBirth(Day);
G.Identification.setMonthOfBirth(Month);
G.Identification.setYearOfBirth(Year);
G.Identification.setGender(Gdr);
double Language1, Language2, Hist, Geog, Chem, Soc,
Math, CompSc, Mor, Sport;
cout << "English: "; cin >> Language1;
cout << "2nd Language: "; cin >> Language2;
cout << "History: "; cin >> Hist;
cout << "Geography: "; cin >> Geog;
cout << "Chemistry: "; cin >> Chem;
cout << "Sociology: "; cin >> Soc;
cout << "Mathematics: "; cin >> Math;
cout << "Comp Sciences: "; cin >> CompSc;
cout << "Morale: "; cin >> Mor;
cout << "Sports: "; cin >> Sport;
G.setEnglish(Language1);
G.setSecondLng(Language2);
G.setHistory(Hist);
G.setGeography(Geog);
G.setChemistry(Chem);
G.setSociology(Soc);
G.setMath(Math);
G.setCompSc(CompSc);
G.setMorale(Mor);
G.setSports(Sport);
system("cls");
cout << "=======================================";
cout << "\nStudent Registration";
cout << "\nFull Name: "
<< G.Identification.getFirstName() << " "
<< G.Identification.getLastName();
cout << "\nDate of Birth: "
<< G.Identification.getDayOfBirth() << "/"
<< G.Identification.getMonthOfBirth() << "/"
<< G.Identification.getYearOfBirth();
cout << "\nGender: " << G.Identification.getGender();
cout << "\n------------------------------------------";
cout << setiosflags(ios::fixed) << setprecision(2);
cout << "\n\tEnglish: " << G.getEnglish();
cout << "\n\tLanguage 2: " << G.getSecondLng();
cout << "\n\tHistory: " << G.getHistory();
cout << "\n\tGeography: " << G.getGeography();
cout << "\n\tChemistry: " << G.getChemistry();
cout << "\n\tSociology: " << G.getSociology();
cout << "\n\tMathematics: " << G.getMath();
cout << "\n\tComp Sciences: " << G.getCompSc();
cout << "\n\tMorale: " << G.getMorale();
cout << "\n\tSports: " << G.getSports();
cout << "\n------------------------------------------";
cout << "\n\tTotal: " << G.CalcTotal()
<< "\tMean: " << G.CalcMean();
cout << "\n=======================================";
cout << "\n\nPress any key to continue...";
getchar();
return 0;
}
//---------------------------------------------------------------------------
|
- To test the program, on the Debug toolbar, click the Run button . An example would be:
- Return to Bcb.
Like a function, a class can be made a friend of another class. When class A is made a friend of class B, all members of class B are directly accessible to the members of class A; this includes private (and protected) members:
Friendship is not mutual: the fact that class A is made a friend of class B does not imply that class B is made a friend of class A. In other words, the fact that the (private and protected) members of class B are accessible to the members of class A does not mean that the members of class A area accessible to the members of class B.To process an order for labels, suppose you create the following class:
//---------------------------------------------------------------------------
#ifndef LabelsH
#define LabelsH
#include <system.hpp>
//---------------------------------------------------------------------------
class TLabels
{
public:
__fastcall TLabels();
__fastcall TLabels(const TLabels& L);
__fastcall ~TLabels();
void __fastcall ProcessALabel();
void __fastcall setPrice(const Double p) { Price = p; }
Double __fastcall getPrice() const { return Price; }
void __fastcall ShowReceipt();
private:
Double Price;
};
//---------------------------------------------------------------------------
#endif
|
And suppose you implement it as follows:
//---------------------------------------------------------------------------
#pragma hdrstop
#include "Labels.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
__fastcall TLabels::TLabels()
: Price(0.00)
{
}
//---------------------------------------------------------------------------
__fastcall TLabels::TLabels(const TLabels& L)
: Price(L.Price)
{
}
//---------------------------------------------------------------------------
__fastcall TLabels::~TLabels()
{
}
//---------------------------------------------------------------------------
void __fastcall TLabels::ProcessALabel()
{
// Get the dimensions of the label
// Get the label's characteristics
}
//---------------------------------------------------------------------------
void __fastcall TLabels::ShowReceipt()
{
cout << "Label Order - Receipt";
cout << "\n\tDimensions: ";
cout << "\n\tArea: ";
cout << "\n\tModel No.: ";
cout << "\n\tModel Name: ";
cout << "\n\tColor: ";
cout << "\n\tAdhesive: ";
cout << "\n\tPrice: "
<< setiosflags(ios::fixed) << setprecision(2)
<< Price;
}
//---------------------------------------------------------------------------
|
To effectively process an order, the new class needs access to the dimensions and the characteristics of the label, which reside in two different classes. Therefore, we will give it unlimited access to the appropriate classes.
To make one class a friend of another, in the body of the class that is granting the friendship, type
friend class ClassName;
The keywords friend and class are required. The ClassName is the name of the class that needs friendship. Here is an example:
//---------------------------------------------------------------------------
#ifndef LabelDimensionsH
#define LabelDimensionsH
#include <system.hpp>
//---------------------------------------------------------------------------
class TDimensions
{
friend class TLabels;
public:
__fastcall TDimensions(Double L = 0.00, Double W = 0.00);
__fastcall ~TDimensions();
void __fastcall setDimensions(const Double L, const Double H);
Double __fastcall getLength() const { return Length; }
Double __fastcall getHeight() const { return Height; }
Double __fastcall Area() const;
private:
Double Length;
Double Height;
};
//---------------------------------------------------------------------------
#endif
|
A class can be made a friend of as many classes as necessary, as illustrated in the following other example:
//---------------------------------------------------------------------------
#ifndef LabelTypeH
#define LabelTypeH
//---------------------------------------------------------------------------
#include <iostream.h>
#include <system.hpp>
#include "LabelDimensions.h"
//---------------------------------------------------------------------------
enum TPrintCategory { pcInkjet = 1, pcLaser, pcMultiPurpose, pcUnspecified };
enum TAdhesive { adNone, adRemovable, adNonRemovable };
//---------------------------------------------------------------------------
class TLabelType
{
friend class TLabels;
public:
. . .
string __fastcall getPrintType() const;
TAdhesive __fastcall getAdhesive() const;
private:
Cardinal ModelNumber;
string Name;
string Color;
Integer PrintType;
TAdhesive Adhesive;
};
//---------------------------------------------------------------------------
#endif
|
Notice that, since a class used to process an order will also specify the dimensions, we do not need a TLabelDimensions member variable anymore. Now that the TLabels class has direct access to the other classes, we restructure it as
follows:
//---------------------------------------------------------------------------
#ifndef LabelsH
#define LabelsH
#include <system.hpp>
#include "LabelType.h"
#include "LabelDimensions.h"
//---------------------------------------------------------------------------
class TLabels
{
public:
__fastcall TLabels();
__fastcall TLabels(const TLabels& L);
__fastcall ~TLabels();
void __fastcall GetLabelDimensions(TDimensions& Dim);
void __fastcall GetLabelCharacteristics(TLabelType& Label);
void __fastcall setPrice(const Double p) { Price = p; }
Double __fastcall getPrice() const { return Price; }
void __fastcall ShowReceipt(const TDimensions& Dim,
const TLabelType& Label);
private:
Double Price;
};
//---------------------------------------------------------------------------
#endif
|
To implement these functions, keep in mind that we have access to the private members of the other classes. This means that we can initialize their member or request their values without declaring variables to hold these values. Here is their implementations:
//---------------------------------------------------------------------------
#include <iomanip.h>
#pragma hdrstop
#include "Labels.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
__fastcall TLabels::TLabels()
: Price(0.00)
{
}
//---------------------------------------------------------------------------
__fastcall TLabels::TLabels(const TLabels& L)
: Price(L.Price)
{
}
//---------------------------------------------------------------------------
__fastcall TLabels::~TLabels()
{
}
//---------------------------------------------------------------------------
void __fastcall TLabels::GetLabelDimensions(TDimensions& Rect)
{
cout << "Enter dimensions of the label\n";
cout << "Length: ";
cin >> Rect.Length;
cout << "Height: ";
cin >> Rect.Height;
Double A = Rect.Area();
if( A <= 1.00 )
Price = 10.95;
else if( A <= 2.625 )
Price = 12.95;
else if( A <= 4.15 )
Price = 14.95;
else if( A <= 10.00 )
Price = 18.95;
else
Price = 26.95;
}
//---------------------------------------------------------------------------
void __fastcall TLabels::GetLabelCharacteristics(TLabelType& Label)
{
Char LabelName[32], LabelColor[32];
Integer AdhesiveType;
Integer PrtType;
cout << "Enter the characteristics of the label\n";
cout << "Model Number: ";
cin >> Label.ModelNumber;
cout << "Type or Name: ";
gets(LabelName);
cout << "Label Color: ";
gets(LabelColor);
cout << "Adhesive Type"
<< "\n0 - No adhesive"
<< "\n1 - Removable Adhesive"
<< "\n2 - Non-Removable Adhesive"
<< "\nYour Choice: ";
cin >> AdhesiveType;
if( AdhesiveType == 1 )
Label.Adhesive = adRemovable;
else if( AdhesiveType == 2 )
Label.Adhesive = adNonRemovable;
else
Label.Adhesive = adNone;
cout << "Printing Type"
<< "\n1 - Inkjet"
<< "\n2 - Laser"
<< "\n3 - Multi-Purpose"
<< "\n4 - Unspecified"
<< "\nYour Choice: ";
cin >> Label.PrintType;
Label.Name = LabelName;
Label.Color = LabelColor;
}
//---------------------------------------------------------------------------
void __fastcall TLabels::ShowReceipt(const TDimensions& Rect,
const TLabelType& Label)
{
TAdhesive Type = Label.getAdhesive();
cout << "=================================";
cout << "\n - Pacific Office Store -";
cout << "\n=================================";
cout << "\n Label Order - Receipt";
cout << "\n---------------------------------\n";
cout << "\n Dimensions: "
<< setiosflags(ios::fixed) << setprecision(2)
<< Rect.getLength() << " * " << Rect.getHeight();
cout << "\n Model No.: " << Label.getModelNumber();
cout << "\n Model Name: " << Label.getName();
cout << "\n Color: " << Label.getColor();
cout << "\n Adhesive: ";
if( Type == adRemovable )
cout << "Removable";
else if( Type == adNonRemovable )
cout << "Non-Removable";
else
cout << "None";
cout << "\n Print Type: " << Label.getPrintType();
cout << "\n Price: " << Price;
cout << "\n=================================";
}
//---------------------------------------------------------------------------
|
The composition of classes performed on our objects allows us now to process an order and display its receipt:
//---------------------------------------------------------------------------
#include <iomanip.h>
#include <conio.h>
#pragma hdrstop
//---------------------------------------------------------------------------
#include "Labels.h"
//---------------------------------------------------------------------------
#pragma argsused
int main(int argc, char* argv[])
{
TLabels Label;
TDimensions Dim;
TLabelType Type;
cout << "Welcome to Pacific Office Store\n";
cout << "This machine allows you to create labels\nto the desired "
<< "dimensions and custom characteristics\n";
Label.GetLabelDimensions(Dim);
Label.GetLabelCharacteristics(Type);
system("cls");
Label.ShowReceipt(Dim, Type);
cout << "\n\nPress any key to continue...";
getchar();
return 0;
}
//---------------------------------------------------------------------------
|
|
Combining Objects |
- To prepare a class that woud handle student and grade registration, add a new unit. Save it as GradeReport
- In the GradeReport.h file, create the foundation of the class as follows:
//---------------------------------------------------------------------------
#ifndef GradeReportH
#define GradeReportH
//---------------------------------------------------------------------------
class TGradeReport
{
public:
private:
};
//---------------------------------------------------------------------------
#endif
|
- Open the Students.h and declare a friend class as follows:
//---------------------------------------------------------------------------
#ifndef StudentsH
#define StudentsH
#include <iostream.h>
//---------------------------------------------------------------------------
enum TStudentGender { sgUnspecified, sgMale, sgFemale };
//---------------------------------------------------------------------------
class TStudents
{
friend class TGradeReport;
public:
. . .
private:
. . .
};
//---------------------------------------------------------------------------
#endif
|
- Open the Grades.h file and declare friend class as follows:
//---------------------------------------------------------------------------
#ifndef GradesH
#define GradesH
#include "Students.h"
//---------------------------------------------------------------------------
class TGrades
{
friend class TGradeReport;
public:
. . .
private:
. . .
};
//---------------------------------------------------------------------------
#endi
|
- To process the registration or the grades, instead of passing the class variables by reference as we have seen already, we will change a little bit by returning the class from the function that will need them (this allows us to test both techniques of returning an object). This is just another way to get the same information. To create the new class, change the content of the GradeReport.h file as follows:
//---------------------------------------------------------------------------
#ifndef GradeReportH
#define GradeReportH
#include <iostream.h>
#include "Students.h"
#include "Grades.h"
//---------------------------------------------------------------------------
struct TGradeInfo
{
int Level;
string MajorCode;
string MajorName;
};
//---------------------------------------------------------------------------
class TGradeReport
{
public:
__fastcall TGradeReport();
__fastcall ~TGradeReport();
TStudents __fastcall Registration();
TGrades __fastcall GetGrades();
void __fastcall ShowReport(const TStudents Student, const TGrades Grd);
private:
TGradeInfo LevelInfo;
};
//---------------------------------------------------------------------------
#endif
|
- To implement the new class, change the GradeReport.cpp as follows:
//---------------------------------------------------------------------------
#include <iomanip.h>
#pragma hdrstop
#include "GradeReport.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
__fastcall TGradeReport::TGradeReport()
{
}
//---------------------------------------------------------------------------
__fastcall TGradeReport::~TGradeReport()
{
}
//---------------------------------------------------------------------------
TStudents __fastcall TGradeReport::Registration()
{
TStudents Student;
int Gender;
cout << "Enter the student's information\n";
cout << "First Name: "; cin >> Student.FirstName;
cout << "Last Name: "; cin >> Student.LastName;
cout << "Day of Birth: "; cin >> Student.DayOfBirth;
cout << "Month of Birth: "; cin >> Student.MonthOfBirth;
cout << "Year of Birth: "; cin >> Student.YearOfBirth;
out << "Gender: ";
cout << "\n1 - Male"
<< "\n2 - Female"
<< "\n3 - Unspecified"
<< "\nYour Choice: ";
cin >> Gender;
Student.setGender(Gender);
cout << "Grade Level(6, 5, 4, etc): ";
cin >> LevelInfo.Level;
cout << "Major Code (A4, F1, G2, etc): ";
cin >> LevelInfo.MajorCode;
cout << "Major Name (Ex.: American Indian History, SocioMafia):\n";
getline(cin, LevelInfo.MajorName);
return Student;
}
//---------------------------------------------------------------------------
TGrades __fastcall TGradeReport::GetGrades()
{
TGrades Grade;
double Language1, Language2, Hist, Geog, Chem, Soc,
Math, CompSc, Mor, Sport;
cout << "\nEnter Student Grades\n";
cout << "English: "; cin >> Grade.English;
cout << "2nd Language: "; cin >> Grade.SecondLng;
cout << "History: "; cin >> Grade.History;
cout << "Geography: "; cin >> Grade.Geography;
cout << "Chemistry: "; cin >> Grade.Chemistry;
cout << "Sociology: "; cin >> Grade.Sociology;
cout << "Mathematics: "; cin >> Grade.Math;
cout << "Comp Sciences: "; cin >> Grade.CompSc;
cout << "Morale: "; cin >> Grade.Morale;
cout << "Sports: "; cin >> Grade.Sports;
return Grade;
}
//---------------------------------------------------------------------------
void __fastcall TGradeReport::ShowReport(const TStudents Student,
const TGrades Grade)
{
cout << "=======================================";
cout << "\nStudent Personal Information";
cout << "\nFull Name: "
<< Student.getFirstName() << " "
<< Student.getLastName();
cout << "\nDate of Birth: "
<< Student.getDayOfBirth() << "/"
<< Student.getMonthOfBirth() << "/"
<< Student.getYearOfBirth();
cout << "\nGender: " << Student.getGender();
cout << "\nGrade Level: " << LevelInfo.Level;
cout << "\nMajor: "
<< LevelInfo.MajorCode << ": "
<< LevelInfo.MajorName;
cout << "\n---------------------------------------";
cout << setiosflags(ios::fixed) << setprecision(2);
cout << "\n\tEnglish: " << Grade.getEnglish();
cout << "\n\t2nd Language: " << Grade.getSecondLng();
cout << "\n\tHistory: " << Grade.getHistory();
cout << "\n\tGeography: " << Grade.getGeography();
cout << "\n\tChemistry: " << Grade.getChemistry();
cout << "\n\tSociology: " << Grade.getSociology();
cout << "\n\tMathematics: " << Grade.getMath();
cout << "\n\tComp Sciences: " << Grade.getCompSc();
cout << "\n\tMorale: " << Grade.getMorale();
cout << "\n\tSports: " << Grade.getSports();
cout << "\n---------------------------------------";
cout << "\n\tTotal: " << Grade.CalcTotal()
<< "\tMean: " << Grade.CalcMean();
cout << "\n=======================================";
}
//---------------------------------------------------------------------------
|
- The main() function can be used simply to call the functions that can take of any needed transaction. As an example, change the Main.cpp file as follows:
//---------------------------------------------------------------------------
#include <iomanip.h>
#pragma hdrstop
//---------------------------------------------------------------------------
#include "Grades.h"
#include "Students.h"
#include "GradeReport.h"
#pragma argsused
//---------------------------------------------------------------------------
int main(int argc, char* argv[])
{
TGradeReport Report;
TStudents Student;
TGrades Grade;
Student = Report.Registration();
Grade = Report.GetGrades();
system("cls");
Report.ShowReport(Student, Grade);
cout << "\n\nPress any key to continue...";
getchar();
return 0;
}
//---------------------------------------------------------------------------
|
- Test the program:
- Return to Bcb
The ability to use already created objects is one of the strengths of C++. If you have a ready made object, you can construct a new one using the existing properties. Inheritance is the ability to create an object using, or based on, another. The new or inherited object is also said to derive, or be derived from, the other object.
There are various ways you can inherit an object: using an operating system object, basing an object on an existing C++ one, or creating an object from a C++ Builder class. To start, you should define an object as complete as possible. This means that it should have functionality, valuable properties, and behaviors that other objects can use with little concerns as to how the object is built, but trusting that it can handle the desired behavior.
Creating the Parent Object |
|
We will create an object that others can inherit from. We will build a brick used in construction. A brick is known by its length, height, and width; but it also has a rectangular base. Therefore, let’s build the base first.The header file of TRectangle creates an object with its dimensions as follows:
//---------------------------------------------------------------------------
#ifndef RectangleH
#define RectangleH
//---------------------------------------------------------------------------
class TRectangle
{
public:
__fastcall TRectangle(double L = 0.00, double H = 0.00);
__fastcall TRectangle(const TRectangle& r);
__fastcall ~TRectangle();
void __fastcall setLength(const double L);
void __fastcall setHeight(const double H);
void __fastcall setDimensions(const double L, const double H);
double __fastcall getLength() const;
double __fastcall getHeight() const;
double __fastcall Perimeter() const;
double __fastcall Area() const;
private:
double Length;
double Height;
};
//---------------------------------------------------------------------------
#endif
|
The source file defines the object with its constructors, provides access to its members and calculates the area of the base:
//---------------------------------------------------------------------------
#pragma hdrstop
#include "Rectangle.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
//---------------------------------------------------------------------------
__fastcall TRectangle::TRectangle(double L, double H)
: Length(L), Height(H)
{
}
//---------------------------------------------------------------------------
__fastcall TRectangle::TRectangle(const TRectangle& Rect)
: Length(Rect.Length), Height(Rect.Height)
{
}
//---------------------------------------------------------------------------
__fastcall TRectangle::~TRectangle()
{
}
//---------------------------------------------------------------------------
void __fastcall TRectangle::setLength(const double L)
{
Length = L;
}
//---------------------------------------------------------------------------
void __fastcall TRectangle::setHeight(const double H)
{
Height = H;
}
//---------------------------------------------------------------------------
void __fastcall TRectangle::setDimensions(const double L, const double H)
{
setLength(L);
setHeight(H);
}
//---------------------------------------------------------------------------
double __fastcall TRectangle::getLength() const
{
return Length;
}
//---------------------------------------------------------------------------
double __fastcall TRectangle::getHeight() const
{
return Height;
}
//---------------------------------------------------------------------------
double __fastcall TRectangle::Perimeter() const
{
return 2 * (Length + Height);
}
//---------------------------------------------------------------------------
double __fastcall TRectangle::Area() const
{
return Length * Height;
}
//---------------------------------------------------------------------------
|
To test the object, we will use the main() function. To make sure the object can respond, we test it with its default values. Then we supply its dimensions and display it. Finally, we make a copy of the object and test that copy.
//---------------------------------------------------------------------------
#include <iomanip.h>
#pragma hdrstop
//---------------------------------------------------------------------------
#include "Rectangle.h"
#pragma argsused
//---------------------------------------------------------------------------
void __fastcall RectProperties(const TRectangle& R)
{
cout << "Characteristics of the rectangle";
cout << setiosflags(ios::fixed) << setprecision(2);
cout << "\nLength: " << R.getLength();
cout << "\nHeight: " << R.getHeight();
cout << "\nPerimeter: " << R.Perimeter();
cout << "\nArea: " << R.Area();
}
//---------------------------------------------------------------------------
int main(int argc, char* argv[])
{
TRectangle Rect1;
double L = 12.125, H = 8.625; // Rectangle with default dimensions
TRectangle Rect2(L, H); // Rectangle with supplied dimensions
TRectangle Rect3; // Will be used to make/test a copy
cout << "Properties of the rectangle with default values";
RectProperties(Rect1);
cout << "\n\nRectangle with provided dimensions";
RectProperties(Rect2);
Rect3 = Rect2;
cout << "\n\nA copy of an existing rectangle";
RectProperties(Rect3);
cout << "\n\nPress any key to continue...";
getchar();
return 0;
}
//---------------------------------------------------------------------------
|
|
Creating a Parent Object |
- Start a new C++ Console Application using the Console Wizard. Save the project in a folder called
People
- Save the unit as Main and the project as Basis
- Add a new unit and save it as Person
- To create a base class, change the header file as follows:
//---------------------------------------------------------------------------
#ifndef PersonH
#define PersonH
#include <iostream.h>
//---------------------------------------------------------------------------
class TPerson
{
public:
__fastcall TPerson(string fn = "", string ln = "");
__fastcall TPerson(const TPerson& P);
__fastcall ~TPerson();
void __fastcall setFirstName(const string f);
string __fastcall getFirstName() const;
void __fastcall setLastName(const string l);
string __fastcall getLastName() const;
private:
string FirstName;
string LastName;
};
//---------------------------------------------------------------------------
#endif
|
- Implement the source file as follows:
//---------------------------------------------------------------------------
#pragma hdrstop
#include "Person.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
//---------------------------------------------------------------------------
__fastcall TPerson::TPerson(string fn, string ln)
: FirstName(fn), LastName(ln)
{
}
//---------------------------------------------------------------------------
__fastcall TPerson::TPerson(const TPerson& P)
: FirstName(P.FirstName), LastName(P.LastName)
{
}
//---------------------------------------------------------------------------
__fastcall TPerson::~TPerson()
{
}
//---------------------------------------------------------------------------
void __fastcall TPerson::setFirstName(const string f)
{
FirstName = f;
}
//---------------------------------------------------------------------------
string __fastcall TPerson::getFirstName() const
{
return FirstName;
}
//---------------------------------------------------------------------------
void __fastcall TPerson::setLastName(const string l)
{
LastName = l;
}
//---------------------------------------------------------------------------
string __fastcall TPerson::getLastName() const
{
return LastName;
}
//---------------------------------------------------------------------------
|
- To find out whether the new class work, change the Main.cpp file as follows:
//---------------------------------------------------------------------------
#include <iostream.h>
#pragma hdrstop
//---------------------------------------------------------------------------
#include "Person.h"
#pragma argsused
//---------------------------------------------------------------------------
void __fastcall ShowInfo(const TPerson& Pers)
{
cout << "\nFull Name: " << Pers.getFirstName()
<< " " << Pers.getLastName();
}
//---------------------------------------------------------------------------
int main(int argc, char* argv[])
{
TPerson P("John", "Landis");
cout << "Personal Information";
ShowInfo(P);
cout << "\n\nPress any key to continue...";
getchar();
return 0;
}
//---------------------------------------------------------------------------
|
- Test the application and return to Bcb.
Once you have a defined object, you can apply its behavior as the starting point of another object. The basic syntax on inheriting from an object is:
structORclass NewObject : AccessLevel ParentObject;
The word structORclass will be replaced by struct or class depending on the object type you are trying to create.
The NewObject element represents the name of the object you are creating.
The colon (:) is read “is based on”. It lets the compiler know that the new object gets its starting behavior and properties from another object.
The word AccessLevel specifies whether the object will use the public or private (or protected) level of access. The most common inheritance, which is also the most we will study, is the public inheritance. If you are creating an object whose parent is a structure, you can usually omit this access level because a structure is public by default. Otherwise, you should specify the level of access.
The ParentObject is the name of the object that the new object is based or is inheriting from.
When inheriting from another object, the new object is considered a child. To get the properties of the parent object, you should declare an instance of the parent. This instance will provide access to the members of the original object. The new object will not have access to the private members of the parent.
As we now have a good working rectangle, we will use it as the base of our brick. The header file of TBox creates an object whose base is the TRectangle object. |
|
//---------------------------------------------------------------------------
#ifndef BoxH
#define BoxH
#include "Rectangle.h"
//---------------------------------------------------------------------------
class TBox : public TRectangle
{
public:
__fastcall TBox(double L = 0.00, double H = 0.00, double W = 0.00);
__fastcall TBox(const TBox& B);
__fastcall ~TBox();
void __fastcall setWidth(const double W);
void __fastcall setDimensions(const double Length,
const double Height, const double Width);
double __fastcall getWidth() const { return Width; }
double __fastcall TotalArea() const;
double __fastcall Volume() const;
private:
double Width;
};
//---------------------------------------------------------------------------
#endif
|
The source file is used to define the object. It makes sure that the new object has access to the desired properties of the parent. This is done using the access methods of the parent object called from the new constructors:
//---------------------------------------------------------------------------
#pragma hdrstop
#include "Box.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
__fastcall TBox::TBox(double L, double H, double W)
: TRectangle(L, H), Width(W)
{
}
//---------------------------------------------------------------------------
__fastcall TBox::~TBox()
{
//TODO: Add your source code here
}
//---------------------------------------------------------------------------
void __fastcall TBox::setWidth(const double W)
{
if( Width < 0.00 )
Width = 0.00;
else
Width = W;
}
//---------------------------------------------------------------------------
void __fastcall TBox::setDimensions(const double L,
const double H, const double W)
{
setLength(L);
setHeight(H);
setWidth(W);
}
//---------------------------------------------------------------------------
double __fastcall TBox::TotalArea() const
{
double Face1 = getLength() + getHeight();
double Face2 = getHeight() + getWidth();
double Face3 = getLength() + getWidth();
return (2 * Face1) + (2 * Face2) + (2 * Face3);
}
//---------------------------------------------------------------------------
double __fastcall TBox::Volume() const
{
return getLength() * getHeight() * getWidth();
}
//---------------------------------------------------------------------------
|
To test the new object, we will use the main() function. First, we will declare a Box without arguments, which means we will display it with the default dimensions. Second, we will test the Box with supplied dimensions:
//---------------------------------------------------------------------------
#include <iomanip.h>
#pragma hdrstop
//---------------------------------------------------------------------------
#include "Rectangle.h"
#include "Box.h"
#pragma argsused
//---------------------------------------------------------------------------
void __fastcall RectProperties(const TRectangle& R)
{
. . .
}
//---------------------------------------------------------------------------
void __fastcall BoxProperties(const TBox& B)
{
cout << "Characteristics of the box";
cout << setiosflags(ios::fixed) << setprecision(2);
cout << "\nLength: " << B.getLength();
cout << "\nHeight: " << B.getHeight();
cout << "\nWidth: " << B.getWidth();
cout << "\nArea: " << B.TotalArea();
cout << "\nVolume: " << B.Volume();
}
//---------------------------------------------------------------------------
int main(int argc, char* argv[])
{
TBox RedBox;
cout << "A Box with default values";
BoxProperties(RedBox);
cout << "\n\n";
TBox GrayBox(6.55, 5.25, 5.75);
cout << "Properties of the Box with dimensions";
BoxProperties(GrayBox);
cout << "\n\nPress any key to continue...";
getchar();
return 0;
}
//---------------------------------------------------------------------------
|
The protected Access Level |
|
The TBox object we created based on the TRectangle class is not very impressive. For one thing, the TBox is using the same features as any other object in order to access the member variables of its parents. This does not provide any privileged access for a child of an object. C++ provides a solution to this problem: a special relationship between an inherited object and its parent.
In the past, we learned that the public level allows the client of a class to access any member of the public section of the class. We also learned to hide other members by declaring them in the private section, which prevents the clients of class from accessing such variables. You can create a special access level that allows only the children of a class to have access to certain members of the parent class. This new access level is called protected and created with that keyword.
The box we created and inherited from the TRectangle object needs to be able to initialize a parallelepiped rectangle with the length, height, and the self-added width. To allow this relationaship, you would change the TRectangle class as follows:
//---------------------------------------------------------------------------
#ifndef RectangleH
#define RectangleH
//---------------------------------------------------------------------------
class TRectangle
{
public:
__fastcall TRectangle(double L = 0.00, double H = 0.00);
__fastcall TRectangle(const TRectangle& r);
__fastcall ~TRectangle();
void __fastcall setLength(const double L);
void __fastcall setHeight(const double H);
void __fastcall setDimensions(const double L, const double H);
double __fastcall getLength() const;
double __fastcall getHeight() const;
double __fastcall Perimeter() const;
double __fastcall Area() const;
protected:
double Length;
double Height;
};
//---------------------------------------------------------------------------
#endif
|
Since only the access level of the member variables has changed, nothing needs to be done in the implementation of the class. On the other hands, by making the member variables of the TRectangle class protected, the TBox class and its public members now have access to their parent’s protected members. This allows us the change the source file of the TBox object as follows:
//---------------------------------------------------------------------------
#pragma hdrstop
#include "Box.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
__fastcall TBox::TBox(double L, double H, double W)
: TRectangle(L, H), Width(W)
{
}
//---------------------------------------------------------------------------
__fastcall TBox::TBox(const TBox& B)
: Width(B.Width)
{
Length = B.Length;
Height = B.Height;
}
//---------------------------------------------------------------------------
__fastcall TBox::~TBox()
{
//TODO: Add your source code here
}
//---------------------------------------------------------------------------
void __fastcall TBox::setWidth(const double W)
{
if( Width < 0.00 )
Width = 0.00;
else
Width = W;
}
//---------------------------------------------------------------------------
void __fastcall TBox::setDimensions(const double L,
const double H, const double W)
{
setLength(L);
setHeight(H);
setWidth(W);
}
//---------------------------------------------------------------------------
double __fastcall TBox::TotalArea() const
{
double Face1 = Length + Height;
double Face2 = Height + Width;
double Face3 = Length + Width;
return (2 * Face1) + (2 * Face2) + (2 * Face3);
}
//---------------------------------------------------------------------------
double __fastcall TBox::Volume() const
{
return Length * Height * Width;
}
//---------------------------------------------------------------------------
|
As you can see, the derived class now has access to the member variables of the parent class and can use them to safely perform the needed calculations.
|
Inheriting Objects |
- To create a protected access level on the parent object, make the following change in the Person.h file:
//---------------------------------------------------------------------------
#ifndef PersonH
#define PersonH
#include <iostream.h>
//---------------------------------------------------------------------------
class TPerson
{
public:
__fastcall TPerson(string fn = "", string ln = "");
__fastcall TPerson(const TPerson& P);
__fastcall ~TPerson();
void __fastcall setFirstName(const string f);
string __fastcall getFirstName() const;
void __fastcall setLastName(const string l);
string __fastcall getLastName() const;
protected:
string FirstName;
string LastName;
private:
};
//---------------------------------------------------------------------------
#endif
|
- Add a new unit and save it as Student
- To derive an object from another, change the header file as follows:
#define StudentH
#include "Person.h"
//---------------------------------------------------------------------------
class TStudent : public TPerson
{
public:
__fastcall TStudent();
__fastcall TStudent(string fn, string ln,
int DOB, int MOB, int YOB, int g);
__fastcall TStudent(string fn, string ln);
__fastcall TStudent(int DOB, int MOB, int YOB);
__fastcall TStudent(const TStudent& S);
__fastcall ~TStudent();
void __fastcall setDayOfBirth(const int d) { DayOfBirth = d; }
int __fastcall getDayOfBirth() const { return DayOfBirth; }
void __fastcall setMonthOfBirth(const int m) { MonthOfBirth = m; }
int __fastcall getMonthOfBirth() const { return MonthOfBirth; }
void __fastcall setYearOfBirth(const int y) { YearOfBirth = y; }
int __fastcall getYearOfBirth() const { return YearOfBirth; }
void __fastcall setGender(const int g) { Gender = g; }
string __fastcall getGender() const;
private:
int DayOfBirth;
int MonthOfBirth;
int YearOfBirth;
int Gender;
};
//---------------------------------------------------------------------------
#endif
|
- To initialize the class using the constructor(s) of its base class, implement the new object as follows:
//---------------------------------------------------------------------------
#pragma hdrstop
#include "Student.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
__fastcall TStudent::TStudent()
: TPerson("John", "Doe"),
DayOfBirth(1),
MonthOfBirth(1),
YearOfBirth(1990),
Gender(0)
{
}
//---------------------------------------------------------------------------
__fastcall TStudent::TStudent(string fn, string ln,
int DOB, int MOB, int YOB, int g)
: TPerson(fn, ln),
DayOfBirth(DOB), MonthOfBirth(MOB), YearOfBirth(YOB), Gender(g)
{
}
//---------------------------------------------------------------------------
__fastcall TStudent::TStudent(string fn, string ln)
: TPerson(fn, ln), DayOfBirth(1), MonthOfBirth(1), YearOfBirth(1990)
{
}
//---------------------------------------------------------------------------
__fastcall TStudent::TStudent(int DOB, int MOB, int YOB)
: TPerson("", ""), DayOfBirth(DOB), MonthOfBirth(MOB), YearOfBirth(YOB)
{
}
//---------------------------------------------------------------------------
__fastcall TStudent::TStudent(const TStudent& Stud)
: TPerson(Stud.FirstName, Stud.LastName),
DayOfBirth(Stud.DayOfBirth), MonthOfBirth(Stud.MonthOfBirth),
YearOfBirth(Stud.YearOfBirth), Gender(Stud.Gender)
{
}
//---------------------------------------------------------------------------
__fastcall TStudent::~TStudent()
{
}
//---------------------------------------------------------------------------
string __fastcall TStudent::getGender() const
{
if( Gender == 1 )
return "Male";
else if( Gender == 2 )
return "Female";
else
return "Unspecified";
}
//--------------------------------------------------------------------------
|
- To prepare the program for a test, change the Main.cpp file as follows:
//---------------------------------------------------------------------------
#include <iostream.h>
#pragma hdrstop
//---------------------------------------------------------------------------
#include "Student.h"
#pragma argsused
//---------------------------------------------------------------------------
void __fastcall ShowInfo(const TStudent& S)
{
cout << "\nFull Name: " << S.getFirstName()
<< " " << S.getLastName();
cout << "\nDate of Birth: "
<< S.getDayOfBirth() << "/" << S.getMonthOfBirth()
<< "/" << S.getYearOfBirth();
cout << "\nGender: " << S.getGender();
}
//---------------------------------------------------------------------------
int main(int argc, char* argv[])
{
TStudent P;
P.setFirstName("Hermine");
P.setLastName("Akono");
P.setDayOfBirth(12);
P.setMonthOfBirth(5);
P.setYearOfBirth(1988);
P.setGender(2);
cout << "Personal Information";
ShowInfo(P);
cout << "\n\nPress any key to continue...";
getchar();
return 0;
}
//---------------------------------------------------------------------------
|
- Implement the Student.cpp class as follows:
//---------------------------------------------------------------------------
#pragma hdrstop
#include "Student.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
__fastcall TStudent::TStudent()
: TPerson("John", "Doe"),
DayOfBirth(1),
MonthOfBirth(1),
YearOfBirth(1990),
Gender(0)
{
}
//---------------------------------------------------------------------------
__fastcall TStudent::TStudent(string fn, string ln,
int DOB, int MOB, int YOB, int g)
: TPerson(fn, ln),
DayOfBirth(DOB), MonthOfBirth(MOB), YearOfBirth(YOB), Gender(g)
{
}
//---------------------------------------------------------------------------
__fastcall TStudent::TStudent(string fn, string ln)
: TPerson(fn, ln),
DayOfBirth(1), MonthOfBirth(1), YearOfBirth(1990)
{
}
//---------------------------------------------------------------------------
__fastcall TStudent::TStudent(int DOB, int MOB, int YOB)
: TPerson("", ""), DayOfBirth(DOB), MonthOfBirth(MOB), YearOfBirth(YOB)
{
}
//---------------------------------------------------------------------------
__fastcall TStudent::TStudent(const TStudent& Stud)
: TPerson(Stud.FirstName, Stud.LastName),
DayOfBirth(Stud.DayOfBirth), MonthOfBirth(Stud.MonthOfBirth),
YearOfBirth(Stud.YearOfBirth), Gender(Stud.Gender)
{
}
//---------------------------------------------------------------------------
__fastcall TStudent::~TStudent()
{
}
//---------------------------------------------------------------------------
string __fastcall TStudent::getGender() const
{
if( Gender == 1 )
return "Male";
else if( Gender == 2 )
return "Female";
else
return "Unspecified";
}
//--------------------------------------------------------------------------
|
- To prepare a test, change the Main.cpp file as follows:
//---------------------------------------------------------------------------
#include <iostream.h>
#pragma hdrstop
//---------------------------------------------------------------------------
#include "Student.h"
#pragma argsused
//---------------------------------------------------------------------------
void __fastcall ShowInfo(const TStudent& S)
{
cout << "\nFull Name: " << S.getFirstName()
<< " " << S.getLastName();
cout << "\nDate of Birth: "
<< S.getDayOfBirth() << "/" << S.getMonthOfBirth()
<< "/" << S.getYearOfBirth();
cout << "\nGender: " << S.getGender();
}
//---------------------------------------------------------------------------
int main(int argc, char* argv[])
{
TStudent P;
P.setFirstName("Hermine");
P.setLastName("Akono");
P.setDayOfBirth(12);
P.setMonthOfBirth(5);
P.setYearOfBirth(1988);
P.setGender(2);
cout << "Personal Information";
ShowInfo(P);
cout << "\n\nPress any key to continue...";
getchar();
return 0;
}
//---------------------------------------------------------------------------
|
- Test the program and return to Bcb
The most common inheritance consists of an object deriving its foundation from another object. This is referred to as single inheritance. C++ allows an object to be based on more than one object. This is called refered to as multiple inheritance.
When an object is based on many other objects, it benefits from the variables of those objects. It has direct access to the public and protected members of each parent object.
To apply a multiple inheritance, specify each class on the right side of the : operator.
|
Performing Multiple Inheritance |
- Add a new unit to your project and save it as Address
- In the Address.h file, create a TAddress class as follows:
//---------------------------------------------------------------------------
#ifndef AddressH
#define AddressH
#include <iostream.h>
//---------------------------------------------------------------------------
class TAddress
{
public:
__fastcall TAddress(string a = "123 Main Street #A",
string c = "City Ville",
string s = "MD",
string z = "20900");
__fastcall TAddress(const TAddress& d);
__fastcall ~TAddress();
void __fastcall setAddress(const string a) { Address = a; }
string __fastcall getAddress() const { return Address; }
void __fastcall setCity(const string c) { City = c; }
string __fastcall getCity() const { return City; }
void __fastcall setState(const string s) { State = s; }
string __fastcall getState() const { return State; }
void setZIPCode(const string z) { ZIPCode = z; }
string __fastcall getZIPCode() const { return ZIPCode; }
protected:
string Address;
string City;
string State;
string ZIPCode;
};
//---------------------------------------------------------------------------
#endif
|
- Implement the TAddreass class as follows:
//---------------------------------------------------------------------------
#pragma hdrstop
#include "Address.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
__fastcall TAddress::TAddress(string a, string c, string s, string z)
: Address(a), City(c), State(s), ZIPCode(z)
{
}
//---------------------------------------------------------------------------
__fastcall TAddress::TAddress(const TAddress& d)
: Address(d.Address), City(d.City), State(d.State), ZIPCode(d.ZIPCode)
{
}
//---------------------------------------------------------------------------
__fastcall TAddress::~TAddress()
{
}
//---------------------------------------------------------------------------
|
- Add a new unit and save it as Staff
- To perform a multiple inheritance, in the Staff.h file, create a TStaff class as follows:
//---------------------------------------------------------------------------
#ifndef StaffH
#define StaffH
#include <iostream.h>
#include "Person.h"
#include "Address.h"
//---------------------------------------------------------------------------
class TStaff : public TPerson, public TAddress
{
public:
__fastcall TStaff();
__fastcall TStaff(string fn, string ln,
string a, string c, string s, string z,
double L, char e, int m);
__fastcall TStaff(const TStaff& S);
__fastcall ~TStaff();
void __fastcall setSalary(const double s) { Salary = s; }
double __fastcall getSalary() const;
void __fastcall setEmplStatus(const char e) { EmploymentStatus = e; }
string __fastcall getEmploymentStatus() const;
void __fastcall setMaritalStatus(const int m) { MaritalStatus = m; }
string __fastcall getMaritalStatus() const;
protected:
double Salary;
char EmploymentStatus;
int MaritalStatus;
};
//---------------------------------------------------------------------------
#endif
|
- Implement the TStaff class as follows:
//---------------------------------------------------------------------------
#pragma hdrstop
#include "Staff.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
//---------------------------------------------------------------------------
__fastcall TStaff::TStaff()
{
}
//---------------------------------------------------------------------------
__fastcall TStaff::TStaff(string fn, string ln,
string a, string c, string s, string z,
double L, char e, int m)
: TPerson(fn, ln),
TAddress(a, c, s, z),
Salary(L), EmploymentStatus(e), MaritalStatus(m)
{
}
//---------------------------------------------------------------------------
__fastcall TStaff::TStaff(const TStaff& S)
: Salary(S.Salary),
EmploymentStatus(S.EmploymentStatus),
MaritalStatus(S.MaritalStatus)
{
}
//---------------------------------------------------------------------------
__fastcall TStaff::~TStaff()
{
}
//---------------------------------------------------------------------------
double __fastcall TStaff::getSalary() const
{
if( Salary < 12.42 )
return 12.42;
else
return 12.42;
}
//---------------------------------------------------------------------------
string __fastcall TStaff::getEmploymentStatus() const
{
string EStatus;
switch(EmploymentStatus)
{
case 'f':
case 'F':
EStatus = "Full-Time";
break;
case 'p':
case 'P':
EStatus = "Parti-Time";
break;
case 'c':
case 'C':
EStatus = "Contractor";
break;
case 's':
case 'S':
EStatus = "Seasonal";
break;
default:
EStatus = "Unknown";
}
return EStatus;
}
//---------------------------------------------------------------------------
string __fastcall TStaff::getMaritalStatus() const
{
string MStatus;
switch(MaritalStatus)
{
case 1:
MStatus = "Single";
break;
case 2:
MStatus = "Married";
break;
case 3:
MStatus = "Widow";
break;
case 4:
MStatus = "Divorcé";
break;
default:
MStatus = "Not Specified";
}
return MStatus;
}
//---------------------------------------------------------------------------
|
- Change the Main.cpp file as follows:
//---------------------------------------------------------------------------
#include <iostream.h>
#pragma hdrstop
//---------------------------------------------------------------------------
#include "Staff.h"
#pragma argsused
//---------------------------------------------------------------------------
void __fastcall ShowInfo(const TStaff& S)
{
cout << "\nFull Name: " << S.getFirstName()
<< " " << S.getLastName();
cout << "\nAddress: " << S.getAddress()
<< "\n " << S.getCity() << " "
<< S.getState() << " " << S.getZIPCode();
cout << "\nEmployment: " << S.getEmploymentStatus();
cout << "\nSalary: $" << S.getSalary();
cout << "\nMarital St: " << S.getMaritalStatus();
}
//---------------------------------------------------------------------------
int main(int argc, char* argv[])
{
TStaff Empl;
Empl.setFirstName("Mark");
Empl.setLastName("Azzuri");
Empl.setAddress("12432 Lockwood Drive #D12");
Empl.setCity("Hyattsville");
Empl.setState("MD");
Empl.setZIPCode("20740");
Empl.setSalary(18.05);
Empl.setEmplStatus('F');
Empl.setMaritalStatus(1);
cout << "Personal Information";
ShowInfo(Empl);
cout << "\n\nPress any key to continue...";
getchar();
return 0;
}
//---------------------------------------------------------------------------
|
- Test the program and return to Bcb
- To allow the user to process hiring, change the Main.cpp file as follows:
//---------------------------------------------------------------------------
#include <iostream.h>
#pragma hdrstop
//---------------------------------------------------------------------------
#include "Staff.h"
#pragma argsused
//---------------------------------------------------------------------------
void __fastcall NewEmployee(TStaff& Employee)
{
string FirstName, LastName, Address, City, State, ZIPCode;
double Salary;
char EmplStatus;
int MStatus;
cout << "First Name: "; cin >> FirstName;
cout << "Last Name: "; cin >> LastName;
cout << "Address: "; getline(cin, Address);
cout << "City: "; getline(cin, City);
cout << "State: "; getline(cin, State);
cout << "ZIP Code: "; cin >> ZIPCode;
cout << "Hourly Salary: $"; cin >> Salary;
cout << "Employment Status"
<< "\nf - Full-Time"
<< "\np - Part-Time"
<< "\nc - Contractor"
<< "\ns - Seasonal"
<< "\nYour Choice: "; cin >> EmplStatus;
cout << "Marital Status"
<< "\n1 - Single"
<< "\n2 - Married"
<< "\n3 - Widow"
<< "\n4 - Divorcé"
<< "\nStatus: "; cin >> MStatus;
Employee.setFirstName(FirstName);
Employee.setLastName(LastName);
Employee.setAddress(Address);
Employee.setCity(City);
Employee.setState(State);
Employee.setZIPCode(ZIPCode);
Employee.setSalary(Salary);
Employee.setEmplStatus(EmplStatus);
Employee.setMaritalStatus(MStatus);
}
//---------------------------------------------------------------------------
void __fastcall ShowInfo(const TStaff& S)
{
cout << "\nFull Name: " << S.getFirstName()
<< " " << S.getLastName();
cout << "\nAddress: " << S.getAddress()
<< "\n " << S.getCity() << " "
<< S.getState() << " " << S.getZIPCode();
cout << "\nEmployment: " << S.getEmploymentStatus();
cout << "\nSalary: $" << S.getSalary();
cout << "\nMarital St: " << S.getMaritalStatus();
}
//---------------------------------------------------------------------------
int main(int argc, char* argv[])
{
TStaff Empl;
cout << "Enter information about the new hire\n";
NewEmployee(Empl);
system("cls");
cout << "Personal Information";
ShowInfo(Empl);
cout << "\n\nPress any key to continue...";
getchar();
return 0;
}
//---------------------------------------------------------------------------
|
- Test the program and return to Bcb.
|
|