Escolar Documentos
Profissional Documentos
Cultura Documentos
Sumário
B.1 Elementos da linguagem B.12 Operadores new e delete
B.2 Tipos de dados B.13 Arrays
B.3 Constantes B.14 Enumerações, estruturas e uniões
B.4 Conversão de tipos B.15 Cadeias
B.5 Declaração de variáveis B.16 Funções
B.6 Operadores B.17 Classes
B.7 Entradas e saídas básicas B.18 Herança
B.8 Sentenças B.19 Sobrecarga de operadores
B.9 Sentenças condicionais: if B.20 Modelos (templates)
B.10 Laços: sentenças repetitivas B.21 Exceções
B.11 Ponteiros B.22 Espaço de nomes (Namespaces)
1
INTRODUÇÃO
C++ é considerado um C maior e mais potente. Neste apêndice, serão mostradas as regras de
A sintaxe de C++ é uma extensão de C, na qual sintaxe do padrão clássico de C++, retiradas do
foram acrescentadas numerosas propriedades, Annotated Reference Manual (ARM), de Strous-
fundamentalmente orientadas a objetos. C ANSI1 trup e Ellis, bem como as últimas propostas in-
já adotou inúmeras características de C++, por corporadas ao novo rascunho de C++ ANSI, que
esse motivo, a emigração de C a C++ não costu- está incluído nas versões 3.0 (atual) e 4.0 (futura)
ma ser difícil. de AT&T C++.
1
Utiliza-se indistintamente os termos ANSI C (nome em inglês) e C ANSI, tradução para o espanhol muito usada na vida profissional
e acadêmica.
2
Guia de Sintaxe ANSI/ISO Padrão C++ 3
B.1.1 Caracteres
Os caracteres que podem ser utilizados para construir elementos da linguagem (componentes léxicos ou tokens)
são:
a b c d e f g h i j k l m n o p q r s t u v w x y z
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
0 1 2 3 4 5 6 7 8 9
+ - * / = ( ) { } [ ] < > ‘ ” ! @ / $ ^ & % - : . , ; ? \ |
B.1.2 Comentários
C++ suporta dois tipos de comentários. As linhas de comentários ao estilo C e ANSI C, tal como:
A versão /*...*/ é utilizada para comentários que excedam o comprimento de uma linha e a versão
/ /... é utilizada somente para comentários de uma linha.
Os comentários não se aninham.
B.1.3 Identificadores
Os identificadores (nomes de variáveis, constantes etc.) devem começar com uma letra do alfabeto (maiúscula
ou minúscula) ou com um caractere sublinhado e podem ter um ou mais caracteres. Os caracteres segundo e
posteriores podem ser letras, dígitos ou um sublinhado, não sendo permitidos caracteres alfanuméricos nem
espaços.
teste_prova //legal
X123 //legal
multi_palavra //legal
var25 //legal
15var //não legal
Para uma boa prática de programação, é aconselhável utilizar identificadores significativos que ajudam a
documentar um programa.
Os diferentes compiladores comerciais de C++ podem incluir novas palavras reservadas. Estes são os casos
de Borland, Microsoft e Symantec.
• enumerações (enum)
• estruturas (struct)
• uniões (união)
• arrays
• classes (classe e struct)
• uniões e enumerações anônimas
• ponteiros
6 Programação em C++: Algoritmos, estruturas de dados e objetos
• Falha ao devolver um valor de uma função. Uma função em C++ declarada com um tipo determinado de
retorno deve devolver um valor desse tipo. Em C, é permitido não seguir a regra.
• Atribuição de ponteiros void. A atribuição de um tipo void* a um ponteiro de outro tipo deve ser feita
com uma conversão explícita em C++. Em C, é realizada implicitamente.
• Início de constantes de cadeia. Em C++, devemos proporcionar um espaço para o caractere de terminação
nulo quando se inicializam constantes de cadeia. Em C, é permitida a ausência desse caractere.
int main( )
{
//...
char car[7] = “Cazorla”, //legal em C
//erro em C++
//...
return 0;
}
B.3 CONSTANTES
C++ contém constantes para cada tipo de dado simples (integer, char etc.). As constantes podem ter três
sufixos, u, l e f, que indicam tipos unsigned, long e float, respectivamente. Assim, podem-se acrescentar
os prefixos o ou ox que representam constantes octais e hexadecimais.
456 0456 Ox456 //constantes inteiras: decimal, octal,
//hexadecimal
1231 123u1 //constantes inteiras: long, unsigned
//long
‘B’ ‘b’ ‘4’ //constantes tipo char
3.1415f 3.14159L //constantes reais de diferente posição
“cadeia de caracteres” //constantes de cadeia
As cadeias de caracteres estão entre aspas e as constantes de um só caractere estão entre apóstrofos.
“ ” //cadeia vazia, ‘\0’
Uma constante literal é um valor escrito diretamente no programa sempre que seja necessário. Por exemplo:
int minhaIdade = 25;
Em C++, os identificadores de variáveis/constantes podem ser declarados como constantes, significando que
têm um valor de início, mas que não pode ser modificado. Essas constantes são denominadas simbólicas.
Essa declaração é efetuada com a palavra reservada const.
O modificador de tipos const também se utiliza em C++ para proporcionar proteção somente de leitura
para variáveis e parâmetros de funções. As funções-membro de uma classe que não modificam os membros
dado que são acessados podem ser declarados const. Esse modificador evita também que parâmetros passados
por referência sejam modificados:
C++ suporta também o método tradicional de declaração de constantes, ainda que agora esteja obsoleto. Para
declarar uma constante por esse método, devemos realizar com #define.
#define estudantePorChave 50
#define PI 3.1416
#define hex 16
(tipo) expressão
C++ modificou a notação anterior por uma notação funcional como alternativa sintática:
Em C++, as declarações de variáveis podem ser situadas em qualquer parte de um programa. Essa caracte-
rística faz que o programador declare suas variáveis próximo ao lugar onde são utilizadas as sentenças de seu
programa. O seguinte programa é legal em C++, mas não é válido em C:
#include <iostream.h>
int main( )
{
int i;
for (i=0; i < 100; ++i)
cout << i << endl;
double j;
for (j = 1.7547; j < 25.4675; j+= .001)
cout << j << endl;
}
O programa anterior poderia ser reescrito, fazendo a declaração e a definição dentro do mesmo laço:
int main( )
{
for (int i=0; i<100; ++i)
cout << i << end1;
B.6 OPERADORES
C++ é uma linguagem muito rica em operadores, classificados nos seguintes grupos:
• Aritméticos.
• Relacionais e lógicos.
• Atribuição.
• Acesso a dados e tamanho.
• Manipulação de bits.
• Vários.
Como conseqüência da grande quantidade de operadores, é produzida também uma grande quantidade de
diferentes expressões.
Exemplos
variável++ //pós-incremento
++variável //pré-incremento
variável-- //pós-decremento
-- variável //pré-decremento
++a; equivale a a = a + 1;
--b; equivale a b = b - 1;
Os formatos pós-fixos ficam de forma diferente segundo a expressão que seja aplicada:
int i, j, k = 5
k++; //k vale 6, mesmo efeito que ++k
--k //k vale agora 5, mesmo efeito que k--
k = 5;
i = 4*k++; //k é agora 6 e i é 20
k = 5;
j = 4 * ++k; //k é agora 6 e i é 24
O processador de atribuição (=) faz que o valor situado à direita do operador seja aplicado à variável situada à
sua esquerda. A atribuição costuma ocorrer como parte de uma expressão de atribuição e as conversões são
produzidas implicitamente.
a = b+ (c=10);
equivale a:
c=10;
a=b+c;
C++ proporciona operadores de atribuição que combinam operadores de atribuições e outros diferentes, pro-
duzindo operadores como +=, /=, -=, *= e %=. C++ suporta outros tipos de operadores de atribuição para mani-
pulação de bits.
+= x = x + y; x + = y;
-= x = x - y; x - = y;
*= x = x * y; x * = y;
/= x = x/y; x / = y;
%= x = x%y; x % = y;
Exemplos
a + = b; equivale a a = a + b;
a * = a + b equivale a a = a * (a+b);
v + = e; equivale a v = v + e;
v % = e; equivale a v = v%e;
Expressões equivalentes
n = n+1;
n += 1;
n++;
++n;
Os operadores lógicos e relacionais são os blocos de construção básicos para construções de tomada de posição
em uma linguagem de programação. A Tabela B.8 mostra os operadores lógicos e relacionais.
Guia de Sintaxe ANSI/ISO Padrão C++ 11
Regras práticas
Os operadores lógicos e relacionais atuam sobre valores lógicos: o valor falso pode ser ou 0 ou o ponteiro nulo;
o valor verdadeiro pode ser qualquer valor diferente de zero. A tabela seguinte mostra os resultados de diferen-
tes expressões.
Avaliação em curto-circuito
C++, como C, admite reduzir o tempo das operações lógicas; a avaliação das expressões é reduzida quando
algum dos operandos recebe valores concretos.
1. Operação lógica AND (&&). Se na expressão exprl && expr2, expr1 recebe o valor zero e a opera-
ção lógica AND (e) sempre será 0, seja qual foi o valor de expr2. Conseqüentemente, expr2 não será
avaliada nunca.
2. Operação lógica OR (||). Se expr1 recebe um valor diferente de zero, a expressão expr1 || expr2
será avaliada a 1, qualquer que seja o valor de expr2; portanto, expr2 não será avaliada.
12 Programação em C++: Algoritmos, estruturas de dados e objetos
Exemplos
~x Muda os bits 1 a 0 e os bits 0 a 1
x & y Operação lógica AND (e) bit a bit de x e y
x | y Operação lógica OR (ou) bit a bit de x e y
x << y x é deslocado para a esquerda (em y posições)
x >> y x é deslocado para a direita (em y posições)
Exemplos
int m, n[12];
sizeof(m) //proporciona 4, em máquinas de 32 bits
sizeof(n) //proporciona 48
sizeof(15) //proporciona 4
tamanho = sizeof(long) – sizeof(int);
Exemplo
a * b/c + d equivale a ((a*b)/(c+d)
+ - * / % ^ & |
~ ! = < > += -= *=
/= %= ^= &= |= << >> >>=
<<= == != <= >= && || ++
-- , ->* -> ( ) [ ]
B.7.1 Saída
O fluxo cout é o fluxo de saída-padrão que corresponde a stdout em C. Esse fluxo deriva da classe ostream
construída em iostream.
14 Programação em C++: Algoritmos, estruturas de dados e objetos
Unidade
cout Tela
central entrada binária saída de caracteres
cout << i;
#include <iostream.h>
int main( )
{
cout << “Olá, mundo\n”;
}
As saídas em C++ podem ser conectadas em cascata, com uma facilidade de escrita maior que em C.
#include <iostream.h>
int main( )
{
int i;
i = 1099;
cout << “O valor de i é” << i << “\n”;
return 0
}
#include <iostream.h>
int main( )
{
int x = 45;
double y = 495.125;
char *c = “e multiplicada por x=”;
cout << c << y*x << “\n”;
}
B.7.2 Entrada
A entrada é manuseada pela classe istream. Existe um objeto predefinido istream chamado cin que se refere
ao dispositivo de entrada-padrão (o teclado). O operador utilizado para obter um valor do teclado é o operador
de extração >>. Por exemplo, se i era um objeto int, será escrito:
cin >> i;
#include <iostream.h>
int main( )
Guia de Sintaxe ANSI/ISO Padrão C++ 15
{
int i;
cin >> i;
cout << i << “\n”;
}
#include <iostream.h>
int main( )
{
char c[60];
int x,y;
B.7.3 Manipuladores
Um método fácil de mudar a largura do fluxo e outras variáveis de formato é utilizar um operador especial
denominado manipulador. Um manipulador aceita uma referência de fluxo como um argumento e devolve uma
referência ao mesmo fluxo.
O programa seguinte mostra o uso de manipuladores especificamente para conversões de número
(dec, oct e hex):
#include <iostream.h>
int main( )
{
int i = 36;
cout << dec << i << oct << i “ ” hex << i <<“\n”;
}
36 44 24
Outro manipulador típico é end1, que representa o caractere de nova linha (salto de linha), e é equivalente a
‘n\’. O programa anterior pode ser escrito também assim:
#include <iostream.h>
int main( )
{
int i = 36;
cout << dec << i “ ” << oct << i <<“ ” << hex << i << end1;
}
B.8 SENTENÇAS
Um programa em C++ consta de uma seqüência de sentenças. Existem diversos tipos de sentença. O ponto-e-vírgula
é utilizado como elemento terminal de cada sentença.
16 Programação em C++: Algoritmos, estruturas de dados e objetos
char c1;
int p, q = 5, r = a+b; //supondo que a e b tenham sido
//declaradas e iniciadas com antecedência
const double IVA = 16.0;
expressão;
Exemplos
n++;
425; //legal, mas não faz nada
a+b; //legal, mas não faz nada
n = a < b || b != 0;
a += b = 3; //sentença complexa
{
sentença
sentença
sentença
...
}
As sentenças fechadas podem ser qualquer uma: declarações, expressões, sentenças compostas etc. Um
exemplo é:
{
int i = 5;
double x = 3.14, y = -4.25;
int j = 4–i;
x = 4.5.*(x–y);
}
if (expressão) if (expressão) {
sentença <seqüência de sentenças>
}
Se expressão for verdadeira (diferente de zero), então são executadas sentença ou seqüência de
sentenças; caso contrário, salta-se a sentença. Depois que a sentença if foi executada, o controle passa para
a sentença seguinte.
Exemplo 1
if (a < 0)
negativos++;
1. if (expressão) 2. if (expressão)
sentença1; <seqüência de sentenças 1>
else else
sentença2; <seqüência de sentenças 2>
Se expressão é diferente de zero, a sentença1 é executada e sentença2 salta; se expressão for zero,
a sentença1 salta e sentença2 é executada. Uma vez que tenha sido executada a sentença if_else, o con-
trole passa para a sentença seguinte.
Exemplo 4
if (Número == 0)
cout << “Não será calculada a média”;
else
média = total / Número;
Exemplo 5
if (quantidade > 10){
desconto = 0.2;
preço = n * preço*(1 – desconto);
}
18 Programação em C++: Algoritmos, estruturas de dados e objetos
else {
desconto = 0;
preço = n * preço;
}
if (expressão 1)
sentença 1; | {sentença composta}
else if (expressão 2)
sentença 2; | {sentença composta}
else if (expressão N)
sentença N; | {sentença composta}
[else
sentença N+1; | {sentença composta}]
Exemplo
if (a > 100)
if (b <= 0)
SomaP = 1;
else
SomaN = 1;
else
Número = 1;
switch (expressão)
{
case constante 1;
sentenças
break:
case constante 2;
sentenças
.
.
.
break;
case constante n:
sentenças
break;
default: //opcional
sentenças
}
A sentença switch requer uma expressão cujo valor seja inteiro. Esse valor pode ser uma constante, uma
variável, uma chamada à função ou uma expressão. O valor de constante deve ser uma constante. Ao execu-
tar a sentença, avaliamos expressão, e se seu valor coincide com uma constante, executamos as sentenças
a seguir; caso contrário, executamos as sentenças a partir de default.
Guia de Sintaxe ANSI/ISO Padrão C++ 19
switch (Pontos)
{
case 10:
nota = ‘A’;
break;
case 9:
nota = ‘B’;
break;
case 7,8:
nota = ‘C’;
break;
case 5, 6:
nota = ‘D’;
break;
default:
nota = ‘F’;
}
• while.
• do.
• for.
while (expressão)
sentença;
ou
while (expressão){
< seqüência de sentenças >
}
Exemplo
int n, soma = 0;
int i = 1;
while (i <= 100)
{
cout <<“Entrar”;
cin >> n;
soma += n;
i++;
}
cout <<“A média é” << double (soma)/100.0;
B.10.2 Sentença do
A sentença do atua como a sentença while. A única diferença real é que a avaliação e o teste de saída do laço
são feitos depois que o corpo do laço foi executado, e não antes. O formato é:
20 Programação em C++: Algoritmos, estruturas de dados e objetos
do
sentença
while (expressão);
sentença seguinte
Executamos sentença e, a seguir, avaliamos expressão, e se for verdadeira (diferente de zero), o con-
trole passa novamente ao princípio da sentença do, e o processo se repete até que expressão seja falso (zero)
e o controle passe para a sentença seguinte.
Exemplo
int n, soma = 0;
int i = 1;
do
{
cout <<“Entrar”;
cin >> n;
soma += n;
i++;
} while (i <=100);
cout << “A média é” << double soma)/100.0;
int i = 2;
do
{
cout << i << “por” << i <<“ =” << i * i++ << end1;
}while (i < 11);
expressão1 é utilizada para inicializar a variável de controle do laço; a seguir, expressão2 é avaliada; se
for verdadeira (diferente de zero), executa-se a sentença e se avalia expressão3, e o controle passa de novo
ao princípio do laço. A iteração continua até que expressão2 seja falsa (zero) cujo momento o controle passa
para a sentença seguinte do laço.
Exemplo
1. for (int i = 0; i < n; i++) //realizam-se n iterações
sentenças
Precaução
• Uma sentença break pode ocorrer unicamente no corpo de uma sentença for, while, do ou
switch.
• Uma sentença continue somente pode ocorrer dentro do corpo de uma sentença for, while
ou do.
char cad[80]=“Cazorla”;
int i;
return expressão;
B.11 PONTEIROS
Um ponteiro é uma referência indireta a um objeto de um tipo especificado. Essencialmente, um ponteiro con-
tém a posição de memória de um tipo dado.
22 Programação em C++: Algoritmos, estruturas de dados e objetos
Uma vez declarado um ponteiro, podem ser fixados o endereço ou a posição de memória do tipo que foi
apontado.
NomeTipo *NomeVariável
Uma vez declarado um ponteiro, p, o objeto que foi apontado é escrito *p e pode ser tratado como qualquer
outra variável de tipo NomeTipo.
int * ip;
double *dp;
Podemos, entretanto, efetuar atribuições entre conteúdos, já que seria efetuada uma conversão explícita de
tipos:
*dp = *ip;
Existe um ponteiro especial (nulo) que costuma ser utilizado com freqüência em programas C++. O
ponteiro NULL tem um valor zero, que o diferencia de todos os endereços válidos. O conhecimento nos
permite comprovar se um ponteiro p é o ponteiro NULL, avaliando a expressão (p==0). Os ponteiros NULL
são utilizados somente como sinal de que aconteceu algo. Em outras palavras, se p é um ponteiro NULL, é
incorreto referenciar *p.
int lista[5];
lista[3] = 5;
Guia de Sintaxe ANSI/ISO Padrão C++ 23
O nome de um array pode ser utilizado como se fosse um ponteiro ao primeiro elemento do array.
0 1 2 3 4 5 6 7 8 9
Este elemento pode ser ativado por: Este elemento pode ser ativado por:
a[0], *p ou p[0] a[6], *(p+6) ou p[6]
Se nome aponta o primeiro elemento do array, então nome+1 aponta o segundo elemento. O conteúdo do
que é armazenado nessa posição se obtém pela expressão
*(nome+1)
Ainda que as funções não possam modificar seus argumentos, se um array é utilizado como um argumen-
to de uma função, a função pode modificar o conteúdo do array.
struct família
{
char *marido;
char *esposa;
char *filho;
};
família mackoy; //mackoy estrutura de tipo família
família *p; //p; um ponteiro a família
p = &mackoy; //p, contém endereço de mackoy
p –> marido,“Luis Mackoy”); //iniciação
p –> esposa,“Vilma González”); //iniciação
p –> filho,“Luizinho Mackoy”); //iniciação
estabelece v como um ponteiro a um objeto que não pode ser modificado. Um exemplo pode ser:
int main( )
{
void *vptr;
int *iptr;
vptr = iptr;
iptr = vptr; //Incorreto em C++, correto em C
iptr = (int *), vptr; //Correto em C++
...
}
Constantes de cadeia
Sua declaração é semelhante a
Ponteiros a cadeias
Os ponteiros de cadeias não são cadeias. Os ponteiros localizam o primeiro elemento de uma cadeia armazenada.
char *varCadeia;
const char *Cadeiafixa;
Guia de Sintaxe ANSI/ISO Padrão C++ 25
Considerações práticas
Todos os arrays em C++ são implementados mediante ponteiros:
#include <iostream.h>
main (void)
{
int *ptrl, *ptr2;
int a[2] = {10, 10};
ptrl =a;
cout << “ptrl é” << “ptrl << “*ptrl é” << *ptr1 << end1;
ptr2 = ptr1 + 1;
cout << “ptr2 é” << ptr2 << “*ptr2 é” << *ptr2 << end1;
if (*ptr1 == *ptr2)
cout << ptr1 é igual a *ptr2 \n”;
else
cout << ptr1 não é igual a *ptr2\n”;
}
new NomeTipo
26 Programação em C++: Algoritmos, estruturas de dados e objetos
int *ptr1;
double *ptr2;
ptr1 = new int; //memória atribuída para o objeto ptr1
ptr2 = new double //memória ampliada para o objeto ptr2
*ptr1 = 5;
*ptr2 = 6.55;
Dado que new devolve um ponteiro, podemos utilizar esse ponteiro para inicializar o ponteiro em uma úni-
ca definição, como:
Se new não pode ocupar a quantidade de memória solicitada, devolve um valor NULL. O operador delete
libera a memória atribuída mediante new.
delete ptr1;
#include <iostream.h>
void main (void)
{
char *c;
c = new char[512];
cin >> c;
cout << c << end1;
delete c;
}
Os operadores new e delete podem ser utilizados para atribuir memória a arrays, classes e outro tipo de dados.
int * i;
i = new int[2][35]; //criar o array
//atribuir o array
...
delete i; //destruir o array
B.13 ARRAYS
Um array (matriz, tabela) é uma coleção de elementos dados do mesmo tipo que se identificam por meio de
um índice. Os elementos começam com o índice 0.
Guia de Sintaxe ANSI/ISO Padrão C++ 27
Declaração de arrays
Uma declaração de um array tem o seguinte formato:
nomeTipo nomeVariável[n]
int multidim[4][10][3];
enum nome
{
lista_símbolos
};
28 Programação em C++: Algoritmos, estruturas de dados e objetos
onde nome é o nome da variável declarada enumerada; lista-símbolos é uma lista de tipos enumerados, aos
quais são atribuídos valores quando se declara a variável enumerada e pode-se ter um valor de inicialização.
Podemos utilizar o nome de uma enumeração para declarar uma variável desse tipo (variável de enumeração).
nome var;
Uma estrutura é um tipo de dado composto que contém uma coleção de elementos de tipos de dados dife-
rentes combinados em uma única construção da linguagem. Cada elemento da coleção é chamado membro e pode
ser uma variável de um tipo de dado diferente. Uma estrutura representa um novo tipo de dado em C++.
struct nome
{
membros
};
struct quadro{
int i;
float f;
};
Uma união é uma variável que pode armazenar objetos de tipos e tamanhos diferentes. Uma união pode ar-
mazenar tipos de dados diferentes, pode armazená-los somente um de cada vez, em oposição a uma estrutura que
armazena simultaneamente uma coleção de tipos de dados. A sintaxe de uma união é:
união nome {
membros
};
Um exemplo de estrutura é:
união alfa {
int x;
char c;
};
alfa w;
u.x = 145;
u.c = ‘z’;
Guia de Sintaxe ANSI/ISO Padrão C++ 29
C++ admite um tipo especial de união chamado união anônima, que declara um conjunto de membros que
compartilham o mesmo endereço de memória. A união anônima não tem atribuído um nome, portanto, acessa
diretamente os elementos da união. A sintaxe de uma união anônima é:
união {
int novoID;
int contador;
};
int main( )
{
união{
int x;
float y;
double z;
};
x = 25;
y = 245.245; //o valor em y sobrescreve o valor de x
z = 9.41415; //o valor em z sobrescreve o valor de z
...
}
B.15 CADEIAS
Uma cadeia é uma série de caracteres armazenados em bytes consecutivos de memória. Uma cadeia pode ser
armazenada em um array de caracteres (char) que termina em um caractere nulo (zero, ‘\0’).
char cão[5] = {‘m’, ‘o’, ‘r’, ‘g’, ‘a’, ‘n’}; //não é uma cadeia
char gato[5] = {‘f’, ‘e’, ‘l’, ‘i’, ‘s’, ‘\0’}; //é uma cadeia
return 0;
}
Essa leitura do teclado lê uma cadeia até que seja encontrado o primeiro caractere branco. Assim, quando
lemos “Serra Magna. Jaén”, em cad somente armazenamos Serra. Para resolver o problema, utilizamos
a função gets( ), que lê uma cadeia completa a partir do teclado. O programa anterior é escrito para ler toda
a cadeia introduzida:
#include <iostream.h>
#include <stdio.h>
30 Programação em C++: Algoritmos, estruturas de dados e objetos
main( )
{
char cad[80];
return 0;
}
B.16 FUNÇÕES
Uma função é uma coleção de declarações e sentenças que realizam uma única tarefa. Cada função tem quatro
componentes: 1) seu nome, 2) o tipo de valor que devolve quando termina sua tarefa, 3) a informação que recebe
ao realizar sua tarefa, 4) a sentença ou sentenças que realizam sua tarefa. Cada programa C++ tem pelo menos
uma função: a função main.
Em C++, devemos declarar uma função antes de utilizá-la. A declaração da função indica ao compilador o tipo de
valor que a função devolve e o número e o tipo de argumentos que recebe. A declaração em C++ é denominada
protótipo:
Os parâmetros por omissão não necessitam ser especificados quando chamamos a função. Os parâmetros
com valores por omissão devem estar ao final da lista de parâmetros:
ImprimirValores(n,a);
ImprimirValores(n); //equivalente a ImprimirValores (n, 0.0)
main ( )
{
int x = 5, y = 4;
int z = Max(x,y);
}
Os parâmetros com valores por omissão devem entrar no final da lista de parâmetros: as funções f1, f2 e f3
são válidas, enquanto as funções f4 e f5 não são válidas.
As funções em linha (inline) evitam os tempos suplementares das chamadas múltiplas de funções. As funções
declaradas em linha devem ser simples, somente com poucas sentenças de programa; podem ser chamadas
somente um número limitado de vezes e não são recursivas.
As funções sobrecarregadas são diferentes no número e tipo de argumentos, e não no tipo que as funções
devolvem, e seus corpos são diferentes em cada uma delas.
#include <iostream.h
void soma(char i)
{
cout << “Soma interior (char)” << end1;
}
void soma(float j)
{
cout << “Soma interior (float)” << end1;
}
Guia de Sintaxe ANSI/ISO Padrão C++ 33
1. Por valor. A função chamada recebe uma cópia do parâmetro, e esse parâmetro não pode ser modificado
dentro da função:
2. Por direção. Passa-se um ponteiro ao parâmetro. Esse método permite simular em C/C++ a chamada por
referência, utilizando tipos ponteiros nos parâmetros formais na declaração de protótipos. O método per-
mite modificar os argumentos de uma função.
3. Por referência. Pode-se passar tipos referência como argumentos de funções, o que permite modificar os
argumentos de uma função.
Se for necessário modificar um argumento de uma função em seu interior, o argumento deve ser um tipo
referência na declaração da função.
34 Programação em C++: Algoritmos, estruturas de dados e objetos
B.17 CLASSES
Uma classe é um tipo definido pelo usuário que contém um estado (dados) e um comportamento (funções que
manuseiam os dados). Uma classe é como uma estrutura (struct) em C com a diferença que contém funções
incorporadas. Além disso, uma classe pode ter alguns membros que sejam privados e os que não podem ser
acessados do exterior da classe. Essa propriedade é chamada encapsulamento e é um meio útil para ocultar
detalhes que não são vistos pelo resto do programa.
As classes são diferentes dos objetos que definem a classe como um tipo. As classes em C++ são compa-
ráveis com os tipos primitivos, como int, char e double e um nome de classe pode aparecer em qualquer
texto que puder fazer int, char e double. Um objeto, ao contrário, é como um inteiro individual, um carac-
tere ou um ponto flutuante. Um objeto tem um estado particular, enquanto uma classe é uma descrição geral do
código e dos dados e não contém informação. Cada classe pode ter muitos objetos. Um objeto é conhecido nor-
malmente como uma instância ou um exemplar.
Sintaxe
Podemos declarar uma classe em C++ utilizando class, struct ou union:
class | struct | union nome[declarações_classe_base]
{
declarações
} [definições_de_objeto];
Guia de Sintaxe ANSI/ISO Padrão C++ 35
|, indica que uma das três palavras reservadas deve ser utilizada no princípio da declaração.
[ ], o conteúdo de seu interior é opcional.
Cada uma das três palavras reservadas, class, struct e union, cria uma classe com essas diferenças:
• O nível de acesso a membros por omissão é privado caso se utilize class. O nível de acesso a membros
é público se utilizamos union ou struct.
• As palavras reservadas struct e class criam um tipo semelhante a uma estrutura em C. Uma union
cria um tipo em que todos os membros dados começam no mesmo endereço na memória.
classe CCad{
private:
char *pDados;
int nComprimento;
public:
CCad( ); //Construtor
-CCad( ); //Destruidor
char *obter(void) {return pDados;}
int obtercomprimento(void) {return nComprimento;}
char * copy(char * s);
char * cat(char * s);
}
B.17.1 Construtor
Um construtor é uma função-membro que é chamada automaticamente quando criamos um objeto; seu nome é
o mesmo que o nome da classe. Quando criamos objetos dinamicamente, utilizamos new e delete, em vez de
malloc e free. Os construtores não têm tipo de retorno (nem, inclusive, void). A própria classe é o tipo de retor-
no. Os construtores são como outras funções membro, ainda que não herdaram. É conveniente que os constru-
tores sejam declarados como públicos para que o resto do programa tenha acesso a eles.
class CDesenho {
private:
long coste;
int nEstrelas;
CCad sDiretor;
public:
//Construtores
CDesenho( );
CDesenho(long c, int n, CCad dir);
~CDesenho( ){delete[];} // destruidores
};
class( )
class Ponto {
public:
Ponto( )
{
x = 0;
y = 0;
}
private:
int x;
int y;
};
C++ cria automaticamente um construtor por omissão quando não existe outro construtor.
Ponto figura[3];
B.17.5 Destruidores
Um destruidor é uma função-membro especial que é chamada automaticamente quando desejamos apagar um
objeto da classe. O nome de um destruidor é o nome da classe, precedido pelo caractere ~ (til). Se não for de-
clarado explicitamente um destruidor, C++ cria automaticamente um vazio.
Guia de Sintaxe ANSI/ISO Padrão C++ 37
class Ponto{
public:
~Ponto( )
{
cout << “Destruidor Ponto chamado \n”;
}
//...
};
Um destruidor não tem parâmetros nem, inclusive, void e não tem tipo de retorno. Uma classe pode ter
somente um destruidor.
class Estudante {
public:
Estudante( )
{
LerId (0);
LerNotaMédia(0.0);
}
void LerId(long);
void LerNotaMédia(float);
private:
long id;
DadosAcadêmicos da;
Direção dir;
float NotaMédia;
};
B.17.7 Funções-membro
As funções-membro são funções declaradas dentro de uma classe. Conseqüentemente, elas têm acesso a mem-
bros public, private e protected dessa classe. Se são definidas dentro da classe, são tratadas como funções
inline e tratadas também como sobrecarregadas.
class vetor {
public:
vetor(int n = 50); //construtor por default
vetor (const vetor& v); //construtor de cópia
vetor(const int a[ ], int n);
...
int teo( ) const { return(size-1); } //função-membro em linha
private:
...
};
38 Programação em C++: Algoritmos, estruturas de dados e objetos
As funções-membro são invocadas normalmente mediante o uso de operadores ponto (.) ou ->.
Uma função-membro constante é aquela que garante que não será modificado o estado do objeto da classe.
class Ponto {
public:
Ponto (int xval, int yval);
Uma amiga (friend) de uma classe tem acesso a todos os membros dessa classe. Se uma função F, amiga
de uma classe C, utiliza um objeto da classe C, é como se todos os membros de C fossem declarados públi-
cos. O tipo mais comum de amigo de uma classe é uma função. As classes também podem ser amigas de
outras classes.
Para declarar uma função como amiga de uma classe, é preciso incluir um protótipo da função interior da
declaração da classe, precedida da palavra reservada friend.
class nome {
...
friend protótipo_de_função;
...
};
class nome {
...
friend class nome_classe;
};
Guia de Sintaxe ANSI/ISO Padrão C++ 39
Função amiga
class Estudante;
class Funcionário {
public:
Funcionário (long idVal);
friend void RegistrarEstudante (Estudante &S,
Funcionário &E, float taxa);
private:
long id; // número de matrícula
float PagoTaxa;
};
Classe amiga
class classe_1 {
friend class classe_2;
//...
};
class classe_2 {
friend class classe_3;
};
B.18 HERANÇA
Uma herança é uma relação é-um entre duas classes, na qual uma nova classe deriva de outra classe –
denominada classe-base. A nova classe é denominada classe derivada. A relação é-um se manifesta como
“um estudante de doutorado é-um estudante que está escrevendo uma tese”.
Sintaxe
class nome_classe_derivada: (public|protected|private) classe_base {
declarações
};
classe_base é o nome da classe da qual é derivada a classe atual – derivada – e os especificadores
de acesso podem ser public, protected ou private. Um membro public é acessível por meio de seu
escopo; os membros de classe_base são herdados sem modificação em seu estado. Um membro privado
(private) é acessível a outras funções-membro dentro de sua própria classe. Um membro protegido (pro-
tected) é acessível a outras funções-membro dentro de sua classe e a qualquer classe derivada dela. Os modifi-
cadores de acesso podem ser utilizados dentro de uma declaração de uma classe em qualquer ordem e com qual-
quer freqüência.
40 Programação em C++: Algoritmos, estruturas de dados e objetos
class D : public A {
...
};
A herança múltipla permite que uma classe seja derivada de mais de uma classe-base. No exemplo seguin-
te, D é a classe derivada e B1, B2 e B3 são classes-base.
A palavra reservada virtual é um especificador de função que proporciona um mecanismo para selecionar
em tempo de execução a função-membro apropriada da classe-base e de classes derivadas
Uma função operador é uma função cujo nome consta da palavra reservada operador seguida por um
operador binário ou unitário com o formato:
operator operador
// Sobrecarga de operadores aritméticos e
// de atribuição
class Ponto
}
//...
public:
//...
Ponto operator * (const Ponto& p);
Ponto operator / (const Ponto& p);
Ponto operator += (const Ponto& p);
//...
};
//implementação de função-membro sobrecarregada
//pl * p2
inline Ponto Ponto::operator * (const Ponto& p)
{
return Ponto (x * p.x, y * p.y, z * p.z);
}
//p1 / p2
...
Guia de Sintaxe ANSI/ISO Padrão C++ 41
Ponto p, q, r;
//...
r = p * q; //multiplicação
//...
r = p += q; //atribuição encadeada e aritmética
//...
O compilador avalia a expressão chamando uma das seguintes funções, dependendo de qual está definida:
tipo_retorno tipo::operator@( )
tipo_retorno operator@ (tipo)
Dependendo do próprio operador, a expressão que utiliza um operador unitário pode ser da forma
operando@
o compilador avalia a expressão chamando uma das seguintes funções, dependendo de onde esteja definida:
classe Cponto {
private:
double x, y;
public:
Cponto& operator = (const Cponto& ponto);
...
};
42 Programação em C++: Algoritmos, estruturas de dados e objetos
class Cponto {
private:
double x, y;
public:
Cponto& operator++( ); //prefixado
Cponto operator++(int); //pós-fixado
};
class P {
public:
void operator++(int); //pós-fixado
void operator--(int); //pós-fixado
};
Sintaxe
template < argumentos_modelo > //modelo de classe
declaração_de_classe
template <classT>
tipo_retorno nome_função(T parâmetro)
T é um parâmetro de modelo
{
T aux;
aux = x;
x = y;
y = aux;
}
int m, n;
Estudante S1;
Estudante S2;
//...
Intercâmbio(m, n); //chamada com inteiros
Intercâmbio(S1, S2); //chamada com estudantes
T pode ser um tipo ou uma expressão. Os modelos instanciam-se para criar classes deles.
MinhaClasse <int> x;
MinhaClasse <Estudante> MinhaEstudante;
B.21 EXCEÇÕES
O manuseio ou manipulação de exceções é o mecanismo para detectar e manipular exceções. Um manipulador
de exceções é um bloco de código que processa condições de erros específicas. Uma exceção é, quase sempre,
um erro em tempo de execução, tal como “falta de memória”, “falha ao abrir um arquivo”, “erros do intervalo
de subíndice” ou “divisão por zero”.
Em C++, quando geramos uma exceção, o erro não pode ser ignorado ou terminará o programa. Um programa
lança ou dispara (throws) uma exceção no ponto em que é detectado o erro. Quando acontece isso, um pro-
grama C++ busca automaticamente o manipulador de exceções, que responde à exceção de alguma forma
apropriada. Essa resposta é denominada “capturar uma exceção” (catching). Se não podemos encontrar um
manipulador de exceções, o programa será terminado.
throw
throw expressão
//lançamento de uma exceção, criando um subíndice
//está fora do intervalo
const unsigned LongArray = 500;
unsigned i;
.
.
.
if (i > = LongArray) //é o subíndice válido
throw ErroIntervalo;
A palavra reservada try, juntamente com as sentenças que seguem entre chaves, é chamada bloco try. Deve
ser seguido imediatamente por um ou mais manipuladores de exceções. Cada manipulador de exceções começa
com a palavra reservada catch seguida por um bloco que contém sentenças.
try {
lista_de_sentenças
}
catch (lista_de_parâmetros){
lista_de_sentenças
}
catch (lista_de_parâmetros){
lista_de_sentenças
}
Sintaticamente, uma especificação de exceções é parte de uma declaração de funções e tem o formato:
A lista de tipos são os tipos que podem ter uma sentença throw expressão dentro da chamada da função;
se a lista for vazia, o compilador pode supor que nenhuma sentença throw será executada pela função, direta
ou indiretamente.
void Demo( )
{ try {
//...
chamada a Demo( )
}
catch (A)
throw;
}
catch (B)
}
//...
}
catch (...)
{
//unexpected
}
Se uma função não está especificada com uma declaração throw, pode lançar qualquer exceção. A declaração
throw( ) indica que uma função não lança nenhuma exceção.
Se uma função lança uma exceção que não está em sua declaração, chama a função unexpected. Na maioria
das implementações, unexpected chama a função terminate que chama abort. A função set_unexpected
permite definir o manejo de exceções não previstas. Todas essas declarações de funções se encontram no arquivo
except ou except.h.
46 Programação em C++: Algoritmos, estruturas de dados e objetos
catch (dec_argumento1) {
sentenças
}
catch (dec_argumento2) {
sentenças
}
...
throw;
namespace nome {
corpo_espaço_de_nomes
}
Esse formato cria um espaço de nomes com o qualificador nome. Dentro dos caracteres chave ({ }),
corpo_espaço_de_nomes pode incluir variáveis, definições de funções e protótipos, estruturas, classes,
enumerações (enum), definições de tipos (typedef) ou outras definições de espaços de nomes. Observe que
um espaço de nomes não termina com um ponto-e-vírgula. As definições de espaço de nomes aparecem em
arquivos de cabeçalho e em módulo independentes com definições de funções.
Exemplo
namespace Vermelho {
int j;
void imprimir(int i)
{cout << “Vermelho::imprimir( ) ” << i << end1;}
}
namespace Azul {
int j;
void imprimir(int);
}
void sub1( ) {...} //pode acessar o espaço de nomes
//Azul e Vermelho
void sub( ) {...} //pode acessar o espaço de nomes
//Azul e Vermelho
Os espaços de nomes Vermelho e Azul têm dois membros com o mesmo nome: inteiro j e função
imprimir( ) (normalmente, essas definições não poderiam conviver em um espaço global, mas um espaço
de nomes elimina esse problema). Um espaço de nomes pode incluir definições de funções e protótipos de
funções. As definições de funções de sub1( ) e sub2( ) têm acesso a todos os membros do espaço de nomes
Vermelho e Azul.
B.22.1 Extensões
Os espaços de nomes se estendem, ou seja, podem ser acrescentadas declarações posteriores a espaços de nomes
definidos anteriormente. As extensões do espaço de nomes podem aparecer também em arquivos independen-
tes da definição original do espaço de nomes.
48 Programação em C++: Algoritmos, estruturas de dados e objetos
nome_espaço_de_nomes::nomes_membro
O operador de resolução de escopo associa imprimir( ) ao espaço de nomes Azul; sem ele, o compilador
define imprimir( ) como uma função global.
É muito útil envolver um conjunto de declarações em um espaço de nomes simplesmente para proteção diante
da possibilidade de conflitos de nomes. O formato é:
namespace {
corpo_nome_de_espaço
}
Todos os membros definidos em corpo_nome_de_espaço estão em um espaço de nomes sem nome que
se garante ser único para cada unidade de tradução.
No acesso aos membros de espaço de nomes, pode-se ter dificuldades, especialmente com qualificadores de espa-
ço de nomes longos e espaços de nomes aninhados. As diretivas using proporcionam acesso a todos os membros
do espaço de nomes sem um qualificador de espaço de nomes e o operador de escopo. O formato é:
O qualificador nome deve ser um nome de espaço definido anteriormente. Podem aparecer as diretivas
using em escopos locais e globais.
Guia de Sintaxe ANSI/ISO Padrão C++ 49
using nome_espaço_de_nomes::nome-membro;
using Branco::vision;
Exemplo
namespace Universidade_Pontifícia_deSalamanca_emMadri{
//...
}
Universidade_Pontifícia_deSalamanca_emMadri::String c3 =
“Fundação”;
Universidade_Pontifícia_deSalamanca_emMadri::String c4 =
“Pablo VI”;
O código anterior é pouco prático em código real; um pseudônimo curto resolve o inconveniente.
UPSAM::String c3 = “Fundação”;
UPSAM::String c4 = “Pablo VI”;
namespace Geometria{
struct Ponto {
double x, y;
};
double pendente (Ponto, Ponto);
}
O espaço de nomes inclui um tipo Ponto e uma função pendente. A implementação do arquivo
geometria.c:
50 Programação em C++: Algoritmos, estruturas de dados e objetos
// geometria.c
#include “geometria.h”
Uma extensão do espaço de nomes acrescentou um membro origem a Geometria. A função pendente( )
calcula a pendente dos pontos p1 e p2 e levanta uma exceção de cadeia de caracteres se o denominador da pen-
dente for zero.
Os espaços de nomes são ilegais no interior de funções, mas podem aparecer em outras definições de espaço
de nomes.
namespace Exterior {
int i, j;
namespace Interior {
const int Máx = 20;
char car;
char bufer[Máx];
void imprimir( );
}
}
O acesso aos membros de um espaço de nomes aninhados é resolvido com o operador de resolução de
escopo (::)
void Exterior::Interior::imprimir( ) {
for (int i = 0; i < Máx; i++) //i é local ao laço for
cout << bufer[i] << ’’;
cout << end1;
}
#inifndf GEOMETRIAH
#define GEOMETRIAH
// arquivo geometria.h
Aplicação. Utilizar o espaço de nomes Geometria para calcular pendentes das variáveis Ponto.
Guia de Sintaxe ANSI/ISO Padrão C++ 51
#include <iostream.h>
#include “geometria.h”
using Geo::Ponto;
using Geo::pendente;
namespace {
Ponto origem = {10, 10};
}
int main( )
{
try {
Ponto a = {3, 5}
Ponto b = {6, 10};
cout << “A linha ab tem a pendente”
<< pendente (a,b) << end1;
cout << “A linha origem_a tem a pendente”
<< pendente (origem, a)
<< end1;
}
catch (char *msg) {
cout << msg << end1;
return 1;
}
return 0;
}
#endif