Sunteți pe pagina 1din 13

Ministerul Educaiei al Republicii Moldova

Universitatea Tehnic a Moldovei


Catedra Automatica si Tehnologii Informationale

RAPORT
Lucrarea de laborator nr.5
Tema: Mostenirea multipla
Varianta 10

A efectuat:
st. gr. SI-141

E. Cucu

A verificat:
Lector universitar

M. Balan

Chiinu 2015

Scopul lucrrii:

Studierea regulilor de determinare a motenirii multiple;


Studierea avantajelor i neajunsurilor motenirii multiple;
Probleme legate de utilizarea motenirii multiple;
Studierea rezolvrii problemelor;

Indicatii teoretice:
Motenirea multipl, reprezint prin sine motenirea de la dou sau mai multe clase.
Pentru a nelege pentru ce ne trebuie motenirea multipl trebuie s ne amintim, c
motenirea simpl nu rezolv toate problemele, aa cum cteodat ne oblig s alegem dintre
dou clase de baz potrivite.
Este interesant prerea lui Buch referitor la acest mecanism: Motenirea multipl
este ca o paraut: de regul, nu ne trebuie, dar, cnd ntmpltor o s ne trebuiasc, o s ne
par ru dac nu o s fie la ndemn .
n aa fel, acest mecanism este foarte necesar. Dar, el nu se folosete n toate limbajele,
dar este realizat n C++. Ca de exemplu: trebuie de descris clasa Fereastra cu buton i
denumire, ns clasele Fereastra, Fereastra cu buton, Fereastra cu denumire, sunt deja create
i reprezint prin sine urmtoarea ierarhie.
Window

Button
Window

Titled
Window

Button
Titled
Window
Figura 1 Motenirea de la dou clase rude.
Ambele clase pot fi utilizate ca clas de baz, pentru noua, nc ne creat. n lipsa
motenirii multiple ar fi fost necesar de ales i de completat funcionalitile care nu ajung.
Nu numai c utilizatorul este pus n faa unei alegeri, completarea codului, prin sine
contrazice principiului de minimizare a codului i utilizarea lui repetat.
Motenirea multipl are loc i n via:
- Practicantul este student i colaborator vremelnic. El primete not pentru lucrul
su, ca student, i n acelai moment, execut funciile de colaborator, i posibil
primete i salariu.

Tehnicianul dentist este un lucrtor sanitar, aa cum a absolvit universitatea de


medicin, n acelai moment el execut sarcini mai mult specifice fierarilor sau
giuvaerilor.
- Ornitorincul hrnete copiii si cu lapte, ns depune ou.
- Aciunile reprezint hrtii, ori valori de pre.
- Clasa iostream motenete clasele: istream i ostream.
Drept ultimul exemplu nu este tocmai din via, i iari din programare.
-

Definirea
Motenirea multipl se declar n felul urmtor:
class Student{
public:
int mark;
...
};
class Worker{
public:
int salary;
};
class Practicant: public Student, public Worker{
};
void PutMark(Student& s, int mark){
s.mark = mark;
}
void PutSalary(Worker& w, int salary){
w. salary = salary;
}
void main(){
Practicant p;
PutMark(p,5);
PutSalary(p,200);
}

Din exemplu se vede, c clasa derivat import comportamentul ambelor clase de baz,
aa cum, , cu parametrii ambelor funcii globale, adic principiul de
rmne in vigoare! Desigur c, rmne n vigoare i posibilitatea de utilizare a formelor de
motenire, se poate de motenit deschis de la una i nchis de la alta.
Problemele
Ca i orice alt instrument puternic i frumos, motenirea multipl are neajunsurile sale,
care au devenit motivul de eliminare a motenirii multiple din multe limbaje moderne.
Problemele apar din motivul apariiei . Presupunem, c n ambele clase
de baz exist cmpuri cu unul i acelai nume.
class A{
public:
int x;
};
class B{
public:
int x;
};

class C: public A, public B{


};
void main(){
C c;
c.x = 10;
}

n aa fel clasa C conine dou variabile cu unul i acelai nume, aa cum se motenesc
ambele, deoarece pentru fiecare clasa de baz variabila poate s aib un sens propriu.
Compilatorul nu poate decide, crei din variabilele motenite sa-i atribuie valoarea nou.
Aceiai situaie are loc i cu funciile.
Rezolvarea acestei neechivalene const n utilizarea precizrii numelui variabilei.
Numele variabilelor pot coincide, dar numele claselor nu coincid. Aa c, pentru indicarea
variabilei care este utilizat trebuie de indicat clasa, de la care este motenit variabila:
c.A::x = 10;
c.B::x = 5;

Mai dificil este cnd clasele A i B sunt nrudite, adic provin de la aceleai clase, aa
cum este prezentat n figura 1, cu toate c poate exista un caz mai dificil. n aceast
configurare exist dou variabile identice, cu unul i acelai sens. Se pot deosebi, aa cum
este prezentat mai sus. Dar problema const n aceia, c ele i dup sens sunt identice, iar
funciile definite n nivelul doi al ierarhiei, vor lucra n propriile copiii ale variabilelor, care
des duc la greeli semantice greu de gsit. Mai mult ca att, n acest caz, constructorul clasei
de baz este chemat de dou ori. Pentru rezolvarea acestei probleme se utilizeaz ultima
form de motenire: virtual.
class A{
public:
int x;
A(int x){this->x=x;}
};
class B: virtual public A{
public:
B(int x):A(x){}
};
class C: virtual public A{
public:
C(int x):A(x){}
};
class D: public B, public C{
public:
D(int x):A(x),B(x),C(x){}
}

Aa cum se vede clasele B i C trebuie ambele s moteneasc clasa A. Imediat se


rezolv problema despre existena a dou variabile identice. Mai mult ca att, n acest caz
este necesar de chemat constructorul clasei de baz manual, aa cum este artat n exemplu.
Deoarece nu ntotdeauna ierarhia este proiectat de un dezvoltator, i unele clase deja pot fi
compilate, n asemenea cazuri rezolvarea problemei este practice imposibil.

Sarcina lucrarii:
a) S se creeze, o ierarhie de motenire: vehicul, camion maina de teren.
b) S se creeze, o ierarhie de motenire: automobil - vehicul, camion main de teren.

Listingul programului:
a)ierarhia vehicul,camion-masina de teren
Headeruri-le Vehicle,Truck,Terrain_car.h
//
// Created by JACK on 11/6/2015.
//
#ifndef CEF05A_VEHICLE_H
#define CEF05A_VEHICLE_H
#include <iostream>
using namespace std;
class Vehicle {
protected:
string name;
int price;
public:
Vehicle();
Vehicle(string,int);
Vehicle(const Vehicle&);
Vehicle& operator =(const Vehicle&);
friend istream& operator >>(istream&, Vehicle&);
friend ostream& operator <<(ostream&,const Vehicle&);
virtual ~Vehicle();
};
#endif //CEF05A_VEHICLE_H
//
// Created by JACK on 11/6/2015.
//
#ifndef CEF05A_TRUCK_H
#define CEF05A_TRUCK_H
#include <iostream>
using namespace std;
class Truck {
protected:
int power;
int weight;
public:
Truck();
Truck(int,int);
Truck(const Truck&);

Truck& operator =(const Truck&);


friend istream& operator >>(istream&, Truck&);
friend ostream& operator <<(ostream&,const Truck&);
virtual ~Truck();
};
#endif //CEF05A_TRUCK_H
//
// Created by JACK on 11/6/2015.
//
#ifndef CEF05A_TRACTOR_H
#define CEF05A_TRACTOR_H
#include "Vehicle.h"
#include "Truck.h"
class Terrain_car :public Vehicle,public Truck {
string type;
public:
Terrain_car();
Terrain_car(string,int,int,int,string);
Terrain_car(const Terrain_car&);
Terrain_car& operator =(const Terrain_car&);
friend istream& operator >>(istream&, Terrain_car&);
friend ostream& operator <<(ostream&,const Terrain_car&);
~Terrain_car();
};
#endif //CEF05A_TRACTOR_H

Fisieruile sursa Vehicle,Truck,Terrain_car.cpp


//
// Created by JACK on 11/6/2015.
//
#include "Vehicle.h"
Vehicle::Vehicle():name(""),price(0) { }
Vehicle::Vehicle(string name,int price):name(name),price(price) { }
Vehicle::Vehicle(const Vehicle&
vehicle1):name(vehicle1.name),price(vehicle1.price) { }
Vehicle& Vehicle::operator=(const Vehicle& obj) {
if(this == &obj) {
return *this;
}
name = obj.name;
price = obj.price;
return *this;
}
istream& operator>>(istream& in, Vehicle& obj) {
cout << "Input name : ";
in >> obj.name;
cout << "Input price : ";
in >> obj.price;

return in;
}
ostream& operator<<(ostream& out, const Vehicle& obj) {
out << "Name : " << obj.name;
out << "\nPrice : " << obj.price;
return out;
}
Vehicle::~Vehicle() {
name = "";
price = 0;
}
//
// Created by JACK on 11/6/2015.
//
#include "Truck.h"
Truck::Truck():power(0),weight(0) { }
Truck::Truck(int power, int weight):power(power),weight(weight) { }
Truck::Truck(const Truck& obj):power(obj.power),weight(obj.weight) { }
Truck& Truck::operator=(const Truck& obj) {
if (this == &obj) {
return *this;
}
power = obj.power;
weight = obj.weight;
return *this;
}
istream& operator>>(istream& in, Truck& obj) {
cout << "Input power : ";
in >> obj.power;
cout << "Input weight : ";
in >> obj.weight;
return in;
}
ostream& operator<<(ostream& out, const Truck& obj) {
out << "\nPower : " << obj.power;
out << "\nWeight : " << obj.weight;
return out;
}
Truck::~Truck() {
power = 0;
weight = 0;
}
//
// Created by JACK on 11/6/2015.
//
#include "Terrain_car.h"
Terrain_car::Terrain_car(): Vehicle(),Truck(),type("") { }

Terrain_car::Terrain_car(string name,int price,int power,int weight,string


type):
Vehicle(name,price),Truck(power,weight),type("") { }
Terrain_car::Terrain_car(const Terrain_car& car):
Vehicle(car),Truck(car),type(car.type) { }
Terrain_car& Terrain_car::operator=(const Terrain_car& car) {
if (this == &car) {
return *this;
}
Vehicle::operator=(dynamic_cast<const Vehicle&>(car));
Truck::operator=(dynamic_cast<const Truck&>(car));
type = car.type;
return *this;
}
istream& operator>>(istream& in, Terrain_car& car) {
in >> dynamic_cast<Vehicle&>(car);
in >> dynamic_cast<Truck&>(car);
cout << "Input type : ";
in >> car.type;
return in;
}
ostream& operator<<(ostream& out, const Terrain_car& car) {
out << dynamic_cast<const Vehicle&>(car);
out << dynamic_cast<const Truck&>(car);
out << "\nType : " << car.type;
return out;
}
Terrain_car::~Terrain_car() {
type = "";
}

Fisierul main.cpp
#include <iostream>
#include <stdlib.h>
#include "Terrain_car.h"
using namespace std;
int main() {
Terrain_car mycar;
cin >> mycar;
system("cls");
cout << mycar;
cout << endl;
system("pause");
return 0;
}

b) ierarhia automibil-vehicul,camion-masina de teren


Headeruri-le Transpor,Vehicle,Truck,Terrain_car.h
//
// Created by JACK on 11/6/2015.
//

#ifndef CEF05A_TRANSPORT_H
#define CEF05A_TRANSPORT_H
#include <iostream>
using namespace std;
class Transport {
protected:
string trans;
public:
Transport();
Transport(string);
Transport(const Transport&);
Transport& operator =(const Transport&);
friend istream& operator >>(istream&, Transport&);
friend ostream& operator <<(ostream&,const Transport&);
virtual ~Transport();
};
#endif //CEF05A_TRANSPORT_H
//
// Created by JACK on 11/6/2015.
//
#ifndef CEF05A_VEHICLE_H
#define CEF05A_VEHICLE_H
#include "Transport.h"
class Vehicle : virtual public Transport {
protected:
string name;
int price;
public:
Vehicle();
Vehicle(string,string,int);
Vehicle(const Vehicle&);
Vehicle& operator =(const Vehicle&);
friend istream& operator >>(istream&, Vehicle&);
friend ostream& operator <<(ostream&,const Vehicle&);
virtual ~Vehicle();
};
#endif //CEF05A_VEHICLE_H
//
// Created by JACK on 11/6/2015.
//
#ifndef CEF05A_TRUCK_H
#define CEF05A_TRUCK_H
#include "Transport.h"
class Truck : virtual public Transport {
protected:
int power;
int weight;
public:
Truck();
Truck(string,int,int);
Truck(const Truck&);

Truck& operator =(const Truck&);


friend istream& operator >>(istream&, Truck&);
friend ostream& operator <<(ostream&,const Truck&);
virtual ~Truck();
};
#endif //CEF05A_TRUCK_H
//
// Created by JACK on 11/6/2015.
//
#ifndef CEF05A_TRACTOR_H
#define CEF05A_TRACTOR_H
#include "Vehicle.h"
#include "Truck.h"
class Terrain_Car :public Vehicle,public Truck {
string type;
public:
Terrain_Car();
Terrain_Car(string,string,int,int,int,string);
Terrain_Car(const Terrain_Car&);
Terrain_Car& operator =(const Terrain_Car&);
friend istream& operator >>(istream&, Terrain_Car&);
friend ostream& operator <<(ostream&,const Terrain_Car&);
~Terrain_Car();
};
#endif //CEF05A_TRACTOR_H

Fisierile sursa Transport,Vehicle,Truck,Terrain_car.cpp


//
// Created by JACK on 11/6/2015.
//
#include "Transport.h"
Transport::Transport():trans("") { }
Transport::Transport(string trans):trans(trans) { }
Transport::Transport(const Transport& obj):trans(obj.trans) { }
Transport& Transport::operator=(const Transport& obj) {
if (this == &obj) {
return *this;
}
trans = obj.trans;
return *this;
}
istream& operator>>(istream& in, Transport& obj) {
cout << "Input Transport type : ";
in >> obj.trans;
return in;
}
ostream& operator<<(ostream& out, const Transport& obj) {
out << "Tranport type : " << obj.trans;

return out;
}
Transport::~Transport() {
trans = "";
}
//
// Created by JACK on 11/6/2015.
//
#include "Vehicle.h"
Vehicle::Vehicle(): Transport(),name(""),price(0) { }
Vehicle::Vehicle(string trans,string name,int price):
Transport(trans),name(name),price(price) { }
Vehicle::Vehicle(const Vehicle& vehicle1):
Transport(vehicle1),name(vehicle1.name),price(vehicle1.price) { }
Vehicle& Vehicle::operator=(const Vehicle& obj) {
if(this == &obj) {
return *this;
}
Transport::operator=(dynamic_cast<const Transport&>(obj));
name = obj.name;
price = obj.price;
return *this;
}
istream& operator>>(istream& in, Vehicle& obj) {
in >> dynamic_cast<Transport&>(obj);
cout << "Input name : ";
in >> obj.name;
cout << "Input price : ";
in >> obj.price;
return in;
}
ostream&
out <<
out <<
out <<
return
}

operator<<(ostream& out, const Vehicle& obj) {


dynamic_cast<const Transport&>(obj);
"\nName : " << obj.name;
"\nPrice : " << obj.price;
out;

Vehicle::~Vehicle() {
name = "";
price = 0;
}
//
// Created by JACK on 11/6/2015.
//
#include "Truck.h"
Truck::Truck(): Transport(),power(0),weight(0) { }
Truck::Truck(string trans,int power,int weight):
Transport(trans),power(power),weight(weight) { }

Truck::Truck(const Truck& obj):


Transport(obj),power(obj.power),weight(obj.weight) { }
Truck& Truck::operator=(const Truck& obj) {
if (this == &obj) {
return *this;
}
Transport::operator=(dynamic_cast<const Transport&>(obj));
power = obj.power;
weight = obj.weight;
return *this;
}
istream& operator>>(istream& in, Truck& obj) {
in >> dynamic_cast<Transport&>(obj);
cout << "Input power : ";
in >> obj.power;
cout << "Input weight : ";
in >> obj.weight;
return in;
}
ostream&
out <<
out <<
out <<
return
}

operator<<(ostream& out, const Truck& obj) {


dynamic_cast<const Transport&>(obj);
"\nPower : " << obj.power;
"\nWeight : " << obj.weight;
out;

Truck::~Truck() {
power = 0;
weight = 0;
}
//
// Created by JACK on 11/6/2015.
//
#include "Terrain_Car.h"
Terrain_Car::Terrain_Car(): Vehicle(),Truck(),type("") { }
Terrain_Car::Terrain_Car(string trans,string name,int price,int power,int
weight,string type):
Transport(trans),Vehicle(trans,name,price),Truck(trans,power,weight),type("") {
}
Terrain_Car::Terrain_Car(const Terrain_Car& car):
Transport(car),Vehicle(car),Truck(car),type(car.type) { }
Terrain_Car& Terrain_Car::operator=(const Terrain_Car& car) {
if (this == &car) {
return *this;
}
Vehicle::operator=(dynamic_cast<const Vehicle&>(car));
Truck::operator=(dynamic_cast<const Truck&>(car));
type = car.type;
return *this;
}
istream& operator>>(istream& in, Terrain_Car& car) {
in >> dynamic_cast<Vehicle&>(car);
cout << "Input power : ";

in >> car.power;
cout << "Input weight : ";
in >> car.weight;
cout << "Input type : ";
in >> car.type;
return in;
}
ostream&
out <<
out <<
out <<
out <<
return
}

operator<<(ostream& out, const Terrain_Car& car) {


dynamic_cast<const Vehicle&>(car);
"\nPower : " << car.power;
"\nWeight : " << car.weight;
"\nType : " << car.type;
out;

Terrain_Car::~Terrain_Car() {
type = "";
}

Fisierul main.cpp
#include <iostream>
#include <stdlib.h>
#include "Terrain_Car.h"
using namespace std;
int main() {
Terrain_Car mycar;
cin >> mycar;
system("cls");
cout << mycar;
cout << endl;
system("pause");
return 0;
}

Concluzie:
In urma efectuarii acestei lucrari de laborator capatat cunostinte despre
modul de lucru cu mecanismul multiplu in C++,este un mecanism foarte util
din considerentul ca clasele scrise precedent pot fi utilizate intr-o clasa care
v-a folosi functionalul lor,in plus cu ceva nou.
In mecanismul de mostenire multiplu in cazul in care avem mostenirea
ROMB poate aparea probleme atunci cind o clasa mosteneste de la doua
clase care la rindul lor mostenesc de la clasa mama deexemplu acelasi
cind,pentru prevederea asemenea cazuri este necesar de declarant clasele
care mostenesc de la clasa mama virtuale.