1. Polymorphism
1.1. Publications
Define a class for publication. Each publication is described with the year of publishing (integer) and the name of publishing house.
From this class derive (public) class for book. Each book additionally should have the number of pages.
Derive (protected) a second class named newspaper. Each newspaper has its number.
From the class for newspaper derive (private) a class for daily newspaper. Each daily newspaper has the day and month of publishing.
Review different levels of access to fields and functions!
oop_av81_en.cpp
#include <iostream>
#include <cstring>
using namespace std;
class Publication {
private:
char name [100];
protected:
int year;
char* getName() {
return name;
}
public:
int getYear() { return year;}
void print () {
cout << "Publication: " << name << " - " << year << endl;
}
Publication( char *name, int year ) {
strcpy(this->name, name);
this->year = year;
}
};
// public inheritance
class Book: public Publication {
private:
int number_of_pages;
public:
Book(char *name, int year, int number_of_pages): Publication(name, year) {
this->number_of_pages = number_of_pages;
}
void printBookYear() {
cout << year; // access to protected resource year
}
void printBookName () {
// access to getName(), name can be accessed because it's private
cout << getName();
}
void numberOfPages() {
cout << number_of_pages;
}
};
// protected inheritance
class Newspaper: protected Publication {
private:
int number;
public:
Newspaper(char* name, int year, int number): Publication(name, year) {
this->number = number;
}
void printYearNewspaper () {
cout << getYear(); // access to public getYear(), that in this class has protected access
}
void printNameNewspaper() {
cout << getName(); // access to getName(), name that can not be accessed because it is private
}
void printNumber() {
cout << number;
}
};
// private inheritance
class DailyNewspaper: private Newspaper {
private:
int day;
int month;
public:
DailyNewspaper(char *name, int day, int month, int year,
int number): Newspaper(name, year, number) {
this->day = day;
this->month = month;
}
using Newspaper::print; // function print from Publication becomes public for DailyNewspaper
using Newspaper::printNumber; // function printNumber from Publication becomes public for DailyNewspaper
};
int main() {
Publication p("Tabernakul", 1992);
p.print(); // public - function
Book *k = new Book("ProsvetnoDelo", 1900, 123);
k->print(); //print is public in Book
k->printBookYear(); // public - function
// cout<<k->getName(); // error! protected - function
Newspaper *s = new Newspaper("Tea", 2013 , 30);
// s->print(); //error! protected - function
// cout<<s->getYear(); // error! protected - function
s->printNameNewspaper(); // public - function
DailyNewspaper d("Vest", 2, 3, 2014, 25);
d.print(); //public-function
// d.printNameNewspaper(); // error! private - function
// cout<<d.getName(); // error! private – function
}
1.2. Hotel reservation
Define a class for HotelReservation
with number of days, number of persons and contact name.
The price for the reservation for one person is 25 EUR per day.
In the class define function price()
that returns the total price of the reservation.
Also define function price(int payment)
that returns the price with the given payment.
Derive a class BBHotelReservation
for reservation only with breakfast.
Price of the breakfast for one person is 5 EUR.
Override the function price(int payment)
.
Define a class Hotel
with name of the hotel and the balance.
Implement a function int reserve(HotelReservation &hr, int payment)
.
This function should make a payment for given hotel reservation.
If the payment surpass the needed amount the function should return the change.
The payment is made on the hotel balance.
What will happen if the argument is not reference?
oop_av82.cpp
#include<iostream>
#include<cstring>
using namespace std;
class HotelskaRezervacija{
protected:
int denovi;
int broj_lica;
char ime[50];
char prezime[50];
public:
HotelskaRezervacija(char *ime, char *prezime, int denovi, int broj_lica){
strcpy(this->ime,ime);
strcpy(this->prezime, prezime);
this->denovi=denovi;
this->broj_lica=broj_lica;
}
virtual int vratiCena() {
return denovi * broj_lica * 25;
}
virtual int vratiCena(int uplata) {
if (uplata >= vratiCena())
return uplata - vratiCena();
else {
cout<<"Za vashata rezervacija treba da naplatite "<<vratiCena()<<endl;
return -1;
}
}
};
class PolupansionskaHotelskaRezervacija: public HotelskaRezervacija{
public:
PolupansionskaHotelskaRezervacija(char *ime, char *prezime, int denovi, int
broj_lica) : HotelskaRezervacija(ime,prezime,denovi,broj_lica){}
//препокривање на vratiCena(int uplata)
int vratiCena(int uplata){
int cena= HotelskaRezervacija::vratiCena() + broj_lica * 5; // пристап до protected податокот broj_lica
if (uplata >= cena)
return uplata - cena;
else {
cout<<"Za vashata rezervacija treba da naplatite "<<cena<<endl;
return -1;
}
}
};
class Hotel{
private:
char ime[50];
int saldo;
public:
Hotel(char *ime) {
strcpy(this->ime, ime);
saldo = 0;
}
// референца кон основната класа може да референцира објекти и кон изведените класи
int uplatiZaRezervacija(HotelskaRezervacija &hr, int uplata) {
int kusur=hr.vratiCena(uplata); //полиморфизам
// која дефиниција на vratiCena ќе се повика?
// важно: vrtiCena е виртуелна функција
if (kusur != -1)
saldo += uplata - kusur;
return kusur;
}
};
int main() {
Hotel h("Bristol");
HotelskaRezervacija *hr1=new HotelskaRezervacija("Petko","Petkovski",5,5);
int cena = h.uplatiZaRezervacija(*hr1,1000);
if (cena!=-1)
cout<<"Kusur : "<<cena<<endl;
PolupansionskaHotelskaRezervacija *hr2=
new PolupansionskaHotelskaRezervacija("Risto","Ristovski",5,5);
cena=h.uplatiZaRezervacija(*hr2,1000);
if (cena!=-1)
cout<<"Kusur : "<<cena<<endl;
//покажувач кон основна класа покажува кон објект од изведена
HotelskaRezervacija *hr3=new PolupansionskaHotelskaRezervacija("Ana","Anovska",4,2);
cena=h.uplatiZaRezervacija(*hr3,100);
if (cena!=-1)
cout<<"Kusur : "<<cena<<endl;
PolupansionskaHotelskaRezervacija hr4("Tome","Tomovski",5,3);
cena=h.uplatiZaRezervacija(hr4,1000);
if (cena!=-1)
cout<<"Kusur : "<<cena<<endl;
}
1.3. Geometric shapes
Define an abstract class for geometric shape with height and base of different geometric figure.
Define the following functions in the class:
- print()
that prints the info for the shape
- volume()
returns the volume of the shape
- height()
returns the height of the shape.
From the class geometric shape derive class for cylinder, cone and cuboid.
For a cylinder and cone store the radius of the base.
For the cuboid store the sides a
and b
of the basis.
In the main
function declare and initialize dynamically allocated array of pointers of the class for geometric shape.
From this array:
-
Find the shape with maximum volume using the global function:
void maxVolume(Shape *array[], int n);
This function should print the info for the shape with maximum volume. -
Find the number of shapes that don’t have basis circle using the global function:
double getRadius(Shape *s);
. This function returns the radius of the basis (if the basis is circle), -1 otherwise.
oop_av83_en.cpp
#include<iostream>
#include<cmath>
using namespace std;
class Shape {
protected:
double height;
public:
Shape (int height = 0) {
this->height = height;
}
virtual void print() { //virtual function
cout << height;
}
virtual double getVolume() = 0; //pure virtual function
double getHeight() const {
return height;
}
};
class Cylinder: public Shape {
private:
double radius;
public:
// constructor
Cylinder(double radius, double height): Shape(height) {
this->radius = radius;
}
// overriding function print()
void print() {
cout << "Cylinder with height ";
Shape::print();
cout << " and radius of tha basis" << radius << endl;
}
// overriding function getVolume()
double getVolume() {
return M_PI * radius * radius * getHeight();
}
double getRadius() {
return radius;
}
};
class Cone: public Shape {
private:
double radius;
public:
// constructor
Cone(double radius, double height): Shape(height) {
this->radius = radius;
}
// overriding function print()
void print() {
cout << "Cone with height ";
Shape::print();
cout << " and with radius of basis " << radius << endl;
}
// overriding function getVolume()
double getVolume() {
return M_PI * radius * radius * getHeight() / 3.0;
}
double getRadius() {
return radius;
}
};
class Cuboid: public Shape {
private:
double a, b;
public:
// constructor
Cuboid(double a, double b, double height): Shape(height) {
this->a = a;
this->a = b;
}
// overriding function print()
void print() {
cout << "Cuboid with height ";
Shape::print();
cout << "and with basis " << this->a << " i " << this->b << endl;
}
// overriding function getVolume()
double getVolume() {
return a * b * getHeight();
}
};
void maxVolume(Shape *shapes[], int n );
double getRadius (Shape *s);
int main() {
Shape** shapes; // dynamically allocated array of pointers of Shape
int n;
cin >> n; // number of elements in the array
shapes = new Shape*[n]; // allocate the pointer array
for (int i = 0 ; i < n ; i++) {
int r, a, b, h, type;
cout << "Shape: 1-cylinder 2-cone 3-cuboid" << endl;
cin >> type;
if (type == 1) { // for Cylinder
cin >> r >> h; shapes[i] = new Cylinder(r, h);
} else if (type == 2) { // for Cone
cin >> r >> h; shapes[i] = new Cone(r, h);
} else if (type == 3) { // for Cuboid
cin >> a >> b >> h; shapes[i] = new Cuboid(a, b, h);
}
}
// 1.
maxVolume(shapes, n);
// 2.
int counter = 0;
for (int i = 0 ; i < n ; i++)
if (getRadius(shapes[i]) == -1)
counter++;
cout << "Number of shapes with base circle is " << counter;
}
void maxVolume(Shape *shapes[], int n)
{
int max = 0;
int maxIndex = 0;
for (int i = 0 ; i < n ; i++)
{
if (shapes[i]->getVolume() > max) {
// call virtual function getVolume()
max = shapes[i]->getVolume();
maxIndex = i;
}
}
cout << "Shape with max volume is:";
shapes[maxIndex]->print(); // virtual call of function print()
}
double getRadius(Shape *g) {
// runtime cast
Cylinder* c = dynamic_cast<Cylinder *>(g);
if (c != 0) { // if cast fails
return c->getRadius();
}
// runtime cast
Cone* k = dynamic_cast<Cone *>(g);
if (k != 0 ) { // if cast fails
return k->getRadius();
}
return -1; // if g is not a pointer to Cylinder or Cone return -1
}