Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Declaração de Classes
⇒ Visibilidade de Membros de Classes
⇒ Enumerações
⇒ Referências
⇒ Funções inline
⇒ Passagem de parâmetros para funções
⇒ Classes e Objetos
⇒ Operadores de dados
⇒ Utilização do especificador const
⇒ Objetos como membros de dados de uma classe
⇒ Operador de inicialização de membro
⇒ Estruturas e classes (observações)
⇒ Sobrecarga de funções
⇒ Funções membro que retornam um objeto
⇒ Membros de dados private static
⇒ Objetos criados dinamicamente
⇒ Herança
⇒ Herança pública e privada
⇒ Reescrevendo funções-membro da classe base
⇒ Classe Abstratas
⇒ Níveis de Herança
⇒ Herança múltipla
⇒ Ponteiros
⇒ Alocação dinâmica em C/C++
⇒ Sobrecarga de operadores
⇒ Operadores unários sobrecarregados pré e pós fixados
⇒ Conversões
⇒ Listas encadeadas
⇒ Ponteiros para funções
⇒ Gravando uma linha por vez no arquivo de saída
⇒ Lendo uma linha por vez do arquivo de entrada
⇒ Identificando o fim de arquivo (eof)
⇒ A função open()
⇒ Lendo um caracter por vez do arquivo de entrada
⇒ Gravando um caracter por vez no arquivo de saída
⇒ Exemplo de operações com arquivos em C++
⇒ Gravando objetos
⇒ Lendo objetos
⇒ Os métodos seekp(), seekg(), tellp() e tellg()
Declaração de Classes
c) As estruturas em C++ podem ter membros de dados e de função; seus membros são
public por default.
d) As uniões em C++ podem ter membros de dados e de função; seus membros são
públicos por default; todos os mebros de uma união ocupam a mesma posição de
memória.
f) Uma instância de estrutura ou união é dita uma variável; uma instância de classe é
dita um objeto. Ou seja, um objeto é uma variável do tipo classe.
Enumerações
c) exemplo:
enum CORES { AZUL=1,VERDE=2,CINZA=31};
cor = VERDE ; // ok
cor = 1 ;// errado - cor é do tipo CORES e 1 é do tipo inteiro
cor=(CORES)1;// foi necessário utilizar o operador de molde
Referências
c) A função chamada não cria cópias locais dos argumentos recebidos; logo, qualquer
alteração nestes será refletida na funçoão chamadora.
Exemplo:
int x;
int &xref = x; // cria referência para x; &x = &x1
Funções inline
b) As funções inline são tratatadas com macros, o que pode aumentar a velocidade de
execução.
c) Esta sugestão (ver item a) pode ser aceita ou não, baseado em critérios que variam de
um compilador para outro (usualmente apenas funções pequenas) .
Passagem de parâmetros para funções
a) A passagem de parâmetros para fun'ções pode ser feita por valor, por referência ou
por ponteiro.
b) Na chamada por valor, a função chamada cria uma cópia local do argumento passado
pela função chamadora.
c) Na chamada por referência, a função chamada não fria uma nova variável, mas
apenas uma referência (ALIAS) do parâmetro fornecido. Quaisquer alterações de
valor nesta referência serão refletidas na função chamadora, a menos que o
especificador CONST seja incluído no protótipo da função. Por exemplo:
void main()
{
int MyVariable=10;
MyFunction_ByPtr(&MyVariable);
}
Classes e Objetos
a) Os membros declarados na seção private são encapsulados. Estes membros(de dados
ou de função) só podem ser acessados por funções mebros da mesma classe.
ClassName.FunctionName();
[ClassName]::[ClassName]()
l) Função destrutora ou destrutor: função que tem o memso nome da classe (precedido
por um ~) chamada automaticamente quando o objeto é destruído (liberado da
memória).
m) A função destrutora não retorna nenhum tipo de valor e não pode receber
argumentos.
[ClassName]::~[ClassName]()
Sumário de termos relacionados
Função de acesso – método public utilizado para ler ou alterar membros de dados private.
Operadores de Dados
a) para declarar funções-membro que não podem modificar o valor dos membros de
dados da classe, apenas acessá-los.
b) para impedir que os valor dos membros de dados sejam alterados após a inicialização,
que deve ser feita obrigatóriamente na função construtora da classe. Neste caso, todos
os métodos da classe devem ser declarados como constantes, conforme sintaxe
exibida em (a).
c) para impedir que o valor de uma variável seja modificado após sua inicialização, que
deve ser feita obrigatoriamente na declaração da variável.
class Date
{
private:
int day, month;
public:
int year;
Date(int,int,int);
int PrintDay();
int PrintMonth();
int ChangeBirthday(int,int,int);
~Date();
};
class President
{
private:
FirstName[20], LastName[20];
public:
President(char [ ],char [ ], int, int, int);
~President();
Date Birthday;
}
b) Vemos que Birthday é uma instância da classe Date, e que está definida como um
membro de dados da classe President.
a) Em C++ é possível declarar duas ou mais funções com o mesmo nome. Estas funções
(além da primeira) são ditas sobrecarregadas.
class Venda
{
private:
int npecas;
float preco;
public:
Venda();// construtor
Venda AddVenda(Venda);
void PrintVenda();
~Venda() { } ;// função destrutora (inline)
};
Venda Venda::AddVenda(Venda A)
{
Venda Temp;
return Temp;
}
f) Este resultado (um objeto da classe Venda) é atribuído ao objeto Temp, declarado no
bloco principal do programa.
a) Quando um membro de dados é declarado como static, ele é compartilhado por todos
os objetos pertencentes à classe.
a) Objetos são criados dinâmicamente por meio do operador new (semelhante à malloc()
na linguagem C), que retorna um ponteiro para o endereço do objeto.
b) O espaço em memória ocupado pelo objeto é liberado por meio da instrução delete.
d) Quando o ponteiro para o objeto é criado por meio da instrução new, a função
construtora é executada.
e) Quando o ponteiro para o objeto é destruído por meio da instrução delete, a função
destrutora é executada.
Herança
Herança pública (ou derivação pública) Class Agente: public Policia todos os
membros public da classe base (Policia) são membros public da classe derivada
(Agente) e todos os membros protected da classe base são protected da classe
derivada. Ou seja, a visibilidade dos membros da classe base é mantida na classe
derivada.
a) Quando é necessário adicionar instruções a uma função de uma classe base pré-
compilada (da qual não dispomos do código-fonte), podemos definir uma função de
mesmo nome na classe derivada. Assim, uma chamada a função será feita de modo
único por um objeto da classe derivada.
void print()
{
Base::print();
}
Classes Abstratas
Classes abstratas são utilizadas apenas para derivar outras classes, ou seja, nenhuma
instância destas classe (objeto) é declarada (ver classe Conta no diretório heritage1).
Níveis de Herança
Uma classe derivada pode ser subclasse de outra classe derivada. Podemos ter múltiplos
níveis de hierarquia (ver classe ContaPremio no diretório heritage1).
Herança múltipla
b) Sintaxe de declaração:
- int *px, y;
- px = &x ; (atribuição)
- y = *px; (operação indireta)
- cout << &px ; (retorna endereço do ponteiro)
- n = py - px ; (diferença = (&y - &x)/(nº de bytes do tipo apontado))
- Operador delete: libera a memória previamente alocada por new. Delete recebe como
argumento o ponteiro retornado por null.
Alocação Dinâmica em C/C++
a) Considere a instrução em C
struct MY_STRUCT S;
c) Esta instrução aloca a memória necessária e retorna um ponteiro genérico void. Este
tipo de ponteiro não pode ser diretamente acessado, sendo necessário utilizar o
operador de molde (struct MY_STRUCT *) para convertê-lo para pobteiro para
MY_STRUCT. (obs: o operador sizeof retorna o tamanho do operando em bytes).
d) Em C++, a alocação dinâmica de memória é feita com o operador new, que considera
o tipo deponteiro a ser retornado, dispensado a utilzação do operador de molde.
S = new MY_STRUCT;
f) O operador new, ao alocar memória para um objeto, faz com que sua função
construtora seja automaticamente executada. Logo, é possível passar parâmetros para
o construtor na própria instrução de alocação dinâmica de memória:
MyClass *Obj;
i) Obviamente, é possível alocar dinamicamente não apenas objetos, mas também tipos
de variáveis pré-definidos na linguagem. Considere as instruções a seguir:
int *ptr;
ptr = new int;
int *intNotas;
int intSize = 10;
float media=0;
.....
delete [] intNotas;
public:
MFC(char*);// construtor
void vdPutData();// função de acesso
void vdUpDateMyString(char*);
~MFC();// destrutor };
MFC::MFC(char *string)
{ int l=strlen(string);
strcpy(strMyStringPtr,string); }
void MFC::vdPutData()
{ cout << strMyStringPtr << endl;}
strcpy(strMyStringPtr,string); }
MFC::~MFC()
{ // libera a memória alocada pelo operador new
delete [] strMyStringPtr; }
void main()
{
MFC Obj1("Saraiva"),Obj2("Kadesh");
Obj1.vdPutData(); getch();
Obj1.vdUpDateMyString("This one is much longer");
Obj1.vdPutData(); getch();
Obj1 = Obj2 ;
Obj1.vdPutData(); getch();
}
Sobrecarga de operadores
a) Os operadores utilizados com os tipos básicos da linguagem C++ não podem ser
utilizados com os tipos definidos pelo usuário, como classes, estruturas e
enumerações.
b) Sobrecarregar um operador significa redefinir seu símbolo, de modo que possa ser
utilizado com tipos definidos pelo usuário.
f) Os seguintes operadores não podem ser sobrecarregados: operador ponto (.), operador
de resolução de escopo (::) e operador condicional ternário (?:).
g) A palavra reservada operator deve vir logo após o tipo retornado pela função
operadora, em sua declaração.
h) Toda vez que [operador] for aplicado a um objeto da classe da qual a função
operadora acima é membro, ela será chamada.
b) Para identificar um operador como pós-fixado, inserir a palavra chave int entre
parênteses; ela apenas servirá, neste contexto, para permtir ao compilador diferenciar
as funções operadoras pós e pré-fixadas.
Conversões
a) Conversões entre tipos básicos: as conversões entre tipos básicos são feitas de forma
implícita (conversão implícita) ou de forma explícita (conversão explícita) através do
operador de molde.
b) Conversão de um objeto para tipo básico: para realizar a conversão de um objeto para
um tipo básico é necessário sobrecarregar o operador de molde, criando uma função
chamada função conversora. Funções conversoras: retornam um valor para o tipo
desejado; na sua declaração não deve ser inserido o tipo do valor retornado, pois esta
informação está contida no operador de molde sobrecarregado ( conversão de objeto
para tipo básico ).
c) Conversão de um tipo básico para objeto: para realizar a conversão de um tipo básico
para objeto é necessário sobrecarregar o operador de atribuição.
Básico Objeto
Básico Operador de molde ou Sobrecarga do operador de
conversão implícita atribuição
Objeto Função conversora (1) Função conversora
(sobrecarga do operador (2) Construtor para conversão
de molde)
Conversão de objeto tipo básico
Sobrecarga do operador de molde – função conversora
class string
{
private:
char str[20];
public:
string() { str[0]=0; }
string(char s[]) { strcpy(str,s);}
// função conversora – não especificar tipo
operator int();
// função conversora – não especificar tipo
operator float();
~string() {}
};
string::operator int()
{
return atoi(str);
}
string::operator float()
{
return atof(str);
}
void main()
{
getch();
}
Listas Encadeadas
b) Rotina de inserção
- encadeamento da lista
c) Rotina de busca
- percorre a lista
while(atual!=NULL)
{
…….
atual = atual próximo;
}
d) Rotina de exclusão
- percorre a lista
while(atualpróximo!=NULL)
{
if(atualpróximocampo = valor) atualpróximo=atualpróximopróximo;
…….
atual = atual próximo;
}
e) Rotina de exclusão especial para elemento no topo da lista – ver código em anexo
f) Rotina de exclusão especial para elemento no fim da lista – ver códgio em anexo.
Treinamento em linguagem C++
Capítulo 11 - Ponteiros
Listas encadeadas (ou listas ligadas)
#include <iostream.h>
#include <conio.h>
#include <stdlib.h>
struct Livro
{ char nome[40];
int code;
float preco;
Livro *proximo;// ponteiro para Livro };
void Inserir()
{
// aloca memória para novo elemento
Livro *novo = new Livro;
// encadeamento da lista
novo->proximo = (Livro *) head;
head = novo;
}
void Listar()
{
Livro *atual= (Livro *)head;
if(!Empty(atual))
while(atual!=NULL)
{
cout << "Nome : " << atual->nome << endl;
cout << "Codigo: " << atual->code << endl;
cout << "Preco : " << atual->preco << endl <<endl;
atual = atual->proximo;
}
}
if(!Empty(atual))
while(atual->proximo!=NULL)
{
if(atual->proximo->code==code)
{ atual->proximo = atual->proximo->proximo;
return; }
aux = atual;
atual = atual->proximo;
}
if(!Empty(atual))
while(atual!=NULL)
{
if(atual->code==code)
{
cout << "Nome : " << atual->nome << endl;
cout << "Codigo: " << atual->code << endl;
cout << "Preco : " << atual->preco << endl <<endl;
//break; se habilitado, impede listagem de ocorrências múltiplas
//do valor da chave de busca
}
atual = atual->proximo;
}
void main()
{
int op,code;
do
{
cout << "[1] Insere elemento na lista" << endl;
cout << "[2] Remove elemento da lista" << endl;
cout << "[3] Busca elemento na lista" << endl;
cout << "[4] Listar elementos"<< endl;
cout << "[5] Sair do programa" << endl;
cout << "Selecione opcao : ";
cin >> op;
switch(op)
{
case 1: Inserir();break;
case 4: Listar();break;
case 5: exit(0);
}
while(1);
}
Ponteiros para funções
(*ptr)();
#include <fstream.h>
void main()
{
ofstream fout("teste.txt");
#include <fstream.h>
void main()
{
const int MAX=80;
char buff[MAX], fim_de_linha='.';
ifstream fin("teste.txt");
while(fin)
{
fin.getline(buff,MAX,fim_de_linha);
cout << buff;
}
}
a) Objetos da classe IFSTREAM têm um valor que pode ser testado para a verificação
de fim de arquivo (EOF).
b) Qualquer mensagem (chamada de um membro de objeto da classe) retornará o valor
zero em caso de fim de arquivo.
c) Portanto, o laço while acima poderia ser reescrito, de forma mais compacta, como:
A função open()
#include <fstream.h>
void main()
{
ifstream fin;
char ch;
fin.open("teste.txt",ios::in);
#include <fstream.h>
void main()
{
ofstream fout;
char ch=0;
fout.open("teste.txt",ios::out);
while(ch!='.')
{
cin >> ch;
fout.put(ch);
}
}
/*
Treinamento em Linguagem C++
Capitulo 13 - Operacoes com Arquivos
[1] Gravar em um arquivo de saída as linhas de um arquivo de entrada que
satisfaçam o seguinte critério:
a) comecem com vogal
b) tenham uma consoante no quinto caracter
[2] Imprimir o número de cada linha (referente à sua posição no arquivo de entrada).
[3] Exibir o número médio de caracteres/linha do arquivo de entrada.
[4] Exibir a percentagem de linhas do arquivo de entrada que satisfazem a condição [1]
*/
#include <fstream.h>
#include <stdio.h>
#include <iomanip.h>
#include <conio.h>
return(-1);
}
void main()
{
ifstream in; // declara objeto da classe ifstream
ofstream out;// declara objeto da classe ofstream
if((VogalConsoante(buffer[0])==0)&&(VogalConsoante(buffer[4])==1))
{
out << setfill('0') << setw(3) << lin << " - " << buffer << endl;
lin2++;
}
}
cout << endl;
cout << "Numero total de linhas no arquivo de entrada = " << lin << endl;
cout << "Percentagem de linhas que satisfazem a condicao = " << setiosflags(ios::fixed) <<
setprecision(1) << 100*(float)lin2/lin << "%" << endl;
getch();
}
Gravando objetos
#include <fstream.h>
void main()
{
ofstream out(“teste.txt”);
MyClass obj;
…….
out.write((char *)&obj,sizeof(obj));
…….
}
Lendo objetos
#include <fstream.h>
void main()
{
ifstream in(“teste.txt”);
MyClass obj;
…….
while(in.write((char *)&obj,sizeof(obj)))
{
…….
}
}
a) Qualquer arquivo em C++ tem dois valores inteiros a ele associados: o ponteiro de
posição corrente de leitura e o ponteiro de posição corrente de gravação.