Upload
others
View
3
Download
0
Embed Size (px)
Citation preview
Visual C++ Programming – Penn Wu, PhD 251
Lecture #9 Inheritance, Composition, and Polymorphism
Introduction In terms of object-oriented programming, “inheritance” is the ability that enables new classes to
use the properties and methods of existing classes through the declaration of inheritance. For
example, the word “car” is a general term that can describe many kinds of vehicles including
“sedan”, “truck”, “pickup”, “SUV”, and more. All these vehicles are specialized cars. A “car”
must have an engine, tires, and a driver’s seat no matter what kind of car it is. Therefore, if a
“sedan” is a kind of “car”, then a “sedan” must have an engine, tires, and a driver’s seat.
Fig 1
“Inheritance” is the act that applies the properties and methods of the “Car” class to the “Sedan”
class; thus, an instance of “Sedan” can use members of “Car” without the need to re-define these
“Car” members in “Sedan”.
A class that is inherited by other classes is called a base class (or parent class). The class that
does the inheriting is called a derived class (or child class). In a sense, a derived class is a
specialized subset of a base class.
Polymorphism is the concept that allows multiple forms of a given method to exist in a class,
each of the form is designed for handling a special situation. Polymorphism also allows a child
class to override the definition of methods of the parent class.
C++ inheritance In C++, programmers create a child class (officially known as “derived class”) with the following
syntax to declare the inheritance from a parent class (aka “base class”), where AccessSpecifier is
public, private, or protected. By the way, if no AccessModifier is given, private is the default.
class childClassName: AccessModifier parentClassName
{
childClass members;
};
The following illustrates how to declare a new class named “Cellphone” as child (derived) class
of an existing class named “Telephone”. It is necessary to note that the “Telephone” class which
is the parent (based) class must be declared before the child can be declared.
class cellphone: public Telephone { }
After the declaration, the child class can inherit all of the “shared” members of the base class
and create its own members. In other words, “inheritance” is for a child class to gain access to all
the public or protected members (such as properties and methods) of the parent class and use
them like its own members. Both public and protected members of a parent class are shareable
members to the child class, while private members are not shareable. A later section will discuss
how these access modifier work in “inheritance”.
The advantage of “inheritance” in object-oriented programming is the “sharing of codes”. In a
given program, you only have to define what a “car” is ONCE by creating a “Car” class. All the
specialized cars, such as “sedan”, “truck”, “pickup”, and “SUV”, can reference to the Car class
Car
Sedan Truck Pickup SUV
Visual C++ Programming – Penn Wu, PhD 252
and share the codes defined in the Car class. It is just like saying “a sedan is a car”, “a truck is a
car”, and “a pickup is a car” without the need to define what a car is over and over again.
Class
inheritance
The following is a class named “Car” containing two public instance variables: “mpg” and
“tankSize”. It also has a protected method named mileage() to calculate the mileage, and a
private variable named “securityCode”. The instructor creates this “Car” class to be inherited by
others.
#using <System.dll>
#using <System.Windows.Forms.dll>
using namespace System;
using namespace System::Windows::Forms;
ref class Car // base class
{
public: // open to the entire program
int mpg;
int tankSize;
protected:
int mileage()
{
return mpg * tankSize;
}
private: // not open to child class
int securityCode;
};
The following is an example that create the Sedan class as child to the Car class. The Sedan
class also has two public variables of int type: “tireNumber” and “ml”. The default constructor,
Sedan(), defines all the default values of the Sedan class. All the shareable members of the “Car”
class, mpg, tankSize, and mileage(), are used by the Sedan as its own members. In the words,
Sedan “inherits” all sharable members of “Car”. Shareable members of Car are also members of
the Sedan class.
ref class Sedan : public Car // declare Sedan a child of Car
{
public:
int tireNumber;
int ml;
Sedan()
{
tireNumber = 4;
mpg = 34;
tankSize = 16;
ml = mileage();
}
};
The declaration on inheritance forces the Car class to share all the public properties and public
methods with the Sedan class. Programmers do not need to declare variables “mpg” and
“tankSize” and the mileage() method again when they create the Sedan class. In other words, the
“Sedan” class inherits all the public members of the “Car” class.
A child class, even as a child, is still an individual class. The way to declare, create, or add
members of a child class is exactly the same as that of any C++ class. In the following example,
the instructor adds a public method named “TurboIt()”.
Visual C++ Programming – Penn Wu, PhD 253
ref class Sedan : public Car // declare Sedan a child of Car
{
public:
int tireNumber;
int ml;
Sedan()
{
tireNumber = 4;
mpg = 34;
tankSize = 16;
ml = mileage();
}
void TurboIt()
{
mpg = mpg * 1.5;
}
};
Some programmers prefer declaring a class method inside the class body, and then use the scope
resolution operator (::) to define details of the member method outside the class body, as
illustrated below. The scope resolution operator (::), which, in C++, can be used to define the
already declared member functions.
ref class Sedan : public Car // declare Sedan a child of Car
{
public:
int tireNumber;
int ml;
Sedan()
{
tireNumber = 4;
mpg = 34;
tankSize = 16;
ml = mileage();
}
void TurboIt();
};
void Sedan::TurboIt()
{
mpg = mpg * 1.5;
}
To use members in both base (parent) and derived (child) classes, you can create an instance of
Sedan in the main() method, such as “s1” in the following code. You can certainly create an
instance of Car (s2). Interestingly, you can also declare an object as Car (such as “s3”) but create
the object as Sedan.
int main()
{
Sedan^ s1 = gcnew Sedan;
Car^ s2 = gcnew Car;
Car^ s3 = gcnew Sedan;
}
Visual C++ Programming – Penn Wu, PhD 254
The s1 object is instantiated as Sedan, s2 object is instantiated as a Car, and s3 is declared as Car
but is instantiated as Sedan. The difference between s1 and s3 is that s1 can uses all shared
members of the “Car” class through inheritance and every member of the “Sedan” class, while s3
can use all shared members of Car and the default values defined in the Sedan() constructor.
Instance of the “Car” class can only use any member of the “Car” class and cannot access the
Sedan() default constructor.
Object Car Sedan
mpg tankSize mileage() securityCode tireNumber() ml Sedan()
s1 yes yes yes no yes yes yes
s2 yes yes yes no no no no
s3 yes yes yes no no no yes
Once Sedan is declared as a derived class (the child class) of the Car class, you can directly use
properties and methods of the Car class with the “member-of” (->) operator. Technically, all the
public members in the Car class are treated as members of the Sedan class. For example, to the
use mpg property of the Car class from a Sedan object, use:
s1->mpg
To assign a value to the mpg property, use:
s1->mpg = 72;
Similarly, to use a method of the Car class, use:
s1->mileage();
The following is the complete code.
#using <System.dll>
#using <System.Windows.Forms.dll>
using namespace System;
using namespace System::Windows::Forms;
ref class Car // base class
{
public: // open to the entire program
int mpg;
int tankSize;
protected:
int mileage()
{
return mpg * tankSize;
}
private: // not open to child class
int securityCode;
};
ref class Sedan : public Car // declare Sedan a child of Car
{
public:
int tireNumber;
int ml;
Sedan()
{
Visual C++ Programming – Penn Wu, PhD 255
tireNumber = 4;
mpg = 34;
tankSize = 16;
ml = mileage();
}
void TurboIt()
{
mpg = mpg * 1.5;
}
};
int main()
{
String^ str = "Car\tMPG\tTank Size\tTires\tMileage\n";
Sedan^ s1 = gcnew Sedan; // instance of Sedan
s1->TurboIt(); // member of Sedan only
str += "s1\t" + s1->mpg + "\t" + s1->tankSize + "\t";
str += s1->tireNumber + "\t" + s1->ml + "\n";
Car^ s2 = gcnew Car;
str += "s2\t" + s2->mpg + "\t" + s2->tankSize + "\n";
Car^ s3 = gcnew Sedan;
str += "s3\t" + s3->mpg + "\t" + s3->tankSize + "\t";
//str += s3->tireNumber + "\t" + s3->ml + "\n";
MessageBox::Show(str);
}
The output looks:
Access
modifiers
Choosing a proper “Access modifier” can make a big difference in inheritance.
• The private members of a base class are private to the base class only; therefore, the derived
class cannot access them.
• The protected members can be inherited by the derived class; however, the derived class
cannot modify values or content of a protected member of the base class.
• The public members of a base class can be inherited either as public members or as private
members by the derived class. In other words, the public members of the base class can
become either public or private members of the derived class.
The protected Access modifier is similar to private. Its only difference occurs in fact with
inheritance. The following table summarizes the different access types according to who can
access them in the following way:
Access public protected private
members of the same class Yes Yes Yes
members of derived classes Yes Yes No
not members Yes No No
Visual C++ Programming – Penn Wu, PhD 256
In the following example, the instructor declares three instance variables: category, IsRegistered,
and origin. They are specified as “public”, “private”, and “protected” respectively. The Car class
has a default constructor, Car(), which specifies the default values of “IsRegistered” and “origin”.
ref class Car // base class
{
public: String^ category;
private: Boolean IsRegistered;
protected: String^ origin;
public:
Car()
{
IsRegistered = true;
origin = "Nakano Japan";
}
};
The following is a derived class that has only a default constructor, Sedan(), to specify what an
instance of the Sedan class should do. It is necessary to note that “category” is a public member
of the “Car”; therefore, Sedan can use it and modify its value. Interestingly, “origin” is a
protected member, yet Sedan can still modify its value. This is because Sedan inherits “origin”
from “Car” which makes “origin” a member of Sedan.
ref class Sedan : public Car
{
public:
Sedan()
{
category = "4 door Sedan";
origin = "Dayton, OH, USA";
MessageBox::Show(category + "\n" + origin);
}
};
In the following example, the instructor attempts to modify the value of “origin” inside the
main() method. This is an illegal act because the main() method is neither a member of the
“Sedan” class nor a member of the “Car” class.
int main()
{
Sedan s1;
s1.origin = "Jechiu, Korea";
}
The compiler will return the following error message:
error C2248: 'Car::origin' : cannot access protected member
declared in class 'Car'
1.cpp(13) : see declaration of 'Car::origin'
1.cpp(8) : see declaration of 'Car'
Apparently a child class (derived class) can access and modify value or contents of both “public”
and “protected” members. The following code attempts to access the “private” member of Car
class from the child class.
ref class Sedan : public Car
Visual C++ Programming – Penn Wu, PhD 257
{
public:
Sedan()
{
category = "4 door Sedan";
origin = "Dayton, OH, USA";
IsRegistered = false;
MessageBox::Show(category + "\n" + origin);
}
};
The attempt is illegal, and the compile will return the following error message:
error C2248: 'Car::IsRegistered' : cannot access private member
declared in class 'Car'
1.cpp(11) : see declaration of 'Car::IsRegistered'
1.cpp(4) : see declaration of 'Car'
The following is the complete code for you to test.
#using <System.dll>
#using <System.Windows.Forms.dll>
using namespace System;
using namespace System::Windows::Forms;
ref class Car // base class
{
public: String^ category;
private: Boolean IsRegistered;
protected: String^ origin;
public:
Car()
{
IsRegistered = true;
origin = "Nakano Japan";
}
};
ref class Sedan : public Car
{
public:
Sedan()
{
category = "4 door Sedan";
origin = "Dayton, OH, USA";
MessageBox::Show(category + "\n" + origin);
}
};
int main()
{
Sedan s1;
}
Default constructor of the parent class is executed by default when inheritance occurs. In the
following example, the “GetFoot” class is the parent class and the “GetInch” is the child class.
By creating an instance of the “GetInch” class, the default constructor of both classes must
execute. The sequence of execution is: parent first, child second.
Visual C++ Programming – Penn Wu, PhD 258
#using <System.dll>
#using <System.Windows.Forms.dll>
using namespace System;
using namespace System::Windows::Forms;
#include "InputBox.cpp"
ref class GetFoot
{
protected:
int feet;
public:
GetFoot() // default constructor
{
feet = Convert::ToInt32(InputBox::Show("Enter the feet:"));
}
};
ref class GetInch : GetFoot
{
protected:
int inch;
public:
int height;
GetInch() // default constructor
{
inch = Convert::ToInt32(InputBox::Show("Enter the inch:"));
height = feet * 12 + inch;
}
};
int main()
{
String^ str = "";
GetInch^ g1 = gcnew GetInch; // call GetFoot() and GetInch()
MessageBox::Show("You are " + g1->height + " inches tall.");
return 0;
}
A parent class can share its members with two or more child classes. The following is an
example of a supportive class named “Socal” which is created to provide shared members;
therefore, it is a based class.
ref class Socal // base class
{
protected:
int staff, faculty;
public:
void setvalues(int x, int y)
{
staff=x;
faculty=y;
}
int total()
Visual C++ Programming – Penn Wu, PhD 259
{
return (staff + faculty);
}
};
In the Socal (Southern California) area, there are three campuses: Pomona, Long Beach, and
Sherman Oaks. Figure 2 explains the relationships among the classes.
Figure 2
The child classes can inherit and use the shared members of the Socal (parent) class. Noticeably
inheritance is a one-way relationship and only the child class can inherit the parent class. The
following is a “dummy” (aka. “empty”) which inherits every from the “Socal” class.
ref class ShermanOaks : public Socal { }; // an empty class
In the following code, the “Pomona” class inherits the “Socal” class, yet it modify the public
method named “total()”.
ref class Pomona: public Socal // derived class
{
public:
int total()
{
return (staff * 0.4 + faculty * 0.6);
}
};
The Long Beach class can manipulate members of the Socal class in another way (assuming half
of the faculties in Long Beach also teach at Pomona, so the formula is different): ref class LongBeach: public Socal // derived class
{
public:
int total()
{
return (staff + faculty / 2);
}
};
The following is the complete code that illustrates the concept.
#using <System.dll>
#using <System.Windows.Forms.dll>
using namespace System;
using namespace System::Windows::Forms;
ref class Socal // base class
{
protected:
int staff, faculty;
public:
void setvalues(int x, int y)
{
Socal
Pomona Long Beach Sherman Oaks
Visual C++ Programming – Penn Wu, PhD 260
staff=x;
faculty=y;
}
public:
int total()
{
return (staff + faculty);
}
};
ref class ShermanOaks : public Socal { }; // an empty class
ref class Pomona: public Socal // derived class
{
public:
int total()
{
return (staff * 0.4 + faculty * 0.6);
}
};
ref class LongBeach: public Socal // derived class
{
public:
int total()
{
return (staff + faculty / 2);
}
};
int main()
{
Pomona^ s1 = gcnew Pomona();
s1->setvalues(15, 7);
LongBeach^ s2 = gcnew LongBeach();
s2->setvalues(12, 6);
ShermanOaks^ s3 = gcnew ShermanOaks();
s3->setvalues(10, 4);
String^ str = "Total employees:\n";
str += s1->total() + "\n" + s2->total() + "\n" + s3->total();
MessageBox::Show(str);
return 0;
}
The output looks:
Multiple layer
inheritance
A derived (child) class can be a base (parent) class to its own derived class. For example, a
variable x is defined in myBase class. The Square class inherits x from myBase and passes it on
Visual C++ Programming – Penn Wu, PhD 261
to the Cube class. The Square class has a function named calSquare(), which will also be used
by the Cube class.
To demonstrate how such a three-layer inheritance works, create the myBase class with a
variable x as shown below:
ref class myBase
{
public:
double x;
};
Create the Square class as a derived class of the myBase class, and then define the calSquare()
function as a public member of the Square class. So, the myBase class cannot use this
calSquare() function.
ref class Square : public myBase
{
public:
int calSquare() // calculate square of x
{
return x * x;
}
};
Create the Cube class as a derived class of the Square class. Technically it is the grandchild of the
myBase class. Also, create the calCube() function as the member of the Cube(), so neither Square
class nor myBase class can use it.
ref class Cube : public Square
{
public:
int calCube() // calculate cube of x
{
return calSquare() * x;
}
};
Finally, in the main() function initiate a Cube object named myNo, which will use the x variable
(inherited from the myBase class by way of the Square class) and the calSquare() function
(inherited from the Square class).
#using <System.dll>
#using <System.Windows.Forms.dll>
using namespace System;
using namespace System::Windows::Forms;
ref class myBase
{
public:
double x;
};
ref class Square : public myBase
{
public:
int calSquare() // calculate square of x
MyBase (parent class)
Square (child class)
Cube (grandchild class)
Visual C++ Programming – Penn Wu, PhD 262
{
return x * x;
}
};
ref class Cube : public Square
{
public:
int calCube() // calculate cube of x
{
return calSquare() * x;
}
};
int main()
{
Cube^ c1 = gcnew Cube();
c1->x = 3;
String^ str = c1->x + "\n"; // inherit x from myBase
str += c1->calSquare() + "\n"; // inherit from Square
str += c1->calCube() + "\n";
MessageBox::Show(str);
return 0;
}
The calCube() function is a member of the Cube class. No inheritance applies to it.
The following is another demonstration of how multiple layer inheritance works. The instructor
creates three classes. Their relationship is illustrated by the following figure.
The functionality of each class is described below:
• TicketPrice: Ask user to enter the ticket price (or price on a tag), and then set the sale price
equal to the unit price.
• DiscountPrice: Ask user to enter the discount rate and then calculate the sale price.
• InvoicePrice: Ask user to enter the tax rate, calculate the final price, and round the value.
Based on the above description, the instructor wrote the following code to create the
“TicketPrice” class.
ref class TicketPrice // parent
{
public:
double unitPrice;
double salePrice;
TicketPrice() // default constructor
{
unitPrice = Convert::ToDouble(InputBox::Show("Unit price: "));
salePrice = unitPrice;
}
};
The following is the code for the “DiscountPrice”. This class inherits both “unitPrice” and
“salePrice” members from the “TicketPrice” class. It also creates its own member
“dicsountRate”.
TicketPrice (parent class)
DiscountPrice (child class)
InvoicePrice (grandchild class)
Visual C++ Programming – Penn Wu, PhD 263
ref class DiscountPrice : TicketPrice // child
{
public:
double discountRate;
DiscountPrice() // default constructor
{
discountRate = Convert::ToDouble(InputBox::Show("Discount rate
(%): ")) * 0.01;
salePrice = unitPrice * (1- discountRate);
}
};
The following is the code for “InvoicePrice” class. This class inherits both “unitPrice” and
“salePrice” members from the “TicketPrice” class. It also inherits “dicsountRate” from the
“DiscountPrice” class. Additionally, it adds two members “RoundIt()” and “taxtRate”.
ref class InvoicePrice : DiscountPrice // grandchild
{
private:
double roundIt(double n)
{
return Math::Round(n, 2);
}
protected:
double taxRate;
public:
double finalPrice;
InvoicePrice() // default constructor
{
taxRate = Convert::ToDouble(InputBox::Show("Tax rate (%): "))
* 0.01;
finalPrice = salePrice * (1 + taxRate);
finalPrice = roundIt(finalPrice);
}
};
Composition In terms of object-oriented, composition is the creation of a new class which contains instance of
other existing classes. The following figure illustrates how a “Student” class consists of an
instance of “Name” class, an instance of “Address” class, and an instance of “Major” class. In
other words, every student has a name, an address, and a major.
The following uses four code snippets to illustrate the concept.
ref class Name
{
}
Ref class Address
{
}
ref class Major
{
}
ref class Student
{
Private:
Name^ n1;
Address^ a1;
Major^ m1;
}
Name n1
Address a1
Major m1 Student
Visual C++ Programming – Penn Wu, PhD 264
The term “composition” can be further divided into two categories of relationship: composition
and aggregation. If an object is exclusively owned by another object, they are in the composition
relationship. If an object can be shared by two or more objects, they are in the aggregation
relationship. In the above example, each Student must have one and only one Name object;
therefore, “a Student has a name” is a composition relationship. Since two or more students could
live in the same house; an address could be shared by two or more students. Student and Address
are in an aggregation relationship.
The following is a sample code that demonstrates how composition works.
#using <System.dll>
#using <System.Windows.Forms.dll>
using namespace System;
using namespace System::Windows::Forms;
ref class Name
{
public:
String^ get() { return "object of Name."; }
};
ref class Address
{
public:
String^ get() { return "object of Address."; }
};
ref class Major
{
public:
String^ get() { return "object of Name."; }
};
ref class Student
{
public:
String^ report;
private:
Name^ n1 = gcnew Name();
Address^ a1 = gcnew Address();
Major^ m1 = gcnew Major();
public:
Student()
{
report = n1->get() + "\n" + a1->get() + "\n" + m1->get();
}
};
int main()
{
Student^ s1 = gcnew Student();
MessageBox::Show(s1->report);
}
A sample output looks:
Visual C++ Programming – Penn Wu, PhD 265
In the following example, composition occurs because each Car object must have an Engine
object. The instructor, however, purposely creates an instance of Engine inside the default
constructor of the Car class.
#using <System.dll>
#using <System.Windows.Forms.dll>
using namespace System;
using namespace System::Windows::Forms;
ref class Engine
{
public:
bool IsGasIn;
String^ status;
Engine()
{
IsGasIn = true;
status = "Engine started.";
}
};
ref class Car
{
public:
String^ report;
Car()
{
Engine^ e1 = gcnew Engine();
report = e1->status + "\nHas gas: " + e1->IsGasIn;
}
};
int main()
{
Car^ c1 = gcnew Car();
MessageBox::Show(c1->report);
}
Polymorphism Polymorphism is a biological term that literally means many forms or shapes. The object-
oriented paradigm support two major types of polymorphism: method (or function)
polymorphism and subclass polymorphism.
In terms of programming, method (or function) polymorphism is the ability to allow multiple
methods of a given class share the same identifier (name) but behave differently. When building
an application for calculating the body mass index (BMI) programmers frequently have to allow
a method to behave in several ways. BMI is a measure of relative weight based on an individual's
mass and height. The following is the formulas used in the U.S. for calculating BMI, where w is
the body weight in pounds (lb) and h is the height in inches.
BMI = (w /h2)×703
Visual C++ Programming – Penn Wu, PhD 266
In the following example, the instructor creates two “forms” of the getBMI() method for the BMI
class. Each form takes different types of parameters and return values of different type, yet all the
two forms have exactly the same identifier “getBMI”. This an example of “method
polymorphism”. Some textbook refers this kind of polymorphism as overloading. Overloading
happens when you define two or more forms of methods with the same identifier in the same
class.
#using <System.dll>
#using <System.Windows.Forms.dll>
using namespace System;
using namespace System::Windows::Forms;
ref class BMI
{
public:
double getBMI(double w, double h) { // form 1
return (w / (h*h)) * 703;
}
String^ getBMI(int w, int h) { //form 2
return ( ((double) w / (h*h)) * 703 ) + "";
}
};
int main()
{
String^ str = "";
BMI^ b1 = gcnew BMI;
str += b1->getBMI(92.7, 1.74) + "\n"; // form 1
str += b1->getBMI(185, 66) + "\n"; // form 2
MessageBox::Show(str);
return 0;
}
Polymorphism can happen among functions that do not belong to any class. The following code
contains two forms of “getF()” function. They both use the formula C = (5/9) × (F - 32) to
convert Fahrenheit to Celsius; however, they take different types of parameter and return values
of different types. This example illustrates “function polymorphism”.
#using <System.dll>
#using <System.Windows.Forms.dll>
using namespace System;
using namespace System::Windows::Forms;
double getF(double f) // form 1
{
return ((double) 5/ (double) 9) * (f - 32);
}
float getF(String^ f) // form 2
{
return ((double) 5/ (double) 9) * (Convert::ToDouble(f) - 32);
}
int main()
{
Visual C++ Programming – Penn Wu, PhD 267
String^ str = "";
str += getF(92.7) + "\n"; // form 1
str += getF("92.7") + "\n"; // form 2
MessageBox::Show(str);
return 0;
}
Polymorphism can happen between a method of parent class and its child class. Subclass
polymorphism is also known as overriding. Overriding happens when you redefine a method
inherited from a parent class. There are in fact, two formulas for calculating BMI, as shown in
the following table.
Metric system U.S. system BMI = w /h2
where w is the body weight in kilograms (kg)
and h is the height in meters (m).
BMI = (w /h2)×703
where w is the body weight in pounds (lb) and
h is the height in inches.
Most countries adapt the metric system. The United States is one of the very few countries that
have not yet adapted the metric system; therefore, it is reasonable to treat the U.S. as an
“exception”. In the following code, the instructor creates a parent class named “BMI” with a
getBMI() method that uses the metric-system formula to return BMI values. The instructor also
create a child class named “USBMI” which inherits public “getBMI” method from the “BMI”
class. The “subclass polymorphism” happens when the “USBMI” class override the “getBMI()”
method.
#using <System.dll>
#using <System.Windows.Forms.dll>
using namespace System;
using namespace System::Windows::Forms;
ref class BMI
{
public: double getBMI(double w, double h) // form 1
{
return w/(h*h);
}
};
ref class USBMI : BMI
{
public: double getBMI(double w, double h) // form 2
{
return (w/(h*h)) * 703; // overriding
}
};
int main()
{
String^ str = "";
BMI^ b1 = gcnew BMI;
USBMI^ u1 = gcnew USBMI;
str += b1->getBMI(90.3, 1.76) + "\n"; // form 1
str += u1->getBMI(191.6, 66.5) + "\n"; // form 2
MessageBox::Show(str);
Visual C++ Programming – Penn Wu, PhD 268
return 0;
}
The “getBMI()” method in both “BMI” and “USBMI” classes have the same identifier, they take
the same types of parameters, and they return the same type of values. However, they use
different formula to calculate the BMI values.
Review
Question
1. The following is an example of __.
ref class Blue : public Color { }
A. inheritance.
B. encapsulation.
C. data hiding.
D. abstract data types.
2. Given the following code segment, which statement is correct?
ref class Sedan: public Car { }
A. Sedan is a base class
B. Car is a derived class
C. The Sedan class is a subclass to the Car class.
D. The Car class is a subclass to the Sedan class.
3. Given the following code segment, __.
ref class Apple: public Orange { .... }
A. Orange is the derived class
B. Orange is the associated class
C. Apple is the derived class
D. Apple is the base class
4. Given the following code segment, __.
ref class Apple: public Orange { .... }
A. Orange inherits shareable properties and methods from Apple.
B. Apple inherits shareable properties and methods from Orange.
C. Apple is a derived class, so it cannot add its own class members.
D. Apple defines data and features for Orange.
5. Given the following code, which member of the Apple class cannot be accessed by the Orange
class.
ref class Apple
{
private: double stockprice;
protected: double dividend;
public: double shares;
};
ref class Orange: public Apple {}
A. stockprice and dividend
B. dividend and share
C. shares and stockprice
Visual C++ Programming – Penn Wu, PhD 269
D. stockprice
6. Given the following code segment, which statement is correct?
ref class Fruit {
.....
public:
double size;
private:
int count;
};
A. A derived class can inherit only the "size" variable.
B. A derived class can inherit both "size" and "count" variables.
C. A derived class can inherit only the "count" variable.
D. A derived class cannot inherit "size" and "count" variables.
7. Which function will be execution if you issue an area("3.5") statement?
A. int area(int x) { // }
B. double area(double x) { // }
C. String^ area(String^ x) { // }
D. void area() { // }
8. Given the following code segment, which statement is correct?
void print(int i) { MessageBox::Show(i); }
void print(double f) { MessageBox::Show(f); }
A. There are two functions, both are named "print", and they do not overload each other.
B. There are two functions called "print", and they can only accept a double data because the one
with int is overloaded to accept a double data.
C. There is a function called "print", it accepts an int type. There is another function, also called
"print", that is meant to overload the previous one to accept a double type of data as input.
D. They are two functions with the same name, the overloading keeps the "print" function from
accepting either int or double type data as input.
9. Given the following code, which statements in the main() method can yield a message "The
sky is blue."?
ref class base {
public: void func() {
MessageBox::Show("The sky was blue."); }
};
ref class child1 : public base {
public: void func() {
MessageBox::Show("The sky is not blue."); }
};
ref class child2 : public base {
public: void func() {
MessageBox::Show("The sky is blue."); }
};
A. base^ obj; obj->func();
B. child1^ obj; obj->func();
C. child2^ obj; obj->func();
D. child^ obj; obj->func();
Visual C++ Programming – Penn Wu, PhD 270
10. Given the following code, which statements in the main() method can yield a message "A
Child object!"?
class Parent {
public: void display() { MessageBox::Show("A Parent object!"); }
};
class Child : public Parent {
public: void display() { MessageBox::Show("A Child object!"); }
};
A. Child^ c1; c1->display();
B. Parent^ C1; C1->display();
C. Child : Parent^ c1; c1->display();
D. Parent::Child^ C2; C1->display();
Visual C++ Programming – Penn Wu, PhD 271
Lab #9 Inheritance and Polymorphism
Learning Activity #1: Inheritance
1. Launch the Developer Command Prompt (not the regular Command Prompt) and change to the C:\cis223
directory.
2. Under the C:\cis223 directory, use Notepad to create a new file named lab9_1.cpp with the following contents:
#using <System.dll>
#using <System.Windows.Forms.dll>
using namespace System;
using namespace System::Windows::Forms;
#include "InputBox.cpp"
ref class GetFoot // base class
{
protected:
int feet;
public:
GetFoot() // default constructor
{
feet = Convert::ToInt32(InputBox::Show("Enter the feet:"));
}
};
ref class GetInch : GetFoot // derived class
{
protected:
int inch;
public:
int height; // member of GetInch
GetInch() // default constructor
{
inch = Convert::ToInt32(InputBox::Show("Enter the inch:"));
height = feet * 12 + inch; // inherit feet from GetFoot
}
};
int main()
{
String^ str = "";
GetInch^ g1 = gcnew GetInch;
MessageBox::Show("You are " + g1->height + " inches tall.");
return 0;
}
3. Open the Visual Studio (2010) Command Prompt, type cl /clr lab6_1.cpp /link
/subsystem:windows /ENTRY:main and press [Enter] to compile.
C:\cis223>cl /clr lab6_1.cpp /link /subsystem:windows /ENTRY:main
4. Test the program, the output looks:
Visual C++ Programming – Penn Wu, PhD 272
and and
5. Download the “assignment template” and rename it to lab9.doc if necessary. Capture a screen shot similar to the
above figure and paste it to the Word document named lab9.doc (or .docx).
Learning Activity #2: Inheritance
1. Launch the Developer Command Prompt (not the regular Command Prompt) and change to the C:\cis223
directory.
2. Use Notepad to create a new file named lab9_2.cpp with the following contents:
#using <System.dll>
#using <System.Windows.Forms.dll>
using namespace System;
using namespace System::Windows::Forms;
ref class Car // base class
{
public: // open to the entire program
int mpg;
int tankSize;
protected:
int mileage()
{
return mpg * tankSize;
}
private: // not open to child class
int securityCode;
};
ref class Sedan : public Car // declare Sedan a child of Car
{
public:
int tireNumber;
int ml;
Sedan()
{
tireNumber = 4;
mpg = 34;
tankSize = 16;
ml = mileage();
}
void TurboIt()
{
mpg = mpg * 1.5;
}
};
int main()
{
String^ str = "Car\tMPG\tTank Size\tTires\tMileage\n";
Visual C++ Programming – Penn Wu, PhD 273
Sedan^ s1 = gcnew Sedan; // instance of Sedan
s1->TurboIt(); // member of Sedan only
str += "s1\t" + s1->mpg + "\t" + s1->tankSize + "\t";
str += s1->tireNumber + "\t" + s1->ml + "\n";
Car^ s2 = gcnew Car;
str += "s2\t" + s2->mpg + "\t" + s2->tankSize + "\n";
Car^ s3 = gcnew Sedan;
str += "s3\t" + s3->mpg + "\t" + s3->tankSize + "\t";
//str += s3->tireNumber + "\t" + s3->ml + "\n";
MessageBox::Show(str);
}
3. Compile and test the program.
4. Capture a screen shot similar to the above figure and paste it to the Word document named lab9.doc (or .docx).
Learning Activity #3: Multiple layer inheritance
1. Use Notepad to create a new file named lab9_3.cpp with the following contents:
#using <System.dll>
#using <System.Windows.Forms.dll>
using namespace System;
using namespace System::Windows::Forms;
#include "InputBox.cpp"
ref class TicketPrice // parent
{
public:
double unitPrice;
double salePrice;
TicketPrice() // default constructor
{
unitPrice = Convert::ToDouble(InputBox::Show("Unit price: "));
}
};
ref class DiscountPrice : TicketPrice // child
{
public:
double discountRate;
DiscountPrice() // default constructor
{
discountRate = Convert::ToDouble(InputBox::Show("Discount rate (%): ")) * 0.01;
salePrice = unitPrice * (1- discountRate);
Visual C++ Programming – Penn Wu, PhD 274
}
};
ref class SalePrice : DiscountPrice // grandchild
{
private:
double roundIt(double n)
{
return Math::Round(n, 2);
}
protected:
double taxRate;
public:
double finalPrice;
double showTaxRate()
{
return taxRate;
}
SalePrice() // default constructor
{
taxRate = Convert::ToDouble(InputBox::Show("Tax rate (%): ")) * 0.01;
finalPrice = salePrice * (1 + taxRate);
finalPrice = roundIt(finalPrice);
}
};
int main()
{
String^ str = "Unit Price\tDiscount\tTax\tSale Price\n";
SalePrice^ s1 = gcnew SalePrice();
str += "$" + s1->unitPrice + "\t$";
str += s1->discountRate + "\t" + s1->showTaxRate() + "\t$" + s1->finalPrice;
MessageBox::Show(str);
return 0;
}
2. Compile and test the program.
and and and
3. Capture a screen shot similar to the above figure and paste it to the Word document named lab9.doc (or .docx).
Learning Activity #4: Subclass Polymorphism
1. Use Notepad to create a new file named lab9_4.cpp with the following contents:
#using <System.dll>
#using <System.Windows.Forms.dll>
using namespace System;
using namespace System::Windows::Forms;
Visual C++ Programming – Penn Wu, PhD 275
ref class Socal // base class
{
protected:
int staff, faculty;
public:
void setvalues(int x, int y)
{
staff=x;
faculty=y;
}
int total() // form 1
{
return (staff + faculty);
}
String^ getCount()
{
return staff + "\t" + faculty + "\t" + total() + "\n";
}
};
ref class ShermanOaks : public Socal { }; // an empty class
ref class Pomona: public Socal // derived class
{
public:
int total() // form 2
{
return (staff * 0.4 + faculty * 0.6);
}
};
ref class LongBeach: public Socal // derived class
{
public:
int total() // form 3
{
return (staff + faculty / 2);
}
};
int main()
{
Pomona^ s1 = gcnew Pomona();
s1->setvalues(15, 7);
LongBeach^ s2 = gcnew LongBeach();
s2->setvalues(12, 6);
ShermanOaks^ s3 = gcnew ShermanOaks();
s3->setvalues(10, 4);
String^ str = "--------Employees Count-------\n";
str += "Staff\tFaculty\tTotal\n";
str += s1->getCount();
str += s2->getCount();
str += s3->getCount();
MessageBox::Show(str);
Visual C++ Programming – Penn Wu, PhD 276
return 0;
}
2. Compile and test the program.
3. Capture a screen shot similar to the above figure and paste it to the Word document named lab9.doc (or .docx).
Learning Activity #5:
1. Use Notepad to create a new file named lab9_5.cpp with the following contents:
#using <System.dll>
#using <System.Windows.Forms.dll>
using namespace System;
using namespace System::Windows::Forms;
#include "InputBox.cpp"
ref class Sum
{
public:
String^ result;
Sum(int n)
{
int sum = 0;
for (int i=1; i<=n; i++)
{
sum = sum + i;
}
result = sum + "\n";
}
};
ref class Factorial
{
public:
String^ result;
Factorial(int n)
{
int factorial = 1;
for (int i=1; i<=n; i++)
{
factorial = factorial * i;
}
result = factorial + "\n";
}
};
Visual C++ Programming – Penn Wu, PhD 277
ref class Average
{
public:
String^ result;
Average(int n)
{
double avg;
for (int i=1; i<=n; i++)
{
avg = avg + i;
}
result = (avg / n) + "\n";
}
};
ref class Mymath
{
public:
String^ str;
Mymath()
{
String^ option = InputBox::Show("1 - Average, 2 - Factorial, 3 - Sum.
[1/2/3]:");
int n = Convert::ToInt32(InputBox::Show("Enter an integer:"));
if (option == "1")
{
Average^ a1 = gcnew Average(n);
str = a1->result;
}
if (option == "2")
{
Factorial^ f1 = gcnew Factorial(n);
str = f1->result;
}
if (option == "3")
{
Sum^ s1 = gcnew Sum(n);
str = s1->result;
}
}
};
int main()
{
Mymath^ m1 = gcnew Mymath();
MessageBox::Show(m1->str);
}
2. Compile and test the program.
and and
Visual C++ Programming – Penn Wu, PhD 278
3. Capture a screen shot similar to the above figure and paste it to the Word document named lab9.doc (or .docx).
Submittal
1. Complete all the 5 learning activities and the programming exercise in this lab.
2. Create a .zip file named lab9.zip containing ONLY the following self-executable files. Upload the .zip file to
Dropbox.
• lab9_1.exe
• lab9_2.exe
• lab9_3.exe
• lab9_4.exe
• lab9_5.exe
• lab9.doc (or lab9.docx or .pdf) [You may be given zero point if this Word document is missing]
3. Upload the zipped file to Question 11 of Assignment 08 as response.
Programming Exercise 09:
1. Launch the Developer Command Prompt.
2. Use Notepad to create a new text file named ex09.cpp.
3. Add the following heading lines (Be sure to use replace [YourFullNameHere] with the correct one).
//File Name: ex09.cpp
//Programmer: [YourFullNameHere]
4. Given the following class myPoly with a function func() which is the first form (form 1), write codes to create
three other forms of the func() function. Particularly, one integer form, one double form, one that takes two
string parameters.
class myPoly {
public:
String^ func(String^ v1)
{//form1
return "I took " + v1 + ".";
}
//YourCodeHere
};
Form Function Value of n, v1, v2
1 Return a text “I took v1.”
where v1 is a value given
by the main() method.
v1: “CIS223”
2 Return a text “I am an
integer n.” where n is a
value given by the main()
method.
15
3 Return a text “I am a
double value n.” where n is
a value given by the main()
method.
27.84
4 Return a text “I am a v1
and a v2.” where v1 and v2
are string values given by
the main() method.
v1: “student”
v2: “good citizen”
5. In the main() method, create a myPoly object named obj. Use this obj object as reference to call each of the
four forms of func() function with the value(s) specified in the above table. You must clearly apply
polymorphism to the codes to earn the credit, as do the examples provided in the lecture note. [Hint: you
may have to use “\n” to create new lines]
6. The output should look:
Visual C++ Programming – Penn Wu, PhD 279
7. Compile the source code to produce executable code.
8. Download the “programming exercise template” and rename it to ex09.doc if necessary. Copy your source
code to the file and then capture the screen shot(s) similar to the above one and paste it to the Word document
named “ex09.doc” (or .docx).
9. Compress the source file (ex09.cpp), executable code (ex09.exe), and Word document (ex09.doc) to a .zip file
named “ex09.zip”.
Grading criteria:
You will earn credit only when the following requirements are fulfilled. No partial credit is given.
• You successfully submit both source file and executable file.
• Your source code must be fully functional and may not contain syntax errors in order to earn credit.
• Your executable file (program) must be executable to earn credit.
You will receive 0 credit if you simply display the messages without applying polymorphism in your code.
Threaded Discussion
Note: Students are required to participate in the thread discussion on a weekly basis. Student must post at
least two messages as responses to the question every week. Each message must be posted on a
different date. Grading is based on quality of the message.
Question:
Class, if you have write a Visual C++ application for three different types of platform, a Windows-
based desktop, a Windows-based tablet, and a Windows-based smartphone, how would you apply the
concept of inheritance and polymorphism to the coding design of your application? [There is never a
right-or-wrong answer for this question. Please free feel to express your opinion.]
Be sure to use proper college level of writing. Do not use texting language.