• Nenhum resultado encontrado

LINGUAGEM DE PROGRAMAÇÃO C++ HIERARQUIA DE CLASSES HIERARQUIA DE CLASSES HERANÇA SIMPLES DEFINIÇÃO UMA CLASSE BASE

N/A
N/A
Protected

Academic year: 2021

Share "LINGUAGEM DE PROGRAMAÇÃO C++ HIERARQUIA DE CLASSES HIERARQUIA DE CLASSES HERANÇA SIMPLES DEFINIÇÃO UMA CLASSE BASE"

Copied!
24
0
0

Texto

(1)

LINGUAGEM DE PROGRAMAC¸ ˜AO C++ HIERARQUIA DE CLASSES Roberto S. Bigonha UFMG 01 de abril de 2009 & % HIERARQUIA DE CLASSES & % ' $ HIERARQUIA DE CLASSES HERANC¸ A SIMPLES

• heran¸ca ´e uma t´ecnica para construir novas classes, chamadas de classes derivadas, a partir das j´a existentes, ditas classes base • heran¸ca permite o re´uso do comportamento de uma classe

• a classe derivada herda todas as caracter´ısticas de sua classe base e pode adicionar novas caracter´ısticas

• heran¸ca permite construir hierarquia de classes

• heran¸ca permite classificar tipos da mesma forma que tipos classificam valores

• heran¸ca estabelece as rela¸c˜oes de especializa¸c˜ao e generaliza¸c˜ao entre as classes base e derivadas

• membros da classe base podem ser redefinidos na classe derivada

' $

HIERARQUIA DE CLASSES

DEFINIC¸ ˜AO UMA CLASSE BASE

class Time {

int hours, minutes, seconds; public:

Time(int hr, int min, int sec){

hours = hr; minutes = min; seconds = sec; }

void display(){

cout << hours << ’:’ << minutes << ’:’ << seconds; }

(2)

' $

HIERARQUIA DE CLASSES

DEFININDO CLASSE DERIVADA

enum timezone { gmt, est, cst, mst, pst }; char *TZ[] = {"GMT","EST","CST","MST","PST"}; class TimeZone : public Time {

|

timezone zone; +--- default ´e private public:

TimeZone(int hr, int min, int sec, timezone zn) : Time(hr,min,sec){zone=zn;} timezone getZone( ) {return zone;}

void display(){Time::display();cout << ’ ’ << TZ[zone];} };

c++/rsb 4

& %

' $

HIERARQUIA DE CLASSES

USANDO BASE E DERIVADA

int main() { Time tm(23, 15, 45); tm.display(); cout << ’\n’; TimeZone tz(10, 26, 0, est); tz.display(); } SAIDA: 23:15:45 10:26:0 EST c++/rsb 5 & % ' $

CONSTRUTORAS DE CLASSE DERIVADA

' $

CONSTRUTORAS DE CLASSE DERIVADA

CONSTRUTORAS DE CLASSE DERIVADA

• Quando um objeto de classe derivada ´e declarado, a fun¸c˜ao

construtora da base ´e executada e, em seguida, executa-se a fun¸c˜ao construtora da derivada

• A lista de parˆametros da construtora da derivada deve conter os parˆametros da construtora da base

• A chamada da construtora da base deve ser indicada explicitamente como abaixo

class TimeZone : public Time{ ...

TimeZone(int hr, int min, int sec, timezone zn)

: Time(hr, min, sec) { ... }; ...

(3)

CONSTRUTORAS DE CLASSE DERIVADA ...

• A lista de argumentos da construtora da classe base deve aparecer na declara¸c˜ao da construtora da derivada

• A chamada `a construtora da classe base deve estar associada a declara¸c˜ao da fun¸c˜ao e n˜ao do prot´otipo

class TimeZone : public Time{ ...

TimeZone(int hr, int min, int sec, timezone zn); ...

}

TimeZone::TimeZone(int hr,int min,int sec,timezone zn) :Time(hr,min,sec){ ...

}

c++/rsb 8

& %

CLASSE DERIVADA DE BASE DERIVADA ...

• Se n˜ao houver chamada expl´ıcita de construtora, a construtora sem parˆametros ´e chamada

class A { int x; public:

A( ):x(100) { }

int getX( ){return x;} };

class B: public A { int y;

public:

B(){ y = 1000; }

int gety( ) {return y;} };

int main(){ B b;

printf("x= %d y= %d\n", b.getX(), b.gety()); }

Sa´ıda: 100 1000

c++/rsb 9

& %

' $

CONSTRUTORAS DE CLASSE DERIVADA

CLASSE DERIVADA DE BASE DERIVADA ...

inline int adjust(int hour){

return hour > 12 ? hour - 12 :(hour == 0 ? 12 : hour); }

inline char makeampm(int hour){ return hour < 12 ? ’a’ : ’p’; }

' $

CONSTRUTORAS DE CLASSE DERIVADA

CLASSE DERIVADA DE BASE DERIVADA...

class DispTime : public TimeZone { char ampm;

public:

DispTime(int hr, int min, int sec, timezone zn)

: TimeZone(adjust(hr), min, sec, zn){ ampm = makeampm(hr);

}

void display() { Time::display();

cout << ’ ’ << ampm << ’m’; << ’ ’ << TZ[getZone()]; }

(4)

' $

CONSTRUTORAS DE CLASSE DERIVADA

CLASSE DERIVADA DE BASE DERIVADA...

int main(){ DispTime dt(21, 42, 12, pst); dt.display(); return 0; } SAIDA: 9:42:12 pm PST c++/rsb 12 & % ' $

CONSTRUTORAS DE CLASSE DERIVADA

CONSTRUTORA PRIVADA E SUBCLASSES

class A{ public: int x; A( ): x(10){ } int f( ){return x;} }; class B: public A { }; int main( ){ B b; printf("x = %d", b.f()); } Sa´ıda: x = 10; class A { int x; A( ): x(10){ } public: int f( ){return x;} }; class B: public A { }; int main( ) { B b; // Erro aqui printf("x = %d", b.f()); } A e B compilam normalmente Erro na compila¸c˜ao de B b c++/rsb 13 & % ' $

CONSTRUTORAS DE CLASSE DERIVADA

PONTEIROS E CLASSES DERIVADAS OU BASE

• Um apontador para uma classe base pode apontar para um objeto de uma classe dela derivada

• O tipo com o qual o ponteiro ´e declarado ´e o seu tipo est´atico e o tipo do objeto apontado ´e o seu tipo dinˆamico

• Os componentes n˜ao-virtuais da classe declarada para o ponteiro continuam acess´ıveis atrav´es dele, mesmo quando anulados (redefinidos)

int main(){

DispTime dt(21, 42, 12, pst);

Time *tp = &dt; TimeZone *zp = &dt; DispTime *dp = &dt; tp->display(); zp->display(); dp->display();

return 0; }

SAIDA: 9:42:12 9:42:12 PST 9:42:12 pm PST

' $

CONSTRUTORAS DE CLASSE DERIVADA

RESOLUC¸ ˜AO DE ESCOPO GLOBAL

int main(){

DispTime dt(21, 42, 12, pst); DispTime *dp = &dt; dp ->display(); // usa display de DispTime cout << ’\n’; // SAIDA: 9:42:12 pm PST dt.display(); cout << ’\n’; // SAIDA: 9:42:12 pm PST dp ->TimeZone::display(); // usa display de TimeZone cout << ’\n’; // SAIDA: 9:42:12 PST dt.TimeZone::display(); // SAIDA: 9:42:12 PST cout << ’\n’;

dp ->Time::display(); // usa display de Time cout << ’\n’; // SAIDA: 9:42:12 dt.Time::display(); // SAIDA: 9:42:12 cout << ’\n’;

(5)

REFERˆENCIAS A CLASSE BASE E DERIVADA

• Uma referˆencia a uma classe base pode ser iniciada com um objeto de classe dela derivada

• O tipo com o qual a referˆencia ´e declarada ´e o seu tipo est´atico e o tipo do objeto referido ´e o seu tipo dinˆamico

• Os componentes n˜ao-virtuais da classe declarada para a referˆencia continuam acess´ıveis atrav´es dela, mesmo quando anulados

(redefinidos) int main(){

DispTime dt(21, 42, 12, pst);

Time& tp = dt; TimeZone& zp = dt; DispTime& dp = dt; tp.display(); zp.display(); dp.display();

return 0;

} // SAIDA: 9:42:12 9:42:12 PST 9:42:12 pm PST

c++/rsb 16

& %

ESCOPO DOS MEMBROS DE CLASSE

• membros p´ublicos (public) de uma classe s˜ao acess´ıveis a todo o programa

• membros privados (private) de uma classe somente s˜ao acess´ıveis a membros fun¸c˜oes da classe

• membros privados da classe base n˜ao s˜ao acess´ıveis `a classe derivada • membros protegidos(protected) da classe base s˜ao acess´ıveis a

membros de classes derivadas (filhas, netas, ...), mas privados para o resto do programa

c++/rsb 17

& %

' $

CONSTRUTORAS DE CLASSE DERIVADA

ESCOPO DOS MEMBROS DA CLASSE BASE

•class B : private A { ... } ou class B : A { ... }:

os membros p´ublicos e protegidos de uma classe base s˜ao membros privados da classe derivada de classe base private

•class B : public A { ... }:

os membros p´ublicos e protegidos de uma classe base s˜ao,

respectivamente, membros p´ublicos e protegidos da classe derivada de classe base public

•class B : protected A { ... }:

os membros p´ublic ou protected da classe base s˜ao membros protected da classe derivada de classe base protected.

' $

CONSTRUTORAS DE CLASSE DERIVADA

ESCOPO DOS MEMBROS DE CLASSE...

class X {

int priv;// private por default protected: int prot; public: int publ; void m(); } void X::m() { priv := 1; // OK prot := 2; // OK publ := 3; // OK }

(6)

' $

CONSTRUTORAS DE CLASSE DERIVADA

ESCOPO DOS MEMBROS DE CLASSE...

void Y::g( ) {

priv := 1; // ERRO: priv ´e privado

prot := 2; // OK: prot ´e protected e g ´e membro de // classe derivada

publ := 3; // OK: publ ´e publico }

void f(Y* p) {

p-> priv := 1; // ERRO:priv ´e privado

p-> prot := 2; // ERRO:prot ´e protected, mas f n~ao // ´e friend ou membro de X ou Y p-> publ := 3; // OK: publ ´e public

}

c++/rsb 20

& %

' $

FUNC¸ ˜OES VIRTUAIS

& %

' $

Fun¸c˜oes Virtuais

FUNC¸ ˜OES VIRTUAIS

• Fun¸c˜ao virtual ´e aquela definida numa classe base e que espera ser anulada por uma fun¸c˜ao em uma classe derivada como o mesmo nome e tipos de parˆametros

• Um apontador para uma classe base pode apontar para um objeto de uma classe dela derivada

• Os componentes virtuais acess´ıveis da classe s˜ao os componentes do objeto apontado, independentemente do tipo do apontador que chama o componente

• Virtual somente a partir do ponto na hierarquia em que foi declarada virtual

• Uma vez virtual, sempre virtual

• Tipo polim´orfico ´e tipo com fun¸c˜oes virtuais

' $

Fun¸c˜oes Virtuais

CLASSE COM FUNC¸ ˜OES VIRTUAIS

class Time {

int hours, minutes, seconds; public:

Time(int hr, int min, int sec){

hours = hr; minutes = min;seconds = sec; }

virtual void display(){

cout << hours << ’:’ << minutes << ’:’ << seconds; }

(7)

CLASSE COM FUNC¸ ˜OES VIRTUAIS...

enum timezone { gmt, est, cst, mst, pst }; char *TZ[] = {"GMT","EST","CST","MST","PST"}; class TimeZone : public Time {

timezone zone; public:

TimeZone(int hr,int min,int sec,timezone zn) :Time(hr,min,sec){ zone = zn;

}

virtual void display() { // virtual opcional

Time::display(); cout << ’ ’ << TZ [zone]; }

};

c++/rsb 24

& %

CLASSE COM FUNC¸ ˜OES VIRTUAIS...

inline int adjust(int hour) {

return hour > 12 ? hour - 12 :(hour == 0 ? 12 : hour); }

inline char makeampm(int hour) { return hour < 12 ? ’a’ : ’p’; }

c++/rsb 25

& %

' $

Fun¸c˜oes Virtuais

CLASSE COM FUNC¸ ˜OES VIRTUAIS...

class DispTime : public TimeZone { char ampm;

public:

DispTime(int hr,int min,int sec,timezone zn)

: TimeZone(adjust(hr),min,sec,zn){ampm=makeampm(hr);} void display(){ Time::display(); cout << ’ ’ << ampm << ’m’; cout << ’ ’ << TZ [zone]; } }; ' $

Fun¸c˜oes Virtuais

REFERˆENCIA A UMA FUNC¸ ˜AO VIRTUAL

(8)

' $

Fun¸c˜oes Virtuais

ANULANDO O ANULAMENTO int main(){ DispTime dt(21, 42, 12, pst); Time& tp = dt; TimeZone& zp = dt; DispTime& dp = dt; tp.Time::display(); cout << ‘\n’; zp.TimeZone::display(); cout << ‘\n’; dp.display(); } SAIDA: 9:42:12 9:42:12 PST 9:42:12 pm PST c++/rsb 28 & % ' $

Fun¸c˜oes Virtuais

LIGAC¸ ˜AO DINˆAMICA DE M´ETODOS I

class A {

public: int i; A( ){i = 10;}

private: virtual void increment( ) { i++; } public: virtual void display( ) {

increment( ); printf("i = %d\n", i); }

};

class B: public A {

public: int i; B() {i = 20;} public: void increment( ){ i++; } };

int main( ) {

B* x = new B( ); x->display( ); // Sa´ıda: i = ? }

c++/rsb 29

& %

' $

Fun¸c˜oes Virtuais

LIGAC¸ ˜AO DINˆAMICA DE M´ETODOS I ...

class A {

public: int i; A( ){i = 10;}

private: virtual void increment( ) { i++; } public: virtual void display( ) {

increment( ); printf("i = %d\n", i); }

};

class B: public A {

public: int i; B() {i = 20;} public: void increment( ){ i++; } };

int main( ) {

B* x = new B( ); x->display( ); // Sa´ıda: i = 10 }

' $

Fun¸c˜oes Virtuais

LIGAC¸ ˜AO DINˆAMICA DE M´ETODOS II

class A {

public: int i; A( ){i = 10;}

private: void increment( ) { i++; } public: virtual void display( ) {

increment( ); printf("i = %d\n", i); }

};

class B: public A {

public: int i; B() {i = 20;} public: void increment( ){ i++; } };

int main( ) {

(9)

LIGAC¸ ˜AO DINˆAMICA DE M´ETODOS II...

class A {

public: int i; A( ){i = 10;}

private: void increment( ) { i++; } public: virtual void display( ) {

increment( ); printf("i = %d\n", i); }

};

class B: public A {

public: int i; B() {i = 20;} public: void increment( ){ i++; } };

int main( ) {

B* x = new B( ); x->display( ); // Sa´ıda: i = 11 }

c++/rsb 32

& %

LIGAC¸ ˜AO DINˆAMICA DE M´ETODOS III

class A {

public: int i; A( ){i = 10;}

private: void increment( ) { i++; } public: virtual void display( ) {

increment( ); printf("i = %d\n", i); }

};

class B: public A {

public: int i; B() {i = 20;} private: void increment( ){ i++; } };

int main( ) {

B* x = new B( ); x->display( ); // Sa´ıda: i = ? }

c++/rsb 33

& %

' $

Fun¸c˜oes Virtuais

LIGAC¸ ˜AO DINˆAMICA DE M´ETODOS III...

class A {

public: int i; A( ){i = 10;}

private: void increment( ) { i++; } public: virtual void display( ) {

increment( ); printf("i = %d\n", i); }

};

class B: public A {

public: int i; B() {i = 20;} private: void increment( ){ i++; } };

int main( ) {

B* x = new B( ); x->display( ); // Sa´ıda: i = 11 }

' $

Fun¸c˜oes Virtuais

LIGAC¸ ˜AO DINˆAMICA DE M´ETODOS IV

class A {

public: int i; A( ){i = 10;}

private: virtual void increment( ) { i++; } public: virtual void display( ) {

increment( ); printf("i = %d\n", i); }

};

class B: public A {

public: int i; B() {i = 20;} private: void increment( ){ i++; } };

int main( ) {

(10)

' $

Fun¸c˜oes Virtuais

LIGAC¸ ˜AO DINˆAMICA DE M´ETODOS IV

class A {

public: int i; A( ){i = 10;}

private: virtual void increment( ) { i++; } public: virtual void display( ) {

increment( ); printf("i = %d\n", i); }

};

class B: public A {

public: int i; B() {i = 20;} private: void increment( ){ i++; } };

int main( ) {

B* x = new B( ); x->display( ); // Sa´ıda: i = 10 }

c++/rsb 36

& %

' $

Fun¸c˜oes Virtuais

RESPEITO `A ENCAPSULAC¸ ˜AO

• Cada classe deve cuidar somente de seus dados locais

• Subclasses nunca devem ter acesso direto a dados herdados • Acesso a dados das superclasses devem ser via os canais

competentes

• Altera¸c˜oes em dados internos da superclasse n˜ao devem afetar a corre¸c˜ao de suas subclasses

• Ad´agio romano[Apeles]: Ne sutor ultra crepˇıdam

c++/rsb 37

& %

' $

Fun¸c˜oes Virtuais

RESPEITO `A ENCAPSULAC¸ ˜AO ...

class Hora { int h, m, s; public:

Hora(int hr, int min, int sec) { ... }

void display(){cout << h << ’:’ << m << ’:’ << s;} }

class HoraLocal : public Hora { String local;

public:

HoraLocal(int h,int m,int s,String local):Hora(h,m,s){ this.local = local;

}

void display(){Hora::display();cout<< ’ ’ << local; } }

' $

Fun¸c˜oes Virtuais

CLASSES ABSTRATAS

• Uma classe abstrata ´e uma que especifica uma ou mais fun¸c˜oes virtuais puras

• Fun¸c˜ao virtual pura n˜ao tem corpo

Exemplo: virtual void display( ) = 0;

• Fun¸c˜oes virtuais puras devem ser definidas por alguma subclasse da classe abstrata

• Subclasses que n˜ao definem as fun¸c˜oes virtuais nulas herdadas tamb´em s˜ao abstratas

(11)

FUNC¸ ˜AO VIRTUAL PURA

•Time ´e uma classe abstrata

class Time {

int hours, minutes, seconds; public:

Time(int hr, int min, int sec) {

hours = hr; minutes = min; seconds = sec; }

void displayTime() {

cout << hours << ’:’ << minutes << ’:’ << seconds; }

virtual void display() = 0;

};

enum timezone { gmt, est, cst, mst, pst };

char *TZ[] = { "GMT", "EST", "CST","MST", "PST" };

c++/rsb 40

& %

FUNC¸ ˜AO VIRTUAL PURA...

class TimeZone : public Time { timezone zone;

public:

TimeZone(int h,int m,int s,timezone z):Time(h,m,s) { zone = z; } void display(); }; void TimeZone::display() { displayTime(); cout << ’ ’ << TZ [zone]; } c++/rsb 41 & % ' $

Fun¸c˜oes Virtuais

FUNC¸ ˜AO VIRTUAL PURA...

int main() { TimeZone dt(21, 42, 12, pst); Time& tp = dt; tp.display(); cout << ’\n’; dt.display(); return 0; } SAIDA: 21:42:12 PST 21:42:12 PST ' $

Fun¸c˜oes Virtuais

FUNC¸ ˜OES VIRTUAIS E DERIVADAS M ´ULTIPLAS

class Date {// classe abstrata protected:

int mo, da, yr; public:

Date(int m, int d, int y){mo = m; da = d; yr = y;} virtual void display() = 0;

};

class NumDate : public Date { public:

(12)

' $

Fun¸c˜oes Virtuais

FUNC¸ ˜OES VIRTUAIS E DERIVADAS M ´ULTIPLAS...

class AlphaDate : public Date { public:

AlphaDate(int m, int d, int y) : Date(m,d,y) { ... } void display();

};

void AlphaDate::display() { static char *mos[] = {

"Janeiro","Fevereiro","Marco","Abril", "Maio","Junho", "Julho","Agosto", "Setembro","Outubro","Novembro", "Dezembro"

};

cout << mos[Date::mo-1] << ’ ’ << da << ", " << yr+1900; }

c++/rsb 44

& %

' $

Fun¸c˜oes Virtuais

FUNC¸ ˜OES VIRTUAIS E DERIVADAS M ´ULTIPLAS...

int main() { NumDate nd(7,29,41); AlphaDate ad(11,17,41); Date& dt1 = nd; Date& dt2 = ad; dt1.display(); cout << ’\n’; dt2.display(); } SAIDA: 7/29/41 Novembro 17, 1941 c++/rsb 45 & % ' $

Fun¸c˜oes Virtuais

CLASSES DE UMA EMPRESA

class OrgEntity { char name[25]; int employee_count; public:

OrgEntity(char *s,int ec) {

strcpy(name,s); employee_count=ec; }

int number_employees() { return employee_count; }

char *org_name() { return name; } virtual int office_party() = 0; };

' $

Fun¸c˜oes Virtuais

CLASSES DE UMA EMPRESA ...

class Company : public OrgEntity { public:

Company(char *s,int ec) : OrgEntity(s,ec){ } virtual int office_party() {

return 100; }

(13)

CLASSES DE UMA EMPRESA

class Division : public Company { public:

Division(char *s,int ec) : Company(s,ec) { } virtual int office_party() {

return 75; }

};

c++/rsb 48

& %

CLASSES DE UMA EMPRESA ...

class Department : public Division { public:

Department(char *s, int ec): Division(s, ec) { } virtual int office_party() {

return 50; } }; c++/rsb 49 & % ' $

Fun¸c˜oes Virtuais

PROGRAMA DE ORC¸ AMENTO

void budget(OrgEntity& oe); int main() {

Company company("Bilbo Software, Inc.", 35); Division div("Aplicacoes Verticais", 12); Department dept("Departamento Medico", 4); // Polimorfismo budget(company); budget(div); budget(dept); } ' $

Fun¸c˜oes Virtuais

PROGRAMA DE ORC¸ AMENTO...

void budget(OrgEntity& oe){

cout << "\n--- Relatorio de Orcamento --\n"; cout << oe.org_name();

cout << " $" << oe.number_employees() * oe.office_party(); cout << ’\n’;

} SAIDA:

(14)

' $

FUNC¸ ˜AO DESTRUIDORA

& %

' $

Fun¸c˜ao Destruidora

FUNC¸ ˜OES DESTRUIDORAS DA BASE E DERIVADA

• Quando um objeto de uma classe derivada sai do escopo de

execu¸c˜ao, a fun¸c˜ao destruidora da classe derivada ´e executada e, em seguida, a fun¸c˜ao destruidora para a classe base ´e executada

• No caso de delete p, onde p ´e ponteiro para a classe base, a

destruidora da base ser´a executada, mesmo se p aponta para objeto da classe derivada

• Quando a fun¸c˜ao destruidora for virtual, todas as destruidoras abaixo dela na hierarquia s˜ao virtuais, e o compilador chama a destruidora correta

• Fun¸c˜oes construtoras n˜ao podem ser virtuais

c++/rsb 53

& %

' $

Fun¸c˜ao Destruidora

CHAMANDO DESTRUIDORA DA BASE

class Company { char *name; public:

Company(char *s){

name = new char[strlen(s+1)]; strcpy(name, s);

}

~Company( ) {

cout << "Destruidor C"; delete name; }

void printOrgName() { cout << name; } };

' $

Fun¸c˜ao Destruidora

CHAMANDO DESTRUIDORA DA BASE ...

class Division : public Company { char *manager;

public:

(15)

CHAMANDO DESTRUIDORA DA BASE...

int main(){

Company *companies[3];

companies[0] = new Company("Casa de Software SJT");

companies[1] = new Division("Pequenos Sistemas", "Carolina"); companies[2] = new Division("Grandes Sistemas", "Patricia"); ... // processa os objetos da companhia

for (int i = 0; i < 3; i++) {

delete companies[i]; // nem sempre a destruidora correta } return 0; } SAIDA: Destruidor C Destruidor C Destruidor C c++/rsb 56 & % DESTRUIDORA VIRTUAL class Company { char *name; public: Company(char *s){

name = new char[strlen(s+1)]; strcpy(name, s); }

virtual ~Company( ) {

cout << "Destruidor C";delete name; }

void printOrgName() { cout << name; } }; c++/rsb 57 & % ' $ Fun¸c˜ao Destruidora DESTRUIDORA VIRTUAL

class Division : public Company { char *manager;

public:

Division(char *s, char *mgr) : Company(s){

manager=new char[strlen(mgr+1)];strcpy(manager, mgr); } ~Division(){ cout<<"Destruidor D"; delete manager; } }; ' $ Fun¸c˜ao Destruidora DESTRUIDORA VIRTUAL int main(){ Company *companies[3];

companies[0] = new Company("Casa de Software SJT");

companies[1] = new Division("Pequenos Sistemas", "Carolina"); companies[2] = new Division("Grandes Sistemas", "Patricia"); ...

(16)

' $ HERANC¸ A M ´ULTIPLA & % ' $ Heran¸ca M´ultipla HERANC¸ A M ´ULTIPLA

• Heran¸ca m´ultipla ´e a capacidade de uma classe derivada ter mais de uma classe base

• Uma derivada de duas bases:

class FileStamp:public Time, public Date{ ...

};

• A construtora de uma classe derivada de bases m´ultiplas deve especificar os argumentos para as fun¸c˜oes construtoras de todas as classes base

FileStamp(char * f,int m,int d,int y,int hr,int mn,int sc) : Time(hr, mn, sc), Date(m, d, y){ ... } • As construtoras s˜ao executadas na ordem especificada

c++/rsb 61

& %

' $

Heran¸ca M´ultipla

USANDO HERANC¸ A M ´ULTIPLA

class Time {

int hours, minutes, seconds; public:

Time(int h, int m, int s) {

hours = h; minutes = m; seconds = s; }

virtual void display() {

cout << hours << ’:’ << minutes << ’:’ << seconds; }

};

' $

Heran¸ca M´ultipla

USANDO HERANC¸ A M ´ULTIPLA

class Date {

int month, day, year; public:

Date(int m, int d, int y){

month = m; day = d; year = y; }

virtual void display(){

cout << month << ’/’ <<day << ’/’ <<year; }

(17)

USANDO HERANC¸ A M ´ULTIPLA...

class FileStamp1 : public Time, public Date { char filename[15];

public:

FileStamp1(char *fn,int m,int d,int y,int h,int min,int s) :Time(h,min,s),Date(m, d, y){strcpy(filename,fn);} void display(); }; void FileStamp1::display(){ cout << filename << ’ ’; Date::display(); cout << ’ ’; Time::display(); } c++/rsb 64 & %

USANDO HERANC¸ A M ´ULTIPLA...

int main(){ FileStamp1 fs("DADOS",4,6,90,13,32,27); fs.display(); } SAIDA: DADOS 4/66/90 13:32:27 c++/rsb 65 & % ' $ Heran¸ca M´ultipla

AMBIGUIDADES COM HERANC¸ A M ´ULTIPLA

class FileStamp2 : public Time, public Date { char filename[15];

public:

FileStamp(char *fn,int m,int d,int y,int h,int min,int s) :Time(h,min,s),Date(m, d, y){strcpy(filename,fn);} }; int main(){ FileStamp2 fs("DADOS",4,6,90,13,32,27); fs.display(); // Erro fs.Time::display(); // OK fs.Date::display(); // OK } ' $ Heran¸ca M´ultipla

A COMPLEXIDADE DE HERANC¸ A M ´ULTIPLA

class A {public: int x;}

class B {public: virtual int h( ){ ... } int x, y; } class C: public A, public B {

public:

(18)

' $

Heran¸ca M´ultipla

A COMPLEXIDADE DE HERANC¸ A M ´ULTIPLA...

c++/rsb 68

& %

' $

Heran¸ca M´ultipla

A COMPLEXIDADE DE HERANC¸ A M ´ULTIPLA...

c++/rsb 69

& %

' $

Heran¸ca M´ultipla

A COMPLEXIDADE DE HERANC¸ A M ´ULTIPLA...

' $

Heran¸ca M´ultipla

(19)

A COMPLEXIDADE DE HERANC¸ A M ´ULTIPLA...

c++/rsb 72

& %

A COMPLEXIDADE DE HERANC¸ A M ´ULTIPLA...

c++/rsb 73

& %

' $

CLASSES BASE VIRTUAIS

' $

Classes Base Virtuais

CLASSES BASE VIRTUAIS

• Com heran¸ca m´ultipla, uma classe derivada pode ter mais de uma ocorrˆencia de uma das bases

• Observe a ambig¨uidade de referˆencia a x em D: class A { ... int x; ... }

class B : public A { ... x ... } class C : public A { ... x ... }

class D : public B, public C { ... x(?) ... }

• Solu¸c˜ao: classe base A deve ser declarada virtual: class A { ... int x; ... }

class B : public virtual A { ... x ... } class C : public virtual A { ... x ... } class D : public B, public C { ... x ... }

(20)

' $

Classes Base Virtuais

BASE VIRTUAL I

class A {public: int x;}; class B: public virtual A { }; class C: public virtual A { }; class D: public B, public C { public:

D() {x = 1000;}; // OK };

int main(int argc, char *argv[]){ D d; printf("x = %d\n", d.x); } Sa´ıda: x = 1000 c++/rsb 76 & % ' $

Classes Base Virtuais

BASE VIRTUAL II

class A {public: int x;}; class B: public virtual A { }; class C: public A { }; class D: public B, public C { public:

D() {x = 1000;}; // ERRO: AMB´IGUO };

int main(int argc, char *argv[]){ D d; printf("x = %d\n", d.x); } c++/rsb 77 & % ' $

Classes Base Virtuais

BASE VIRTUAL III

class A {public: int x;}; class B: public A { }; class C: public A { }; class D: public B, public C { public:

D() {x = 1000;}; // ERRO: AMB´IGUO };

int main(int argc, char *argv[]){ D d;

printf("x = %d\n", d.x); }

' $

Classes Base Virtuais

BASE VIRTUAL IV

class A {public: int x;}; class B: public virtual A{ }; class C: public virtual A{ };

class D: public virtual B, public virtual C, public virtual A{ public: D(){ A::x = 10;

B::x = 11; C::x = 13; x = 13;

} };

int main(int argc, char *argv[]){ D d;

printf("d.A::x=%d,d.B::x=%d,d.C::x=%d,d.D::x = %d\n", d.A::x,d.B::x,d.C::x,d.D::x);

(21)

BASE VIRTUAL V

class A {public: int x;}; class B: public virtual A{ }; class C: public virtual A{ };

class D: public virtual B, public virtual C, public A{ public: D(){ A::x = 10; // ERRO: A ´e base amb´ıgua

B::x = 11; C::x = 13;

x = 13; // ERRO: refer^encia amb´ıgua }

};

int main(int argc, char *argv[]){ D d; printf("d.A::x=%d,d.B::x=%d,d.C::x=%d,d.D::x = %d\n", d.A::x,d.B::x,d.C::x,d.D::x); } // c++/rsb 80 & % BASE VIRTUAL VI

class A {public: int x;}; class B: public virtual A{ }; class C: public virtual A{ };

class D: public B, public C, public virtual A{ public: D(){ A::x = 10;

B::x = 11; C::x = 13; x = 13;

} };

int main(int argc, char *argv[]){ D d;

printf("d.A::x=%d,d.B::x=%d,d.C::x=%d,d.D::x = %d\n", d.A::x,d.B::x,d.C::x,d.D::x);

} // Sa´ıda: d.A:x=13, d.B::x=13, d.C::x=13, d.D::x = 13

c++/rsb 81

& %

' $

Classes Base Virtuais

BASE VIRTUAL VII

class A {public: int x;}; class B: public virtual A{ }; class C: public A{ };

class D: public B, public C, public virtual A{ public: D(){ A::x = 10; // ERRO: A ´e base amb´ıgua

B::x = 11; C::x = 13;

x = 13; // ERRO: refer^encia amb´ıgua }

};

int main(int argc, char *argv[]){ D d;

printf("d.A::x=%d,d.B::x=%d,d.C::x=%d,d.D::x = %d\n", d.A::x,d.B::x,d.C::x,d.D::x);

}

' $

Classes Base Virtuais

USO DE BASE VIRTUAL

struct Item{

char name[25]; int cost; };

class Product : public virtual Item { int qty_sold;

public:

Product(char *nm, int qty, int cst){

qty_sold = qty; strcpy(name, nm); cost = cst; }

(22)

' $

Classes Base Virtuais

USO DE BASE VIRTUAL...

class Service : public virtual Item { int manhours;

public:

Service(char *nm, int mh, int cst){

manhours = mh; strcpy(name, nm); cost = cst; }

virtual void display(){cout << manhours;} };

class Installation : public Product, public Service { public:

Installation(char *nm, int qty, int hrs, int cst) : Product(nm, qty, cst), Service(nm, hrs, cst) { } void display();

};

c++/rsb 84

& %

' $

Classes Base Virtuais

USO DE BASE VIRTUAL...

void Installation::display(){

cout << "\nInstalados "; Product::display(); cout << ’ ’ << name << "es" << "\nTempo: "; Service::display();

cout << " horas"; << "\nCusto: $" << cost; } int main(){ Installation inst("refrigeradores", 2,3,75); inst.display(); return 0; }

SAIDA: Instalados 2 refrigeradores Tempo: 3 horas Custo: $75 c++/rsb 85 & % ' $ COMPILAC¸ ˜AO DE CLASSES ' $ COMPILAC¸ ˜AO DE CLASSES

IMPLEMENTAC˜AO DE MEMBROS FUNC¸ ˜OES

• Membros Fun¸c˜oes N˜ao-Virtuais

–referˆencias `as fun¸c˜oes resolvidas em tempo de compila¸c˜ao –n˜ao podem ser alterados

–n˜ao fazem parte do leiaute dos objetos, portanto na inicializa¸c˜ao de estruturas devem ser ignorados

• Membros Fun¸c˜oes Virtuais

–para cada classe ´e criada uma tabela de fun¸c˜oes virtuais (VMT) –todo objeto passa a ter o endere¸co da VMT da classe

–referˆencias `as fun¸c˜oes resolvidas em tempo de execu¸c˜ao, via VMT –n˜ao podem ser alterados

(23)

HERANC¸ A SIMPLES E FUNC¸ ˜OES VIRTUAIS

class A {

public: int a;

virtual void f (int); virtual void g (int); virtual void h (int); };

class B : public A {

public: int b; virtual void g (int); };

class C : public B {

public: int c; virtual void h (int); };

c++/rsb 88

& %

LEIAUTE DOS OBJETOS

+---+ | int a | vtbl: | vptr --+--->+---+ | int b | | &A::f | | int c | | &B::g | +---+ | &C::h | +---+ C* pc = new C; pc -> g(2); ---> (*(pc->vptr[1]))(pc,2); c++/rsb 89 & % ' $ COMPILAC¸ ˜AO DE CLASSES

HERANC¸ A M ´ULTIPLA E FUNC¸ ˜OES VIRTUAIS

class A {

public: virtual void f ( ){..}; } class B : { public: virtual void f ( ){ ... g(); ...}; virtual void g ( ){ ... }; }; this+deltaB class C : public A, public B { |

public: virtual void f ( ){ ... g(); ...}; };

' $

(24)

' $

Verifica¸c˜ao de Tipos Dinˆamicos

dynamic cast

• A fun¸c˜ao dynamic cast<T*>(p) verifica o tipo do objeto apontado por p e retorna:

–um ponteiro do tipo T*, se tipo dinˆamico de p for T* ou ponteiro para um tipo que tem T como base ´unica

–um ponteiro do tipo T*, se o tipo est´atico de p for T* ou D*, onde

T ´e uma base da classe D. Neste caso, o uso de dynamic cast n˜ao ´e necess´ario, pois o compilador pode determinar a validade da convers˜ao

–0, se nenhum dos casos anteriores se aplica ou se p==0

• O prop´osito do dynamic cast ´e cuidar da convers˜ao em situa¸c˜oes em que o compilador n˜ao tem meios de fazˆe-la

•dynamic cast n˜ao permite viola¸c˜ao acidental de prote¸c˜ao de base privada ou protegida

c++/rsb 92

& %

' $

Verifica¸c˜ao de Tipos Dinˆamicos

dynamic cast ...

class A { ... } class B { ... }

class C: public A, protected B { ... }; class D: public C { ... };

void f(C* p) {

A* q = p; // OK

A* r = dynamic_cast<A*>(p); // OK, mas desnecess´ario B* t = p; // Erro: B ´e base protegida B* u = dynamic_cast<B*>(p) // ok, mas faz u = 0

D* z = dynamic_cast<D*>(p) // ok, se p apontar para objeto // do tipo D, sen~ao faz z = 0 }

c++/rsb 93

& %

' $

Verifica¸c˜ao de Tipos Dinˆamicos

Referências

Documentos relacionados

• Uma declara¸ c˜ ao de classe pode conter membros privados ( private ), protegidos ( protected ) e p´ ublicos ( public ). • private : membros declarados como privados somente s˜

Neste contexto, está à agricultura orgânica, que é um sistema de produção alternativo seguro e sustentável, baseado na interação dinâmica entre o solo, as plantas,

A RCJS desenvolve ações que visam aproximar EES e comunidades/instituições ligadas à Igreja Evangélica de Confissão Luterana no Brasil (IECLB) e a escolas da

Conjunto da Empilhadeira com Resfriamento que inclui Admissão Superior de Ar com Pré-filtro, Invólucro de Exaustão, Sistema de Proteção do Trem de Força com Paralisação do

Nos outros lados as forzas da carga situada en A e a do outro vértice sem- pre sumarían e tampouco se anularían.. C.1.- Un condutor macizo en forma de esfera recibe unha

O sistema desenvolvido mostrou ser uma ferramenta importante para usuários de imagens NOAA, especialmente os que necessitam de uma grande série temporal com alta precisão

A partir deste resultado, a empresa então teve condições de analisar as causas do problema e partir para melhorias buscando sua solução, além de tomar a decisão

3 - Poderão se inscrever no presente processo seletivo todos docentes que queiram concorrer a ter contrato celebrado com a rede estadual de educação a partir de 2021,