A maior rede de estudos do Brasil

Grátis
169 pág.
Apostila - Programa--o C++

Pré-visualização | Página 43 de 50

é quando esta foi usada como classe-base para 
mais de uma clase derivada e dessas classes derivadas foi derivada outra por meio de herança 
múltipla. Uma classe-base não pode ser usada mais de uma vez numa mesma classe derivada. 
Entretanto, uma classe-base pode ser indiretamente usada mais de uma vez em classes derivadas. 
Observe a classe Super do exemplo abaixo: 
 
#include <iostream> 
using namespace std; 
 
class Base { 
 protected: int valor; 
 public: Base(int n = 0) {valor = n;} 
 virtual void Print() { cout << "\nValor : " << 
valor; } 
}; 
class Deriv1 : virtual public Base { 
public: Deriv1(int n = 0) : Base(n) { } 
Curso de Linguagem Computacional C/C++ 
________________________________________________________________________________________________ 
Sistemas Industriais Inteligentes – DAS – CTC – UFSC 135 
}; 
class Deriv2 : virtual public Base { 
public: Deriv2(int n = 0) : Base(n) { } 
}; 
class Super : public Deriv1, public Deriv2 
{ 
 public: 
 Super(int n = 0) : Base(n) { } 
 int RetValor() { return valor; } 
 void Print() { cout << "\nValor do Super-Objeto : " << valor; } 
}; 
int main(int argc, char* argv[]) 
{ 
 Base B(5); 
 Deriv1 D1(10); 
 Super S(343); 
 B.Print(); 
 D1.Print(); 
 S.Print(); 
 
 return 0; 
} 
Neste caso, cada objeto da class Super poderia ter dois sub-objetos da classe Base. Se um 
objeto da classe Super tentasse acessar dados ou funções da classe Base, ocorreria um erro de 
ambiguidade. A declaração virtual nas classes Deriv1 e Deriv2 faz com que estas classes 
compartilhem uma única classe-base. A classe Super só terá um subobjeto da classe Base e não terá 
mais nenhum problema de ambigüidade. 
Os construtores de classes-base são sempre executados antes do construtor da classe 
derivada. Os construtores de classes-base virtuais são chamados antes de qualquer construtor de 
classes-bases não-virtuais. 
17.4 Funções Amigas 
O conceito de isolamento interno dos itens de uma classe, onde funções não-membros não 
teriam o privilégio de acesso aos dados privados ou protegidos desta classe, é violado por um 
mecanismo oferecido por C++ que permite que funções não-membro, às quais foi dada uma 
permissão especial, tenham acesso à parte interna da classe. Declarando uma função como amiga, 
ela tem os mesmos privilégios de uma função-membro, mas não está associada a um objeto da 
classe. No programa abaixo apresentamos a sintaxe das funções amigas: 
 
// Uso de funcoes amigas 
#include <iostream> 
#include <strstrea> 
using namespace std; 
 
class Data; // Declara que existe esta classe 
 
class Tempo 
{ 
private: 
 long h, min, s; 
public: 
 Tempo(long hh = 0, long mm = 0, long ss = 0) 
 { h = hh; min = mm; s = ss; } 
Curso de Linguagem Computacional C/C++ 
________________________________________________________________________________________________ 
Sistemas Industriais Inteligentes – DAS – CTC – UFSC 136 
 friend char * PrintTime( Tempo &, Data &); 
}; 
class Data 
{ 
private: 
 int d, m, a; 
public: 
 Data(int dd = 0, int mm = 0, int aa = 0) 
 { d = dd; m = mm; a = aa; } 
 friend char * PrintTime( Tempo &, Data &); 
}; 
char * PrintTime( Tempo & Tm, Data & Dt) // Função global e amiga 
{ 
 char * temp = new char[50]; 
 memset(temp, '\0', 50); 
 strstream sIO(temp, 50, ios::out); 
 sIO << "\n Relogio-> \t" << Tm.h << ":" << Tm.min << ":" << Tm.s; 
 sIO << "\n Data-> \t" << Dt.d << "/" << Dt.m << "/" << Dt.a; 
 return temp; 
} 
int main(int argc, char* argv[]) 
{ 
 Tempo Tm( 15, 56, 4); 
 Data Dt( 9, 5, 2000); 
 char * str = PrintTime( Tm, Dt); 
 cout << "\n" << str; 
 delete str; 
 
 return 0; 
} 
Neste exemplo, queremos que a função PrintTime() tenha acesso aos dados privados da 
classe Tempo e Data. Desta forma, usamos a palavra-chave friend na declaração da função 
friend char * PrintTime( Tempo &, Data &); 
 
Esta declaração pode ser colocada em qualquer posição da classe. Não há diferença se for 
colocada na parte pública ou na parte privada da classe. Um objeto Tempo é passado como 
argumento à função PrintTime(). Este argumento é necessário pois, mesmo quando se dá a uma 
função amiga o privilégio de acesso aos dados privados da classe, ela não é parte daquela classe, 
devendo ser informada sobre qual objeto agirá. 
A função PrintTime() cria um objeto da classe strstream. Este objeto atua como se 
fosse um objeto cout, entretanto em vez de enviar os dados para a saída padrão (tela), ele 
armazena estes dados no buffer de caracteres fornecidos ao seu construtor. Esta é uma das formas 
mais fáceis para converter dados de uma classe para texto (ASCII) e armazenar estes dados em um 
buffer de caracteres. Note que operamos sob o objeto criado assim como operamos com o objeto 
cout. O mesmo princípio pode ser empregado para a leitura de dados armazenados em um buffer 
de caracteres, operando-se como se estivéssemo utilizando o operador cin. 
Funções amigas são muito empregadas quando sobrecarregamos os operadores << e >> 
associados aos objetos cout e cin respectivamente. Desta forma definimos o operador << para 
imprimir os dados da classe e o operador >> para adquirir os dados da classe. Como, muitas vezes 
desejamos que estes operadores tenham acesso aos membros privados da classe, então devemos 
defini-los como funções amigas. 
friend ostream & operator <<(ostream & OS, Tempo const & T); 
Curso de Linguagem Computacional C/C++ 
________________________________________________________________________________________________ 
Sistemas Industriais Inteligentes – DAS – CTC – UFSC 137 
friend istream & operator >>(istream & IS, Tempo & T; 
 
Todo e qualquer operador que queremos sobrecarregar como sendo uma função global (i.e., 
recebe um parâmetro se for unário e dois se for binário) e queremos permitir que este operador 
tenha acesso a membros privados e protegidos de uma dada classe, devemos definir este operador 
como sendo uma função amiga. 
No nosso programa exemplo acima, definimos que a função PrintTime()é amiga das 
classes Data e Tempo. Para tal, precisamos declarar nas duas classes que esta função é amiga da 
classe. Quando declaramos a função na classe Tempo, estaremos declarando uma função que 
recebe como parâmetro um objeto da classe Data desconhecida até então pelo compilador. Para 
evitar que o compilador gere um erro indicando que a classe não existe, devemos declarar no início 
do arquivo que existe a classe Data, e que esta será definida posteriormente. Fazemos isto através 
da instrução: 
 class Data; 
17.5 Classes Amigas 
Além de ser possível declarar funções independentes como amigas, podemos declarar uma 
classe toda como amiga de outra. Neste caso, as funções-membro da classe serão todas amigas da 
outra classe. A diferença é que estas funções-membro têm também acesso à parte privada ou 
protegida da sua própria classe. 
Para modificar o programa anterior e declarar que a classe Data é amiga da classe Tempo, 
basta retirarmos a declaração da função amiga PrintTime() da classe Tempo e adicionarmos a 
declaração: 
 friend class Data; 
 
Agora, se definirmos que a funçao PrintTime() passa a ser uma função da classe Data, 
ela automaticamente passará a ser amiga da classe Tempo e terá acesso a todos os membros desta 
classe. 
Uma função ou classe amiga deve ser declarada como tal dentro da classe em que os dados 
serão acessados. Em outras palavras, quem escreve uma classe deve especificar quais funções ou 
classes irão acessar a sua parte privada ou protegida. Desta forma, um programador que não tem 
acesso ao código-fonte da classe não poderá criar uma função amiga para esta classe. As funções 
amigas devem ser declaradas pelo autor da classe. Observe que a palavra chave friend oferece 
acesso em uma só direção. Se a classe A é amiga da classe B, o inverso não é verdadeiro. 
Uma função operadora amiga deve receber no mínimo um argumento objeto. Em outras 
palavras, você não pode criar uma função operadora binária como operator +() que receba