Baixe o app para aproveitar ainda mais
Prévia do material em texto
nov/2004 Renato Maia 1 A Linguagem C++ Renato Maia maia@inf.puc-rio.br TeCGraf/PUC-Rio Renato Maia 2nov/2004 Hello, World! #include <iostream> int main() { std::cout << "Hello, world!" << "\n"; } nov/2004 Renato Maia 3 MÓDULO I Recursos Básicos Renato Maia 4nov/2004 Recursos Básicos n Parte 1: ¨ Tipos ¨ Declarações ¨ Ponteiros ¨ Vetores ¨ Estruturas ¨ Operadores ¨ Expressões ¨ Comandos ¨ Funções n Exemplo ¨ Calculadora n Parte 2: ¨ Espaços de Nomes ¨ Compilação e Ligação nov/2004 Renato Maia 5 Tipos Renato Maia 6nov/2004 Tipo Lógico n Tipo: bool n Literais: true , false n Conversões: ¨ trueè 1 ¨ falseè 0 ¨0 è false ¨?0 è true Renato Maia 7nov/2004 Tipo Caractere n Tipo: char n Modificadores: signed , unsigned n Literais: ¨Letras: 'a', 'b', ..., 'Z' ¨Algarismos: '0', '1', ..., '9' ¨Especiais: '\n', '\t', '\0' ¨Números: 97 // o 'a' na tabela ASCII Renato Maia 8nov/2004 Tipo Inteiro n Tipo: int n Modificadores: ¨ signed , unsigned ¨ short , long n Literais: ¨ Decimal: 20 ¨ Octal: 020 ¨ Hexadecimal: 0x20f Renato Maia 9nov/2004 Tipos Reais n Tipos: float , double n Modificadores: long (aplicável ao double) n Literais: (não podem conter espaços) ¨ 1.23 ¨ .23 ¨ 1. ¨ 1.23e10 ¨ 1.23e-10 Renato Maia 10nov/2004 Tipo Vazio n Tipo: void n Uso: ¨Como tipo de retorno de uma função n Define funções que não retornam valores ¨Como tipo de ponteiro n Define um ponteiro para tipo indefinido (ponteiro genérico) Renato Maia 11nov/2004 Enumerações n Exemplo: enum DiaSem { DOM, SEG, TER, QUA, QUI, SEX, SAB }; n Uso ¨Definir um tipo que assume um conjunto de valores inteiros pré-definidos (enumerados). nov/2004 Renato Maia 12 Declarações Renato Maia 13nov/2004 Declarações Especificador Tipo Declarador Iniciação/Definição char ch ; string s ; int count = 1 ; const double pi = 3.1415926535897932385 ; extern int error_number ; const char * name = "Najla" ; const char * season[ ] = {"spring","summer", "fall","winter}; struct Date { int d, m, y } ; int day(Date* p) { return p->d; } ; double sqrt(double) ; template<class T> T abs(T a) { return a<0 ? –a : a; } typedef list<int> SmallNums ; struct User ; enum Beer { Carlsberg, Tuborg, Thor } ; namespaceNS { int a; } ; Renato Maia 14nov/2004 Declarações (observações) n Declaração com vários nomes ¨ int a, b = 0; // apenas o 'b' é iniciado. ¨ int* pa, pb; // o 'pb' NÃO é um ponteiro. n Nomes de identificadores ¨hello, DEFINED, var23, _123, __, um_nome_razoavelmente_GRANDE n Iniciação (apenas estáticos) ¨Globais, namespace e static Renato Maia 15nov/2004 Escopo int x = 0; { int x = 1; cout << x; { int x = 2; cout << x; } x = 3; cout << x; } cout << x; Renato Maia 16nov/2004 Declaração de Tipos n Exemplos: typedef char *Pchar; Pchar p1, p2; char *p3 = p1; n Na realidade a declaração de um typedef define apenas um sinônimo para algum tipo. nov/2004 Renato Maia 17 Ponteiros e Vetores Renato Maia 18nov/2004 Ponteiros n Uso < Outras Formas char c = 'a'; char **ppc; char *pc = &c; char *vetp[15]; char c2 = *pc; char (*fp)(char*); pc: c: 'a' &c Renato Maia 19nov/2004 Iniciação de Ponteiros n A linguagem C++ não define uma palavra reservada para indicar um endereço de memória inválido ou nulo (e.g. null de Java). Ao invés disso usa-se o valor 0, que pode ser atribuído a ponteiros. Nenhum objeto é criado no endereço 0. n int *pi = 0; Renato Maia 20nov/2004 Vetores n Dimensões float d1[3]; float d2[10][20]; // não: float d2[10, 20]; n Iniciação int v1[ ] = { 1, 2, 3, 4 }; // v1 é do tipo int[4] char v3[3] = {'a','b',0}; // não: char v3[2] = {'a','b',0}; int v5[5] = {1,2,3} // equiv.: int v5[3] = {1,2,3,0,0}; int v7[5]; v7 = {1,2,3,4,5} // erro: apenas na iniciação Renato Maia 21nov/2004 Literais de Cadeias de Caracteres n Na iniciação de vetores de caracteres char c2[ ] = "cadeia"; char c3[ ] = { 'c', 'a', 'd', 'e', 'i', 'a', '\0' }; sizeof("cadeia") == 7 n Acesso através de ponteiros irrestritos (vs. ponteiros para const.) char *pc = "imutavel"; pc[0] = ' '; // erro: resultado indefinido n Comparação de cadeias const char *p = "C++"; const char *q = "C++"; if (p == q) cout << "one!\n"; // depende da implementação do C++ n Quebrando cadeias grandes const char longa[ ] = "inconstitucional" "issimamente\n" // "inconstitucionalissimamente\n" Renato Maia 22nov/2004 Ponteiros e Vetores n Conversão implícita para ponteiros char v[ ] = "cadeia"; char *p; p = v; // conversão implícita v = p; // erro: não é possível atribuir um ponteiro a um vetor 'c' 'a' 'd' 'e' 'i' 'a' 0v: p: p: p+=5; Renato Maia 23nov/2004 Aritmética de Ponteiros n Iteração sobre uma cadeia de caracteres char v[ ] = "uma cadeia\n" for (int i = 0 ; v[i] != 0 ; i++ ) use(v[i]); for (char *p = v ; *p != 0 ; p++ ) use(*p); n Subtração de ponteiros (ou endereços) int v1[10]; int v2[10]; int i1 = &v1[5] - &v1[3]; // i1 == 2 int i2 = &v1[5] - &v2[3]; // indefinido Renato Maia 24nov/2004 Constantes n Declaração const int model = 90; const int v[ ] = { 1, 2, 3, 4, 5 }; // v[i] é const const int x; // erro: exige iniciação n Ponteiros constantes char*const cp; // ponteiro constante const char*pc; // ponteiro para uma constante char const*pc2; // ponteiro para uma constante Renato Maia 25nov/2004 Referências n Definição int i = 1; int& r = i; // r e i se referem ao mesmo elemento n Uso int x = r; // x = 1 r = 2; // i = 2 n Iniciação int& r2; // erro: falta iniciação extern int& r3; // ok: r3 é iniciado em outro módulo Renato Maia 26nov/2004 Ponteiros Genéricos (void *) n Recurso de baixo nível n Operações int* pi = &i; void* pv = pi; // ok: conversão implicita de int* para void* *pv; // erro: não é possível acessar um void* pv++; // erro: não é possível incrementar um void* n Conversões (cast) int* pi2 = static_cast<int*>(pv); // conver. explíc. double* pd1 = pv; // erro double* pd2 = pi; // erro double* pd3 = static_cast<double*>(pv); // inseguro nov/2004 Renato Maia 27 Estruturas Renato Maia 28nov/2004 Estruturas n Declaração struct address { char *name; // "Jim Dandy" long int number; // 61 char *street; // "South St" char *town; // "New Providence" char state[2] ; // ’N’ ’J’ long zip; // 7974 }; Renato Maia 29nov/2004 Estruturas (cont.) n Uso address jd; jd.name = "Jim Dandy"; jd.number = 61; n Iniciação address jd = { "Jim Dandy", 61, "South St", "New Providence", {´N´,´J´}, 7974 }; Renato Maia 30nov/2004 Ponteiro para Estruturas n Operador de acesso através de ponteiros p->m è (*p).m n Uso address *p = &jd cout << p->name << ´\n´ << p->number << ´ ´ << p->street << ´\n´ << p->town << ´\n´ << p->state[0] << p->state[1] << ´ ´ << p->zip << ´\n´; Renato Maia 31nov/2004 Cópia de Estruturas address current; address set_current(address next) { address prev = current; current = next; return prev; } Renato Maia 32nov/2004 Declaração Antecipada struct Link { Link* previous; Link* successor; }; struct List; // definido posterior. struct Link { Link* pre; Link* suc; List* member_of; }; struct List { Link* head; }; nov/2004 Renato Maia 33 Operadores Renato Maia 34nov/2004 Operadores Relacionais n Igual == n Diferente != n Maior que > n Menor que < n Maior ou igual >= n Menor ou igual <= Renato Maia 35nov/2004 Operadores Aritiméticos n Adição + n Subtração - n Multiplicação * n Divisão / n Módulo % n Inversor de sinal - n Incremento -- n Decremento ++ Renato Maia 36nov/2004 OperadoresLógicos n E (and) && n Ou (or) || n Negação (not) ! Renato Maia 37nov/2004 Operadores sobre Bits n E bit a bit & n Ou inclusivo bit a bit | n Ou exclusivo (xor) bit a bit ^ n Complemento ~ n Deslocamento a esquerda << n Deslocamento a direita >> Renato Maia 38nov/2004 Operadores de Atribuição n Atribuição simples = n Multiplicação e atribuição *= n Divisão e atribuição /= n Módulo e atribuição %= n Soma e atribuição += n Subtração e atribuição -= n Deslocamento a esquerda e atribuição <<= n Deslocamento a direita e atribuição >>= n E bit a bit e atribuição &= n Ou inclusivo bit a bit e atribuição |= n Ou exclusivo bit a bit e atribuição ^= Renato Maia 39nov/2004 Operadores Composicionais n Seqüência <expr> , <expr> n Condicional <cond> ? <true> : <false> cout << ( (p1+p2+p3)/3 >= 5 ? "aprovado" : "reprovado" ) Renato Maia 40nov/2004 Operadores de Memória Dinâmica n Alocação new n Desalocação delete n Desalocação de vetores delete[ ] Renato Maia 41nov/2004 Operad. de Conversão de Tipos n Conversão estática (tipos relacionados) static_cast<tipo>(valor) n Conversão estática (tipos não relacion.) reinterpret_cast<tipo>(valor) n Conversão dinâmica dynamic_cast<tipo>(valor) n Conversão de C (tipo) valor Renato Maia 42nov/2004 Operadores de Construção n Construtor tipo (valor) n Exemplos double d = 1.23; int i = int(d); complex c = complex(d); // tipo definido na biblioteca padrão do C++ Renato Maia 43nov/2004 Operadores (observações) n Ordem de avaliação dos operandos é indefinida. int a = f() + g() // g() pode executar primeiro n Sempre use parênteses para garantir a precedência esperada. if ( (i & mask) == 0 ) // ... n Evite escrever expressões complexas e pouco legíveis. Conte com as otimizações do compilador. nov/2004 Renato Maia 44 Comandos Renato Maia 45nov/2004 Bloco de Comandos { <comando>; <comando>; <comando>; ... <comando>; } Renato Maia 46nov/2004 Comandos de Seleção n Condicional if (<expr>) <comando>; else <comando>; n Seleção switch (<expr>) { case <const>: <comandos>; break; case <const>: <comandos>; break; default: <comandos>; break; } Renato Maia 47nov/2004 Comandos de Iteração n Laço com teste no início while (<cond>) <comando>; n Laço com teste no final do <comando> while (<cond>); n Laço com contador for (<início>; <cond>; <increm>) <comando>; for (;;) { /* ... */ } // para sempre Renato Maia 48nov/2004 Comando de Salto n O famigerado goto int i; int j; for (i = 0; i<n; i++) for (j = 0; j<m; j++) if (nm[i][j] == a) goto found; // não encontrado // ... found: // nm[i][j] == a nov/2004 Renato Maia 49 Funções Renato Maia 50nov/2004 Definição extern void swap(int*, int*); // declaração void swap(int* p, int* q) // definição { int t = *p; *p = *q; *q = t; } Renato Maia 51nov/2004 Funções inline inline int fac(int n) { return (n<2) ? 1 : n*fac(n-1); } int i = f(6); è int i = 720; int i = f(6); è int i = (int n = 6, (n<2) ? 1 : ...) Renato Maia 52nov/2004 Variáveis Estáticas void f(int a) { while (a--) { static int n = 0; // iniciada uma vez int x = 0; // iniciada n vezes cout << "n == " << n++ << ", x == " << x++ << '\n'; } } n == 0, x == 0 n == 1, x == 0 n == 2, x == 0 Renato Maia 53nov/2004 Passagem de Parâmetros n Passagem por referência void increment(int& aa) { aa++; }; int x = 1; increment(x); // x == 2 n Parâmetros constantes void f(const int *p) { *p = 1; /* erro! */ } n Parâmetros anônimos void search(table* t, const char* key, const char*) { // não é possível utilizar o terceiro parâmetro } Renato Maia 54nov/2004 Constantes por Referência n Referência para valores constantes double& dr = 1; // error: não pode ser constante const double& cdr = 1; // ok: double t = double(1) ; const double& cdr = t; n Valores constantes por referência void update(float& i) ; void g(double d, float r) { update(2.0f) ; // error: argumento constante update(r) ; // passa uma referência a r update(d) ; // error: necessária conversão de tipo } Renato Maia 55nov/2004 Valor de Retorno n Retorno por referência int vet[5]; int& getcounter(int i) { return vet[i]; } getcounter(3)++; n Retorno de variáveis automáticas int* fp() { int local = 1; /* ... */ return &local; } // cuidado! int& fr() { int local = 1; /* ... */ return local; } // cuidado! Renato Maia 56nov/2004 Sobrecarga de Funções void print(double); void print(long); void f() { print(1L); // print(long) print(1.0); // print(double) print(1); // erro: ambígua, print(long(1)) or // print(double(1)) ? } Renato Maia 57nov/2004 Parâmetros Default void print(int value, int base =10); void f() { print(31) ; print(31,16) ; print(31,2) ; } n Alternativa void print(int value, int base) ; inline void print(int value) { print(value,10) ; } n Erros comuns int h(int a = 0, int b, char* c = 0) ; // erro Renato Maia 58nov/2004 Parâmetros Variáveis #include <cstdarg> void error(int severity, ...) { // "severidade" e mensagens va_list ap; va_start(ap, severity) ; // iniciação arg for (;;) { char* p = va_arg(ap,char*) ; if (p == 0) break; cerr << p << ' '; } va_end(ap) ; // limpa o conteúdo de ap cerr << '\n'; if (severity) exit(severity) ; } // error(1, "Erro", "Faltal", "Econtrado", static_cast<char*>(0)); Renato Maia 59nov/2004 Ponteiros para Funções void print(const char *s) { /* ... */ } void (*pf)(const char*); // ponteiro para função void f() { pf = print; // também: pf = &print; pf("error"); // também: (*pf)("error"); } Renato Maia 60nov/2004 Macros n Substituições simples #define PI 3.141593 n Macros razoáveis #define CASE break;case #define FOREVER for(;;) n Macros perigosas #define SQUARE(a) a * a int m = SQUARE(2 + i++) // 2 + i++ * 2 + i++ nov/2004 Renato Maia 61 Exemplo Calculadora Renato Maia 62nov/2004 Exemplo n Entrada ¨perimetro = 2 * pi * (r = 2.5) ¨area = pi * r * r n Saída ¨15.708 ¨19.635 Renato Maia 63nov/2004 Gramática da Calculadora program: END expr_list END expr_list: expression ; expression ; expr_list expression: expression + term expression - term term term: term / primary term * primary primary primary: NUMBER NAME NAME = expression - primary ( expression ) Renato Maia 64nov/2004 Tokens enum Token_value { NAME, NUMBER, END, PLUS = '+', MINUS = '-', MUL = '*', DIV = '/', PRINT = ';', ASSIGN = '=', LP = '(', RP = ')' }; Token_value curr_tok = PRINT; double number_value; string string_value; Renato Maia 65nov/2004 Leitura de Tokens Token_value get_token() { char ch = 0; do { // pula espaços em branco, exceto '\n' if(!cin.get(ch)) return curr_tok = END; } while (ch != '\n' && isspace(ch)) ; … Renato Maia 66nov/2004 Leitura de Tokens … switch (ch) { case 0: return curr_tok = END; case ';': case '\n': return curr_tok = PRINT; case '*': case '/': case '+': case '-': case '(': case ')': case '=': return curr_tok = Token_value(ch) ; … Renato Maia 67nov/2004 Leitura de Tokens … case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '.': cin.putback(ch) ; cin >> number_value; return curr_tok = NUMBER; … Renato Maia 68nov/2004 Leitura de Tokens … default: // NAME, NAME=, ou erro if (isalpha(ch)) { string_value = ch; while (cin.get(ch) && isalnum(ch)) string_value += ch ; cin.putback(ch) ; return curr_tok = NAME; } error("bad token") ; return curr_tok = PRINT; } } Renato Maia 69nov/2004 Erros double error(conststring& s) { no_of_errors++; cerr << "error: " << s << '\n'; return 1; } Renato Maia 70nov/2004 Expressão double expr(bool get) { // adiciona e subtrai double left = term(get) ; for(;;) switch (curr_tok) { case PLUS: left += term(true) ; break; case MINUS: left -= term(true) ; break; default: return left; } } Renato Maia 71nov/2004 Termo double term(bool get) { // multiplica e divide double left = prim(get) ; for (;;) switch (curr_tok) { case MUL: left *= prim(true) ; break; case DIV: if (double d = prim(true)) { left /= d; break; } return error("divide by 0") ; default: return left; } } Renato Maia 72nov/2004 Variáveis n Armazenar numa tabela que associe strings a números reais n Sugestão: usar o template 'map' da biblioteca padrão do C++ ¨std::map<string,double> table; Renato Maia 73nov/2004 Primário double prim(bool get) { // manipula primários if (get) get_token() ; switch (curr_tok) { case NUMBER: // constante real { double v = number_value; get_token() ; return v; } case NAME: { double& v = table[string_value] ; if (get_token() == ASSIGN) v = expr(true) ; return v; } … Renato Maia 74nov/2004 Primário … case MINUS: // menos unário return -prim(true) ; case LP: { double e = expr(true) ; if (curr_tok != RP) return error(") expected") ; get_token() ; // consome o ')' return e; } default: return error("primary expected") ; } } Renato Maia 75nov/2004 Função main int main(int argc, char* argv[]) { table["pi"] = 3.1415926535897932385; // constantes predefinidas table["e"] = 2.7182818284590452354; while (cin) { get_token() ; if (curr_tok == END) break; if (curr_tok == PRINT) continue; cout << expr(false) << '\n'; } return 0; } Renato Maia 76nov/2004 Exercícios 1. Compilar e executar o programa de exemplo mostrado previamente 2. Escrever um programa de encriptação que recebe um texto pela entrada padrão (cin) e devolve um texto codificado na saída padrão (cout). ¨ A codificação deve ser feita na forma c^chave[i], tal que chave é uma string dada pela linha de comando. Dessa forma quando um texto for novamente codificado com a mesma chave o texto original é recuperado. ¨ Os caracteres da chave devem ser utilizados de forma circular. ¨ Se nenhuma chave for fornecida, então nenhuma codificação deve ser feita. Renato Maia 77nov/2004 Teste do Exercício 2 n Legenda: ¨ encrypt: nome do seu programa ¨ senha: chave de criptografia ¨ input.txt: um arquivo de texto qualquer ¨ output.dat: arquivo com o texto codificado ¨ back.txt: arquivo com o texto decodificado n Comandos: C:\>encrypt senha < input.txt > output.dat C:\>encrypt senha < output.dat > back.txt nov/2004 Renato Maia 78 Espaços de Nomes Renato Maia 79nov/2004 Espaços de Nomes namespace Parser { double expr(bool) ; double prim(bool get) { /* ... */ } double term(bool get) { /* ... */ } double expr(bool get) { /* ... */ } } namespace Lexer { enum Token_value { NAME, NUMBER, END, PLUS=´+´, MINUS=´-´, MUL=´*´, DIV=´/´, PRINT=´;´, ASSIGN=´=´, LP=´(´, RP=´)´ }; Token_value curr_tok; double number_value; string string_value; Token_value get_token() { /* ... */ } } Renato Maia 80nov/2004 Nomes Qualificados double Parser::term(bool get) // note a qualificação Parser:: { double left = prim(get) ; // nenhuma qualificação necessária for (;;) switch (Lexer::curr_tok) { // note a qualificação Lexer:: case Lexer::MUL: // note a qualificação Lexer:: left *= prim(true) ; // nenhuma qualificação necessária // ... } // ... } Renato Maia 81nov/2004 Utilizando Declarações namespace Parser { double term(bool get); // ... using Lexer::curr_tok; // use o curr_tok do Lexer } double Parser::term(bool get) { double left = prim(get); for (;;) switch (curr_tok) { // qualificação Lexer:: é desnecessária case Lexer::MUL: left *= prim(true) ; // ... } // ... } Renato Maia 82nov/2004 Diretivas de Utilização namespace Parser { double term(bool get); // ... using namespace Lexer; // incorpora todas as declarações } double Parser::term(bool get) { double left = prim(get); for (;;) switch (curr_tok) { // qualificação Lexer:: é desnecessária case MUL: // qualificação Lexer:: é desnecessária left *= prim(true) ; // ... } // ... } Renato Maia 83nov/2004 Espaços de Nomes Anônimos namespace { int a; void f() { /* ... */ } int g() { /* ... */ } } /* Equivalente a: namespace $$$ { int a; void f() { /* ... */ } int g() { /* ... */ } } using namespace $$$; */ Renato Maia 84nov/2004 Alias de Espaços de Nome // nome muito longo namespace American_Telephone_and_Telegraph { /* ... */ } American_Telephone_and_Telegraph::String s3 = "Grieg"; American_Telephone_and_Telegraph::String s4 = "Nielsen"; // alias namespace ATT = American_Telephone_and_Telegraph; ATT::String s3 = "Grieg"; ATT::String s4 = "Nielsen"; Renato Maia 85nov/2004 Exercício n Dividir o programa de exemplo da calculadora em módulos (usando espaços de nomes) ¨Módulo Léxico (namespace Lexer) n Leitura e interpreção de tokens ¨Módulo Parser (namespace Parser) n Interpretação e avaliação de expressões ¨Módulo de Erros (namespace Error) n Contagem e exibição de erros nov/2004 Renato Maia 86 Compilação e Ligação Renato Maia 87nov/2004 Compilação Condicional #ifdef NDEBUG const bool ARG_CHECK = false; // desabilita verificações #else const bool ARG_CHECK = true; // habilita verificações #endif void f3(int* p) { assert(!ARG_CHECK || p!=0) ; // ou não faz verificação ou p!=0 // ... } Renato Maia 88nov/2004 Compilação em Partes lexer.cppparser.cpp error.cppmain.cpp <string><map> lexer.hparser.h error.h Renato Maia 89nov/2004 Cabeçalho do Módulo Lexer #include <string> namespace Lexer { enum Token_value { NAME, NUMBER, END, PLUS = '+', MINUS = '-', MUL = '*', DIV = '/', PRINT = ';', ASSIGN = '=', LP = '(', RP = ')' }; extern Token_value curr_tok; extern double number_value; extern std::string string_value; Token_value get_token(); } Renato Maia 90nov/2004 Módulo Lexer #include "lexer.h" #include "error.h" #include <iostream> #include <cctype> using std::cin; Lexer::Token_value Lexer::curr_tok = Lexer::PRINT; double Lexer::number_value; std::string Lexer::string_value; Lexer::Token_value Lexer::get_token() { /* ... */ } Renato Maia 91nov/2004 Guardas de Inclusão n Para evitar que um cabeçalho seja incluído diversas vezes no mesmo arquivo // error.h: #ifndef CALC_ERROR_H #define CALC_ERROR_H namespace Error { // ... } #endif // CALC_ERROR_H Renato Maia 92nov/2004 Ligação com Código C n A forma de chamada de funções C é diferente das chamadas de C++. É necessário informar ao compilador quando uma função deve ser ligada como uma função C. extern "C" void funcao_c(int, int); extern "C" { void uma_funcao_c(int, int); void outra_funcao_c(int, double); void mais_outra_funcao_c(char*); } extern "C" { #include "modulo_c.h" } Renato Maia 93nov/2004 Ponteiros para Funções C typedef int (*FT)(const void*, const void*) ; // FT tem ligação C++ extern "C" { typedef int (*CFT)(const void*, const void*) ; // CFT tem ligação C void qsort(void* p, size_t n, size_t sz,CFT cmp) ; // cmp tem ligação C } void isort(void* p, size_t n, size_t sz,FT cmp) ; // cmp tem ligação C++ void xsort(void* p, size_t n, size_t sz,CFT cmp) ; // cmp tem ligação C extern "C" void ysort(void* p, size_t n, size_t sz,FT cmp) ; // cmp tem ligação C++ int compare(const void*, const void*) ; // compare() tem ligação C++ extern "C" int ccmp(const void*, const void*) ; // ccmp() tem ligação C void f(char* v,int sz) { qsort(v,sz,1,&compare) ; // erro qsort(v,sz,1,&ccmp) ; // ok isort(v,sz,1,&compare) ; // ok isort(v,sz,1,&ccmp) ; // erro } Renato Maia 94nov/2004 Exercício n Dividir o programa de exemplo da calculadora em unidades de compilação diferentes (usando a mesma estrutura de módulos do último exercício) ¨Módulo Léxico (lexer.cpp e lexer.h) ¨Módulo Parser (parser.cpp e parser.h) ¨Módulo de Erros (error.cpp e error.h) ¨Módulo Principal (main.cpp) nov/2004 Renato Maia 95 MÓDULO II Mecanismos de Abstração Renato Maia 96nov/2004 Mecanismos de Abstração n Parte 1: ¨ Classes ¨ Objetos n Parte 2: ¨ Sobrecarga de Operadores ¨ Classes Derivadas n Parte 3: ¨ Herança Múltipla ¨ Templates n Parte 4: ¨ Exceções ¨ Informação de Tipo Dinâmica (RTTI) nov/2004 Renato Maia 97 Classes Renato Maia 98nov/2004 Classes n As classes de C++ define um novo tipo que funcionam como um tipo básico da linguagem n A forma de usar um objeto de uma classe não deve diferir do uso dos tipos básicos n A única diferença deve ser na sua criação Renato Maia 99nov/2004 Funções Membro class Date { int d,m,y; void init(int dd, int mm, int yy) ; void add_year(int n) { y += n; } void add_month(int n) { m += n; } void add_day(int n) { d += n; } }; void Date::init(int dd, int mm, int yy) { // especifica a classe a que pertence d = dd; m = mm; y = yy; } Renato Maia 100nov/2004 Controle de Acesso class Date { int d,m, y; // privado: acessível por funções membro public: // público: acessível por qualquer cliente void init(int dd, int mm, int yy) ; void add_year(int n) { y += n; } void add_month(int n) { m += n; } void add_day(int n) { d += n; } }; Renato Maia 101nov/2004 Classes e Estruturas n Estruturas são equivalentes a classes, sendo que o controle de acesso padrão é o público. struct X { // ... } Equivalente a: class X { public: // ... } Renato Maia 102nov/2004 Importância Controle Acesso n Erros que causam inconsistência de dados privados são localizados na implementação das funções membro de acesso n Alterações na implementação não são propagadas aos clientes n Simplifica a utilização da classe, pois é necessário conhecer apenas a interface pública Renato Maia 103nov/2004 Construtores class Date { int d,m, y; public: Date(int dd=0,int mm=0,int yy=0); // ... }; Date::Date(int dd, int mm, int yy) { d = dd ? dd : today.d; m = mm ? mm : today.m; y = yy ? yy : today.y; // verifica de a data é válida } n Inicição de objetos Date Date today(22) ; Date july4(4, 7, 1983) ; Date birthday(4, 12) ; Date now; Renato Maia 104nov/2004 Membros Estáticos class Date { int d,m, y; static Date today; public: Date(int dd=0,int mm=0,int yy=0); // ... static void settoday(int, int, int); }; Date Date::today(17, 11, 2004); void Date::settoday(int d,int m,int y){ today = Date(dd, mm, yy) } n Acesso a membros estáticos Date now; now.settoday(22, 11, 2004); ou Date::settoday(22, 11, 2004); Renato Maia 105nov/2004 Auto-Referência n Todo objeto tem um ponteiro implícito demominado this que aponta para o próprio objeto bool Date::is_the_same(Date& other) { return *this == other; } Renato Maia 106nov/2004 Funções Membro Constantes n Não alteram os estado do objeto class Date { int d,m, y; public: int day() const { return d++; } // erro: tentativa de alteração do estado int month() const; // ... }; inline int Date::month() const { return m; } n Podem ser chamadas a partir de referências constantes const Date my_date(12, 4, 1865); cout << my_date.day() << "/" << my_date.month() << "/" << my_date.year() Renato Maia 107nov/2004 Membros Mutáveis n Alteração de membros através de funções membro constantes string Date::string_rep() const { if (!cache_valid) { compute_cache() ; cache_valid = true; } return cache; } class Date { mutable bool cache_valid; mutable string cache; void compute_cache() const; // ... public: // ... string string_rep() const; }; Renato Maia 108nov/2004 Funções Auxiliares n É possível definir funções auxiliares para manipular objetos int diff(Date a,Date b) ; bool leapyear(int y) ; Date next_weekday(Date d) ; Date next_saturday(Date d) ; n Função membro vs. função auxiliar ¨ Função membro acessa diretamente o estado privado do objeto ¨ Função auxiliar realiza sua tarefa apenas com as operações da interface pública do objeto. Renato Maia 109nov/2004 Funções Amigas class Matrix; class Vector { float v[4] ; // ... friend Vector multiply( const Matrix&, const Vector&) ; }; class Matrix { Vector v[4] ; // ... friend Vector multiply( const Matrix&, const Vector&) ; }; n Permite acessar a interface privada das classes Vector multiply( const Matrix&m, const Vector& v ) { Vector r; for (int i = 0; i<4; i++) { // r[i] = m[i] * v; r.v[i] = 0; for (int j = 0; j<4; j++) r.v[i] +=m.v[i].v[j] * v.v[j] ; } return r; } Renato Maia 110nov/2004 Funções Amigas n Funções Membro class List_iterator { // ... int* next() ; }; class List { friend int* List_iterator::next() ; // ... }; n Classes Amigas class List { friend class List_iterator; // ... }; ¨ Todas funções membro de List_iterator se tornam amigas da classe List Renato Maia 111nov/2004 Exercício n Implementar o tipo Date, como ilustrado nos exemplos anteriores: ¨ Construtor default ¨ Definir o valor da data default n Use uma abordagem similar à função Date::settoday() ¨ Funções para acesso aos dados n Dia, mês e ano ¨ Funções para adicionar dias, meses e anos n Para simplificar, considere meses com exatos 30 dias. nov/2004 Renato Maia 112 Objetos Renato Maia 113nov/2004 Criação e Destruição n Sempre que um objeto não é mais utilizado, ele deve ser destruído n Assim como a inicialiação (ou construção) de objetos, a destruição pode ser feita automaticamente pelo compilador ou pode ser feita explicitamente Renato Maia 114nov/2004 Destrutores struct cache { bool valid; string rep; }; class Date { cache* c; void compute_cache () const; // ... public: Date(int dd=0,int mm=0,int yy=0); ~Date(); // destrutor // ... string string_rep() const; }; n Libera os recursos alocados durante a construção do objeto Date::Date(int dd,int mm,int yy) { c = new cache; c->valid = false; // ... } Date::~Date() { delete c; } Renato Maia 115nov/2004 Cópia Default n Operação de cópia default void apaga(Date *dia) { Date copia = *dia;// copia.c = dia->c; copia.d = dia->d; ... delete dia; // destrói o objeto, apaga 'c' cout << "O dia " << copia.string_rep() << "foi apagado\n"; // erro } // ... Renato Maia 116nov/2004 Variáveis Locais n Construção: ¨ Fluxo de execução encontra a declaração da variável n Destruição ¨ Variável sai do escopo n Exemplo void f(int i) { if (i>0) { Date aa; // ... } Date bb; // ... } Renato Maia 117nov/2004 Memória Dinâmica n Construção ¨ Explicitamente através do operador new Date *d = new Date(22, 11, 2004); n Destruição ¨ Explicitamente através do operador delete delete d; n Cuidados ¨ Objetos destruídos delete dia; delete dia; // erro ¨ Brechas de memória (memory leaks) void hoje() { Date *dia = new Date(); cout << "Hoje é dia " << dia.string_rep() << "\n"; } Renato Maia 118nov/2004 Membros de Classes n Construção ¨ Na construção do objeto a que pertence, na ordem que aparecem na declaração. n Destruição ¨ Na destruição do objeto o que pertence , na ordem inversa da que aparecem na declaração. n Inicialização deMembros class DaySequence { const int days; Date start; public: DaySequence(const Date& s, const int i) : days(i), start(s) { } } Renato Maia 119nov/2004 Vetores n Construção ¨ Na criação do vetor ¨ Apenas é permitido para tipos com um construtor sem parâmetros n Destruição ¨ Na destruição do vetor n Exemplo Date vds[10];// cria 10 objetos usando o construtor Date::Date() Date vdd[10] = new Date[10]; delete[] vdd; // destroy os 10 objetos do vetor Renato Maia 120nov/2004 Variáveis Locais Estáticas n Construção ¨ Fluxo de execução encontra a declaração da variável pela primeira vez. n Destruição ¨ Termino do programa n Exemplo // Declaração das variáveis // Construção dos objetos void f(int i) { f(0); // d1 é construído static Date d1; f(1); // apenas o d2 é contruído // ... f(2); // nenhum dos objetos é criado if (i) { static Date d2; // ... } } Renato Maia 121nov/2004 Não Locais n Variáveis não locais: ¨ Variáveis globais ¨ Variáveis em espaços de nomes ¨ Variáveis estáticas de classe n Construção ¨ Antes no início da função main ¨ Na ordem que suas definições aparecem n Destruição ¨ Após o término da função main ¨ Na ordem inversa que suas definições aparecem n Exemplo class X { static Date memdate; }; // apenas a definição do membro estático Date date; // declaração de variável global Date X::memdate; // declaração do membro estático da classe X namespace Z { Date date2; } // delaração da varíavel no espaço de nomes Renato Maia 122nov/2004 Objetos Temporários n Construção ¨ Na avaliação da expressão que os criam n Destruição ¨ Ao final da avaliação da expressão que os criam n Exemplo void f(string& s1, string& s2, string& s3) { const char* cs= (s1+s2).c_str() ; cout << cs; // problema: cs aponta para uma área desalocada if (strlen(cs=(s2+s3).c_str())<8 && cs[0]==´a´) { // ok // qualquer uso de cs aqui é inválido } } Renato Maia 123nov/2004 Exercício n Implementar o tipo Table, que deve oferecer a seguinte interface: struct Name { enum Gender { male, female } const char* s; Gender g; }; class Table { Name* p; size_t sz; int c; public: Table(size_t s = 15); ~Table(); Name* lookup(const char *) ; bool insert(Name&) ; }; nov/2004 Renato Maia 124 Sobrecarga de Operadores Renato Maia 125nov/2004 Operadores Disponíveis n Operadores que podem ser redefinidos +- * / % ^ & | ~ ! = < > += -= *= /= %= ^= &= |= << >> >>= <<= == != <= >= && || ++ -- ->* , -> [] () new new[] delete delete[] n Operadores que NÃO podem ser redefinidos :: (Resolução de escopo) . (Seleção de membros) .* (Seleção de membros através de ponteiros para função) Renato Maia 126nov/2004 Funções Operadoras n Função Membro class complex { double re, im; public: complex(double r, double i=0) : re(r) , im(i) { } complex operator+(complex) ; }; n Função Auxiliar complex operator+(complex, double) ; Renato Maia 127nov/2004 Casamento de Função Operador n Escolha da função operador para um operador @ ¨Operadores Binários (a@b) a.operator@(b) ou ::operator@(a, b) ¨Operadores Unários (a@) a.operator@() ou ::operator@(a) Renato Maia 128nov/2004 Exemplos de Sobrecarga de Operadores class X { // members (with implicit 'this' pointer): X* operator&() ; // & unário (endereço de) X operator&(X) ; // & binário (e bit a bit) X operator++() ; // incremento prefixo X operator&(X,X) ; // erro: ternário X operator/() ; // erro: / unário }; // nonmember functions: X operator-(X) ; // menos unário X operator-(X,X) ; // menos binário X operator--(X&,int) ; // decremento posfixo X operator-(); // erro: nenhum operando X operator-(X,X,X) ; // erro: ternário X operator%(X) ; // erro: % unário Renato Maia 129nov/2004 Significados Predefinidos n As funções operator=, operator[], operator() e operator-> devem ser definidas como funções membro não estáticas n Apenas alguns operadores já possuem um significado predefinido = (atribuição, faz cópia dos valores dos membros) & (endereço de, retorna o endereço do objeto) , (seqüência, retorna o valor do segundo parâmetro) n Entretanto, esses significados podem ser redefinidos através da sobrecarga de operadores Renato Maia 130nov/2004 Cópia de Objetos n Construtor de cópia Date::Date(const Date& other) { // exemplo: c = new cache; // Date copia = data; c->valid = false; d = other.d; m = other.m; y = other.y; } n Operador de atribuição Date::operator=(const Date& other) { // exemplo: if (*this != other) { // Date copia(2, 4, 1876); delete c; // copia = data; c = new cache; c->valid = false; d = other.d; m = other.m; y = other.y; } } Renato Maia 131nov/2004 Procura pela Implementação de Operadores n Considere a expressão x@y, (x é do tipo X e y é do tipo Y) ¨ Se X é uma classe e define operator@ como um membro essa função membro como operadora ¨ Caso contrário n Procura por declarações de operator@ no contexto de x@y n Adicinonalmente, se X é definido num espaço de nomes N, procura por declarações de @ em N n Adicinonalmente, se Y é definido num espaço de nomes M, procura por declarações de @ em M. Neste último caso, todas as declarações de operator@ são levadas em consideração para determinar a que se adequa a expressão. n As mesmas regras para casamento de funções sobrecarregadas são aplicadas a operadores. Renato Maia 132nov/2004 Conversões Implícitas bool operator==(complex,complex) ; void f(complex x, complex y) { x==y; // significa operator==(x,y) x==3; // significa operator==(x,complex(3)) 3==y; // significa operator==(complex(3),y) } n Essas conversão não se aplicam para funções operadoras membro Renato Maia 133nov/2004 Operadores de Conversão Explícita class Tiny { char v; void assign(int i) { if (i&~077) v=0; else v=i; } public: Tiny(int i) { assign(i) ; } Tiny& operator=(int i) { assign(i) ; return *this; } operator int() const { return v; } // conversão para int }; n Atenção Tiny::operator int() const { return v; } // certo int Tiny::operator int() const { return v; } // errado Renato Maia 134nov/2004 Ambigüidades n Sempre que a combinação de construtores e operadores de conversão gerarem ambiguidade na resolução de funções sobrecarregadas, o compilador informará o erro. n Tome cuidado com conversões inesperadas (ou a falta delas) class Quad { public: Quad(double) ; // ... }; Quad operator+(Quad,Quad) ; void f(double a1, double a2) { Quad r1 = a1+a2; // adição com precisão dupla Quad r2 =Quad(a1)+a2; // força aritmética da classe quad } Renato Maia 135nov/2004 Construtores Explícitos n Considere complex z = 2; // inicializa z com complex(2) String s = 'a'; // cria uma string com int('a') elementos n Solução class String { // ... explicit String(int n) ; // prealoca n bytes String(const char* p) ; // valor inicial é uma string C string p }; Renato Maia 136nov/2004 Operador de Indexação class Assoc { struct Pair { string name; double val; Pair(string n ="", double v =0) :name(n) , val(v) { } }; vector<Pair> vec; // privado para prevenir cópia Assoc(const Assoc&) ; Assoc& operator=(const Assoc&) ; public: Assoc() {} double& operator[](const string&) ; void print_all() const; }; double& Assoc::operator[](const string& s) { vector<Pair>::iterator p=vec.begin(); for (; p!=vec.end(); ++p) if (s == p->name) return p->val; vec.push_back(Pair(s,0)) ; return vec.back().val; } void Assoc::print_all() const { vector<Pair>::const_iterator p=vec.begin(); for (; p!=vec.end(); ++p) cout << p->name << ": " << p->val << ´\n´; } Renato Maia 137nov/2004 Operador de Chamada de Função class Add { complex val; public: Add(complex c) { val= c; } // salva o valor Add(double r, double i) { val = complex(r,i) ; } void operator()(complex& c) const { c += val; } // adiciona valor }; complex vc[10]; void for_each(Add& func) { for (int i = 0; i < 10; i++) func(vc[i]); } void main() { Add func(2, 3); for_each(func); } Renato Maia 138nov/2004 Operador de Dereferência n Declaração (operador unário) class Ptr { /* ... */ X* operator->(); }; n Transformação void f(Ptr p) { p->m = 7; // (p.operator–>())–>m = 7 } n Uso void g(Ptr p) { X* q1 = p->; // erro de sintaxe X* q2 = p.operator->();// ok } Renato Maia 139nov/2004 Operadores Unários Posfixos class Ptr_to_T { T* p; T* array; int size; public: Ptr_to_T(T* p, T* v, int s) ; // associa a pos. p do vetor v de tam. s Ptr_to_T& operator++() ; // prefixo Ptr_to_T operator++(int) ; // posfixo Ptr_to_T& operator--(); // prefixo Ptr_to_T operator--(int) ; // posfixo T&operator*() ; // prefixo }; nov/2004 Renato Maia 140 Classes Derivadas Renato Maia 141nov/2004 Classes Derivadas class Employee { string name; Date hiring_date; shot department; // ... public: void print() const; string get_name() const { return name; } // ... }; class Manager : public Employee { set<Employee*> group; short level; // ... public: void print() const; // ... }; Renato Maia 142nov/2004 Estrutura de Objetos Employee: name department ... name department ... group level ... Manager: Renato Maia 143nov/2004 Polimorfismo void f(Manager m1, Employee e1) { list<Employee*> elist; elist.push_front(&m1); elist.push_front(&e1); } void g(Manager mm, Employee ee) { Employee* pe= &mm; // ok: todo Gerente é um Empregado Manager* pm= ⅇ // erro: nem todo Empregado é um Gerente pm->level = 2; // desastre: ee não tem um 'level' pm = static_cast<Manager*>(pe) ; // força bruta, mas funciona pm->level = 2; // ok: pm aponta para mm que tem um 'level' } Renato Maia 144nov/2004 Implement. de Funções Membro n Não é possível acessar membros privados em classes derivadas void Manager::print() const { cout << "Name: "<< name << '\n'; // erro: name é privado cout << "\tDept:\t"<< department << '\n'; // erro: department é privado cout << "\tLevel:\t" << level << '\n'; cout << "\tTeam:\t" << group.size() << '\n'; } n É necessário usar a interface pública (e protegida, i.e. protected) void Manager::print() const { Employee::print(); // cuidado: print() não qualificado causa recursão cout << "\tLevel:\t" << level << '\n'; cout << "\tTeam:\t" << group.size() << '\n'; } Renato Maia 145nov/2004 Controle de Acesso n Escopo Privado (private) ¨ Nomes podem ser usados em funções membro e funções amigas da classe. n Escopo Protegido (protected) ¨ Nomes podem ser usados em funções membro e funções amigas da classe e nas funções membro e funções amigas das suas classes derivadas. n Escopo Público (public) ¨ Nomes podem ser usados em quaisquer funções. Renato Maia 146nov/2004 Acesso a Membros Herdados n class X : public B { /* ... */ }; ¨ Acesso aos membros públicos e protegidos de B e conversão de X* para B* só pode ser feito em funções membro e amigas de X. n class Y : protected B { /* ... */ }; ¨ Acesso aos membros públicos e protegidos de B e conversão de Y* para B* só pode ser feito em funções membro e amigas de Y e de suas classes derivadas. n class Z : private B { /* ... */ }; ¨ Acesso aos membros públicos de B e conversão de Z* para B* só pode ser feito pode ser feito de qualquer função. Adicionalmente, o acesso aos membros protegidos de B só pode ser feito em funções membro e amigas de Z e de suas classes derivadas. Renato Maia 147nov/2004 Construção n Classe Base Employee(const string& n, int d) : name(n), department(d) { // … } n Classe Derivada Manager(const string& n, int d, int lvl) : Employee(n, d), level(lvl) // não é possível iniciar diretamente // os membros de Employee { // … } Renato Maia 148nov/2004 Cópia Fatiada n Exemplo void f(const Manager& m) { Employee e = m; // constrói e a partir da parte Employee de m e = m; // atribui a parte Employee de m a e } n Cuidado void slice_copy(Employee ee) { ee.print(); } // ... Manager m("John Gee", 1, 4); slice_copy(m); // objeto Employee criado com os dados de m Renato Maia 149nov/2004 Funções Virtuais n Definição class Employee { // ... virtual void print() const; }; n Exemplo void virtual_call(Employee* ee) { ee->print(); // a função print adequada é chamada } // ... Manager m("John Gee", 1, 4); virtual_call(&m); Renato Maia 150nov/2004 Classes Abstratas n Permite definir classes com funções sem implementação class Shape { public: // funções virtuais puras virtual void rotate(int) = 0; virtual void draw() = 0; virtual bool is_closed() = 0; // ... }; n Não é possível criar objetos de classes abstratas Shape s; // erro: Shape é abstrata n Classes abstratas somente são utilizadas como classe base class Point { /* ... */ }; class Circle : public Shape { public: // define funções virtuais herdadas void rotate(int) { } void draw() ; bool is_closed() { return true; } Circle(Point p, int r) ; private: Point center; int radius; }; Renato Maia 151nov/2004 Ponteiros para Membros struct Class { const char* memb_data; virtual void memb_func() = 0; }; typedef void (Class::*PMF)() ; // tipo ponteiro para função membro typedef const char* Class::*PMD; // tipo ponteiro para membro de dado void f(Class* p) { PMF pmf = &Class::memb_func(); p->memb_func() ; // chamada direta (p->*pmf)() ; // chamada através de ponteiro para membro PMD pmd = &Class::memb_data; p->memb_data() ; // acesso direto p->*pmd = "string" ; // acesso através de ponteiro para membro } Renato Maia 152nov/2004 Propósito de Classes Concretas n Classes concretas são usadas para definir novos tipo (e.g. classe Date) que façam tarefas simples e de forma eficiente. n Se o comportamento de uma classe concreta não é adequado, uma nova classe deve ser construída. Se possível utilizando a classe concreta, da mesma forma se utiliza um int na classe Date. n Sempre tente definir um bom conjunto de tipos como base da sua aplicação e defina esses tipos através de classes concretas nov/2004 Renato Maia 153 Herança Múltipla Renato Maia 154nov/2004 Problema n Suponha um sistema de simulação onde cada elemento simulado realiza uma tarefa e possui uma representação visual dessa tarefa. n Cada elemento tem o comportamento de uma tarefa e de algo visual. n Definimos duas classes: ¨ Task: define o comportamento relativo a execução de uma tarefa ¨ Displayed: define o comportamento relativo a exibição visual de informações Renato Maia 155nov/2004 Solução com Herança Múltipla n Para cada elemento simulado a sua repesentação visual (Displayed) é muito dependente da sua tarefa (Task). n A implementação da simulação de um satélite pode ser feita numa única classe que herde as interfaces e implementações fornecidas pelas classes Task e Displayed. Task dados funções Displayed dados funções Satellite dados funções Renato Maia 156nov/2004 Herança Múltipla n Classe com herança múltipla class Satellite : public Task, public Displayed { // ... }; n É possível acessar membros das duas classes base void f(Satellite& s) { s.draw() ; // Displayed::draw() s.delay(10) ; // Task::delay() s.transmit() ; // Satellite::transmit() } Renato Maia 157nov/2004 Herança Múltipla n Objetos de classes com herança múltipla de comportam como um objeto de cada classe base void highlight(Displayed*) ; void suspend(Task*) ; voidg(Satellite* p) { highlight(p) ; // passa um ponteiro para a parte Displayed suspend(p) ; // passa um ponteiro para a parte Task } Renato Maia 158nov/2004 Resolução de Ambigüidade class Task { // ... virtual debug_info* get_debug() ; }; class Displayed { // ... virtual debug_info* get_debug() ; }; void f(Satellite* sp) { debug_info* dip = sp->get_debug() ; // erro: ambíguo dip = sp->Task::get_debug() ; // ok dip = sp->Displayed::get_debug() ; // ok } Renato Maia 159nov/2004 Redefinição de Membros n Definir na classe derivada o comportamento adequado class Satellite : public Task, public Displayed { // ... debug_info* get_debug() // defefine Task::get_debug() e // Displayed::get_debug() { debug_info* dip1 = Task::get_debug() ; debug_info* dip2 = Displayed::get_debug() ; return dip1->merge(dip2) ; } }; Renato Maia 160nov/2004 Classes Base Duplicadas struct Link { Link* next; }; class Task : public Link { // o Link é usado para manter // a lista de todas Tasks. // ... }; class Displayed : public Link { // o Link é usado para manter // a lista de todos Displayed. // ... }; Task dados funções Displayed dados funções Satellite dados funções Link dados funções Link dados funções Renato Maia 161nov/2004 Classes Base Duplicadas n Atenção: void insert_before(Satellite* s, Task* t, Displayed* d) { s->next = t.next; // erro: ambíguo s->Task::next = t.next; s->Displayed::next = d.next; t.next = s; d.next = s; } Renato Maia 162nov/2004 Classes Base Virtuais n Classes base virtuais não são duplicadas quando herdadas class Task : public virtual Link { // ... }; class Displayed : public virtual Link { // ... }; Task dados funções Displayed dados funções Satellite dados funções Link dados funções Renato Maia 163nov/2004 Controle de Acesso struct B { int m; // ... }; class D1 : public virtual B { /* ... */ } ; class D2 : public virtual B { /* ... */ } ; class DD : public D1, private D2 { /* ... */ }; DD* pd = new DD; B* pb = pd; // ok: accessível através de D1 int i1 = pd->m; // ok: accessível através de D1 Renato Maia 164nov/2004 Usando Herança Múltipla n Múltiplas interfaces ¨ Compor uma classe com uma interface composta da interface de duas outras classes. n Classes intimamente dependentes ¨ Reduzir o uso de funções amigas juntando a implementação de duas classes intimamente dependentes numa única. n Reutilização de código ¨ Permitir compor uma nova classe a partir da implementação de outras nov/2004 Renato Maia 165 Templates Renato Maia 166nov/2004 Declaração template<class C> class String { struct Srep; Srep *rep; public: String(); String(const C*); String(const String&); C read(int i) const; // ... }; Renato Maia 167nov/2004 Definição template<class C> struct String<C>::Srep { C* s; // ponteiro para elementos int sz; // número de elementos // ... }; template<class C> C String<C>::read(int i) const { return rep->s[i] ; } template<class C> String<C>::String() { p = new Srep(0,C()) ; } Renato Maia 168nov/2004 Instanciação n Versão com char int main() { String<char> buf; map<String<char>,int> m; while (cin>>buf) m[buf]++; // escreve o resultado } n Versão com Jchar (tipo fictício para representar caracteres japoneses) int main() { String<Jchar> buf; map<String<Jchar>,int> m; while (cin>>buf) m[buf]++; // escreve o resultado } Renato Maia 169nov/2004 Parâmetros n Um tipo template<class C> class String { /* … */ } n Uma constante de um tipo básico (int, double, etc.) template<class T, int i> class Buffer { T v[i]; int sz; /* … */ } n Outros templates template<class T, template<class> class C> class Xrefd { C<T> mems; C<T*> refs; // ... }; Xrefd<Entry,vector> x1; Renato Maia 170nov/2004 Equivalência de Tipos n Considere ¨ String<char> s1; ¨ String<unsigned char> s2; ¨ typedef unsigned char Uchar; ¨ String<Uchar> s3; ¨ String<char> s4; ¨ Buffer<char, 10> b2; ¨ Buffer<char, 20-10> b3; // o compilador pode avaliar expressões constantes. n As seguintes variáveis são do mesmo tipo ¨ s1 ó s4 ¨ s2 ó s3 ¨ b1 ó b2 Renato Maia 171nov/2004 Corretude do Template template<class T> class List { struct Link { Link* suc; T val; Link(Link* s, const T& v) : suc(s) , val(v) { } } // erro de sintaxe: faltando um ponto e vírgula Link* head; public: List() : head(7) { } // erro: ponteiro inicializado com int void print_all() { for (Link* p = head; p; p=p->suc) cout << p->val << '\n'; } }; void f(List<int>& li, List<Rec>& lr) { li.print_all() ; // ok lr.print_all() ; // erro: se Rec não define o operador << } Renato Maia 172nov/2004 Template de Funções template<class T> void sort(vector<T>& v) { // Shell sort (Knuth, Vol. 3, pg. 84). const size_t n = v.size() ; for (int gap=n/2; 0<gap; gap/=2) for (int i=gap; i<n; i++) for (int j=i-gap; 0<=j; j-=gap) if (v[j+gap]<v[j]) swap(v[j], v[j+gap]); } void f(vector<int>& vi, vector<string>& vs) { sort(vi) ; // sort(vector<int>&); sort(vs) ; // sort(vector<string>&); } Renato Maia 173nov/2004 Definição dos Parâmetros de Uma Função Template template<class T, class U> T implicit_cast(U u) { return u; } void g(int i) { implicit_cast(i) ; // error: não pode deduzir T implicit_cast<double>(i) ; // T é double; U is int implicit_cast<char, double>(i) ; // T é char; U is double implicit_cast<char*, int>(i) ; // T é char*; U é int; erro } Renato Maia 174nov/2004 Parâmetros Default template<class T = int, class U> T implicit_cast(U u) { return u; } void g(int i) { implicit_cast(i) ; // T é int; U is int implicit_cast<double>(i) ; // T é double; U is int implicit_cast<char, double>(i) ; // T é char; U is double implicit_cast<char*, int>(i) ; // T é char*; U é int; erro } Renato Maia 175nov/2004 Especializações template<class T> class Vector<T*> : private Vector<void*> { public: typedef Vector<void*> Base; Vector() : Base() {} explicit Vector(int i) : Base(i) {} T*& elem(int i) { return static_cast<T*&>(Base::elem(i)) ; } T*& operator[](int i) { return static_cast<T*&>(Base::operator[](i)) ; } // ... }; Vector<Shape*> vps; Vector<char*> vpc; Vector<Node*> vpn; Renato Maia 176nov/2004 Templates e Herança class Shape { /* ... */ }; class Circle : public Shape { /* ... */ }; class Triangle : public Shape { /* ... */ }; void f(set<Shape*>& s) { // ... s.insert(new Triangle()) ; // ... } void g(set<Circle*>& s) { f(s) ; // erro, s é um set<Circle*>, não um set<Shape*> } nov/2004 Renato Maia 177 Exceções Renato Maia 178nov/2004 Lançamento struct Range_error { int i; Range_error(int ii) { i = ii; } }; char to_char(int i) { if (i<numeric_limits<char>::min() || numeric_limits<char>::max()<i) throw Range_Error(); return c; } Renato Maia 179nov/2004 Captura void g(int i) { try { char c = to_char(i) ; // ... } catch (Range_error) { cerr << "oops\n"; } } Renato Maia 180nov/2004 Hierarquia de Exceções class Matherr{ }; class Overflow: public Matherr{ }; class Underflow: public Matherr{ }; class Zerodivide: public Matherr{ }; void f() { try { /* ... */ } catch (Overflow) { // trata Overflow ou qualquer coisa que derive de Overflow } catch (Matherr) { // trata qualquer Matherr que são seja Overflow } } Renato Maia 181nov/2004 Re-Lançamento void h() { try { // código que pode lançar exceções Matherr } catch (Matherr) { if (pode_tratar_completamente) { // trata Matherr } else throw; // re-lança a exceção } } Renato Maia 182nov/2004 Captura de Qualquer Exceçãovoid m() { try { // faz algo } catch (...) { // trata qualquer exceção // limpeza throw; } } Renato Maia 183nov/2004 Ordem de Captura void g() { try { /* ... */ } catch (...) { // trata qualquer exceção } catch (std::exception& e) { // trata qualquer exceção da biblioteca padrão } catch (std::bad_cast) { // trata erros de conversão dinâmica } } Renato Maia 184nov/2004 Exceções em Construtores class Vector { public: class Size{ }; enum {max = 32000 }; Vector::Vector(int sz) { if (sz<0 ||max<sz) throw Size() ; // ... } // ... }; Vector* f(int i) { try { Vector* p = new Vector(i) ; // ... return p; } catch(Vector::Size) { // lida com erro de tamanho } } Renato Maia 185nov/2004 Exceções na Iniciação de Membros class X { Vector v; // ... public: X(int) ; // ... }; X::X(int s) try :v(s) // iniciação de v por s { // corpo do construtor } // captura de exceções lançadas por v catch (Vector::Size) { // ... } Renato Maia 186nov/2004 Exceções em Destrutores n Durante o lançamento de uma exceção os objetos que perdem seu escopo são destruídos n Exceções lançadas por destrutores durante o lançamento de uma exceção causam o encerramento do programa n Para evitar essa situação usa-se a função da biblioteca padrão uncaught_exception X::~X() try { f(); } catch (...) { if (uncaught_exception()) { // faça algo else throw; // re-lança } Renato Maia 187nov/2004 Especificação de Exceções void f() throw (x2, x3) { /* ... */ } n Equivalente a: void f() try { /* ... */ } catch (x2) { throw; } catch (x3) { throw; } catch (...) { std::unexpected() ; // encerra a aplicação } Renato Maia 188nov/2004 Exceções Não Capturadas n Exceções não especificadas resultam na chamada de std::unexpected, que chama um tratador definido pela seguinte função: ¨ typedef void (*unexpected_handler)() ; ¨ unexpected_handler set_unexpected(unexpected_handler) ; n Exceções não capturadas resultam na chamada de std::terminate, que chama um tratador definido pela seguinte função: ¨ typedef void (*terminate_handler)() ; ¨ terminate_handler set_terminate(terminate_handler) ; Renato Maia 189nov/2004 Exceções Padrão n Lançadas pela linguagem bad_alloc lançada pelo operador new bad_cast lançada pelo operador dynamic_cast bad_typeid lançada pelo operador typeid bad_exception lançada por uma função com especificação de exceções n Lançadas pela bibioteca padrão exception logic_error runtime_error length_error domain_error out_of_range invalid_argument range_error overflow_error underflow_error out_of_range bad_cast bad_typeid bad_alloc bad_exception nov/2004 Renato Maia 190 Run-Time Type Information (RTTI) Renato Maia 191nov/2004 Exemplo class Component : public virtual Storable { /* ... */ }; class Receiver : public Component { /* ... */ }; class Transmitter : public Component { /* ... */ }; class Radio : public Receiver, public Transmitter { /* ... */ }; Component Component Radio Storable Receiver Transmisser Renato Maia 192nov/2004 Conversão Dinâmica void echo_handler(Receiver* pr) { // pw aponta para um Transmitter? if (Transmitter* pt = dynamic_cast<Transmitter*>(pr)) pt->send(pr->receive()) ; else { // Opa! Não é possível ecoar } } Renato Maia 193nov/2004 Classes Não-Polimórficas class My_storable: public Storable { // ... // base polimórfica (tem funções virtuais) }; class My_date : public Date { // ... // base não polimórfica (não tem funções virtuais) }; void g(Storable* pb, Date* pd) { My_storable* pd1 = dynamic_cast<Storable*>(pb) ; // ok My_date* pd2 = dynamic_cast<My_date*>(pd) ; // erro: Date não // é polimórfica } Renato Maia 194nov/2004 Conversão de Referências n O operador dynamic_cast em referências lança a exceção bad_cast try { Transmitter& t = dynamic_cast<Transmitter&>(r); t.send(r.receive()); } catch (bad_cast){ /* ... */ } Renato Maia 195nov/2004 Ambigüidades n Objetos da classe Radio são compostos por dois objetos Component (de Receiver e Transmitter) void h1(Radio& r) { Storable* ps = &r; // ... Component* pc = dynamic_cast<Component*>(ps) ; // pc = 0 } Renato Maia 196nov/2004 Navegando na Hierarquia de Classes void g(Radio& r) { Receiver* prec= &r; // Receiver é uma base de Radio Radio* pr = static_cast<Radio*>(prec) ; // ok, sem verificação pr = dynamic_cast<Radio*>(prec) ; // ok, verificação dinâmica Storable* ps= &r; // Storable é base virtual pr = static_cast<Radio*>(ps) ; // erro: conversão de base virtual pr = dynamic_cast<Radio*>(ps) ; // ok, verificação dinâmica } Renato Maia 197nov/2004 Construção e Destruição de Objetos n Durante a construção ou destruição de um objeto, apenas parte dele existe ¨ Na execução do construtor da classe Receiver para um objeto Radio o objeto Radio ainda não existe completamente. ¨ É bom evitar chamar funções virtuais na construção ou destruição de objetos, pois pode ocasionar a chamada da função da classe sendo construída, mesmo que seja a criação de um objeto de uma classe derivada. Renato Maia 198nov/2004 Operador typeid n Pseudo declaração class type_info; const type_info& typeid(type_name) throw(bad_typeid) ; const type_info& typeid(expression) ; . Renato Maia 199nov/2004 Informações de Tipo class type_info { public: virtual ~type_info() ; // é polimórfico bool operator== (const type_info&) const; // pode ser comparado bool operator!= (const type_info&) const; bool before(const type_info&) const; // ordem const char* name() const; // nome do tipo private: type_info(const type_info&) ; // evita cópia type_info& operator=(const type_info&) ; // evita cópia // ... }; Renato Maia 200nov/2004 Mal Uso do RTTI n Programadores de linguagems procedurais ¨ C, Pascal, Modula-2 e Ada void rotate(const Shape& r) { if (typeid(r) == typeid(Circle)) { // do nothing } else if (typeid(r) == typeid(Triangle)) { // rotate triangle } else if (typeid(r) == typeid(Square)) { // rotate square } // ... } Renato Maia 201nov/2004 Mal Uso do RTTI n Programadores de linguagens altamente dependentes de verificação dinâmica de tipos ¨ Smaltalk, Lisp, Java(?) class Object{ /* ... */ }; // polimórfico class Container : public Object { public: void put(Object*) ; Object* get() ; // ... }; class Ship : public Object{ /* ... */ }; Ship* f(Ship* ps,Container* c) { c->put(ps) ; // ... Object* p = c->get() ; if (Ship* q=dynamic_cast<Ship*>(p)) { return q; } else { // faça algo (lança um erro) } } nov/2004 Renato Maia 202 MODULO III Biblioteca Padrão Renato Maia 203nov/2004 Biblioteca Padrão n Parte 1: ¨ Visão Geral ¨ Contêiners n Parte 2: ¨ Iteradores ¨ Algoritmos ¨ Objetos Função n Parte 3: ¨ Strings ¨ Streams nov/2004 Renato Maia 204 Visão Geral Renato Maia 205nov/2004 Organização n Contêiners ¨ Estruturas de dados n Utilidades ¨ Operadores, pares, objetos função, alocadores, etc. n Iteradores n Algoritmos ¨ Busca, ordenação, etc. n Diagnóstico ¨ Exceções, assetivas, etc. n Strings n I/O ¨ Streams, buffers, arquivos, etc. n Localização ¨ Configurações regionais n Suporte C++ ¨ Limites numéricos, RTTI, etc. n Numérica ¨ Complexos, operações sobre vetores e matrizes, etc. Renato Maia 206nov/2004 Standart Template Library Contêiners (estruturas de dados) Algoritmos (operações) Iteradores (acesso genérico) nov/2004 Renato Maia 207 Contêiners Renato Maia 208nov/2004 Operações Comuns template <class T, class A =allocator<T> > class std: :vector { public: // Tipos typedef T value_type; typedef A allocator_type; typedef typename A::size_type size_type; typedef typename A::difference_type difference_type; typedef /* DEP. DE IMPLEMENT. */ iterator; // algo como um T* typedef /* DEP. DE IMPLEMENT. */ const_iterator; // +/- const T* typedef std::reverse_iterator<iterator> reverse_iterator; typedef std::reverse_iterator<const_iterator> const_reverse_iterator; typedef typename A::pointer pointer; // para elemento typedef typename A::const_pointer const_pointer; typedef typename A::reference reference; // de elemento typedef typename A::const_reference const_reference; ... Renato Maia 209nov/2004 Operações Comuns (cont) template <class T, class A = allocator<T> > class vector { public: // ... // iteratores: iterator begin() ; // aponta para o primeiro const_iterator begin() const; iterator end() ; // aponta para um após o último const_iterator end() const; reverse_iterator rbegin() ;// aponta para o último const_reverse_iterator rbegin() const; reverse_iterator rend() ; // aponta para um antes do primeiro element of reverse sequence const_reverse_iterator rend() const ; // ... }; Renato Maia 210nov/2004 Programação Genérica template<class C> typename C::value_type sum(const C& c) { typename C::value_type s = 0; typename C::const_iterator p = c.begin() ; // começa do começo while (p!=c.end()) { // continue até o fim s += *p; // pega um valor ++p; // faça p apontar para o próximo elemento } return s; } Renato Maia 211nov/2004 Características Comuns n Tipos parametrizados ¨ value_type Tipo dos elementos ¨ allocator_type Tipo do alocador usado n Tipos de iteradores ¨ iterator Tipo do iterador ¨ const_iterator Tipo do iterador constante ¨ reverse_iterator Tipo do iterador reverso ¨ const_reverse_iterator Tipo do iterador reverso constante n Tipos ponteiro e referência ¨ pointer Tipo ponteiro para o elemento ¨ const_pointer Tipo ponteiro constante para o elemento ¨ reference Tipo referência para o elemento ¨ const_reference Tipo referência constante para o elemento Renato Maia 212nov/2004 Características Comuns n Criação e destruição ¨ Construtor default Cria o contêiner vazio ¨ Construtor de cópia Copia um contêiner de mesmo tipo ¨ Construtor(begin, end) Cria um contêiner e copia em [begin, end[ ¨ Destrutor Apaga todos os elementos e libera a memória n Comparação ¨ == Verifica se o conteúdo é igual ¨ != Verifica se o conteúdo não é igual ¨ < Verifica se o conteúdo é lexicograficamente menor ¨ > Verifica se o conteúdo é lexicograficamente maior ¨ <= Verifica se o conteúdo é lexicograficamente menor ou igual ¨ >= Verifica se o conteúdo é lexicograficamente maior ou igual ¨ = Atribui o conteúdo de outro contêiner Renato Maia 213nov/2004 Características Comuns n Acesso ¨ size() Devolve o número de elementos ¨ empty() Verifica se o contêiner está vazio ¨ max_size() Devolve o número máximo de elementos ¨ begin() Iterador para o início ¨ end() Iterador para um após o fim ¨ rbegin() Iterador para o início da iteração reversa ¨ rend() Iterador para um após o fim da iteração reversa n Alteração ¨ swap(c) Troca o conteúdo com outro contêiner (::swap(c,c)) ¨ insert(pos,elem) Insere uma cópia de elem (significado de pos varia) ¨ erase(beg,end) Remove todos os elementos em [beg,end[ ¨ clear() Remove todos os elementos Renato Maia 214nov/2004 Requisitos dos Elementos n Cópia ¨ Os elementos devem poder ser copiados, pois os contêiners guardam cópias de elementos. n Comparação ¨ Containers associativos fazem comparação dos elementos nas buscas (< e =) n O que acontece no código abaixo? std::map<char*,int> map; char name[] = "Renato"; map[name] = 11; cout << map["Renato"] << '\n'; Renato Maia 215nov/2004 Contêiner Vetor n seqüência de elementos para acesso aleatório ¨ J Acesso aleatório ¨ L Alterações no meio ou no início n Cabeçalho ¨ #include <vector> n Parâmetros ¨ Tipo dos elementos armazenados ¨ Tipo do gerenciador de memória (opcional) n Exemplos ¨ vector<int> vi; ¨ vector<MyClass> vobj; ¨ vector<vector<string> > mtrstr; Renato Maia 216nov/2004 Operações do Contêiner Vetor n Construtores ¨ vector(n) n posições com valor default ¨ vector(n,val) n posições com valor val n Atribuição ¨ assign(beg, end) Atribui um vetor com os valores de [beg,end[ ¨ assign(n,val) Atribui um vetor com n cópias de val n Acesso ¨ [pos] Indexação sem verificação ¨ at(pos) Indexação com verificação ¨ front() Primeiro elemento ¨ back() Último elemento Renato Maia 217nov/2004 Operações do Contêiner Vetor n Capacidade ¨ capacity() Tamanho de posições alocadas ¨ reserve(n) Reserva espaço para um total de n elemetos n Tamanho ¨ resize(n) Altera o número de elementos ¨ resize(n,val) Idem, val define o valor de inicialização n Alteração no final ¨ push_back(val) Adiciona ao final ¨ pop_back() Remove o último elemento n Alteração na seqüência ¨ insert(pos,val) Insere cópia de val antes de pos ¨ insert(pos,n,val) Insere n cópias de val antes de pos ¨ insert(pos,beg, end) Insere os valores de [beg,end[ antes de pos ¨ erase(pos) Apaga elemento em p Renato Maia 218nov/2004 Contêiner Lista n seqüência de elementos para acesso seqüêncial ¨ J Alterações na ordem dos elementos ¨ J Inserções em quaisquer pontos da seqüência ¨ L Acesso aleatório n Cabeçalho ¨ #include <list> n Parâmetros ¨ Tipo dos elementos armazenados ¨ Tipo do gerenciador de memória (opcional) n Exemplos ¨ list<int> li; ¨ list<MyClass> lobj; ¨ list<vector<string> > lvet; Renato Maia 219nov/2004 Operações do Contêiner Lista n Construtores ¨ list(n) n posições com valor default ¨ list(n,val) n posições com valor val n Atribuição ¨ assign(beg, end) Atribui um vetor com os valores de [beg,end[ ¨ assign(n,val) Atribui um vetor com n cópias de val n Acesso ¨ front() Primeiro elemento ¨ back() Último elemento Renato Maia 220nov/2004 Operações do Contêiner Lista n Alteração nas extremindades ¨ push_back(val) Adiciona ao final ¨ pop_back() Remove o último elemento ¨ push_front(val) Adiciona um novo primeiro elemento ¨ pop_front() Remove o primeiro elemento n Alteração na seqüência ¨ insert(pos,val) Insere cópia de val antes de pos ¨ insert(pos,n,val) Insere n cópias de val antes de pos ¨ insert(pos,beg, end) Insere os valores de [beg,end[ antes de pos ¨ erase(pos) Apaga elemento em p Renato Maia 221nov/2004 Operações do Contêiner Lista n Remoção ¨ remove(val) Remove todos os elementos com valor val ¨ remove_if(op) Remove os elementos que op(elem)==true ¨ unique() Remove duplicatas ¨ unique(op) Remove duplicatas que op(elem)==true n Alterações sem cópia ¨ splice(pos,list) incorpora todos os elementos de list para antes de pos ¨ splice(pos,list,p) move *p de list para antes de pos ¨ splice(pos,list,beg,end) move os elementos de list em [beg,end[ ... idem ¨ sort() Ordena usando operador < ¨ sort(op) Ordena usando comparação cmp ¨ merge(list) Internala com list mantendo a ordenação (<) ¨ merge(list,op) Internala com list mantendo a ordenação (op) ¨ reverse() Inverte a ordem dos elementos Renato Maia 222nov/2004 Contêiner Fila Dupla n seqüência de elementos para acesso nas extremidades ¨ J Acesso nas extremidades ¨ L Alterações no meio da seqüência n Cabeçalho ¨ #include <deque> n Parâmetros ¨ Tipo dos elementos armazenados ¨ Tipo do gerenciador de memória (opcional) n Exemplos ¨ deque<int> dqi; ¨ deque<MyClass> dqobj; ¨ deque<vector<string> > dqvet; Renato Maia 223nov/2004 Operações do Contêiner Fila Dupla n Construtores ¨ deque(n) n posições com valor default ¨ deque(n,val) n posições com valor val n Atribuição ¨ assign(beg, end) Atribui um vetor com os valores de [beg,end[ ¨ assign(n,val)Atribui um vetor com n cópias de val n Acesso ¨ [pos] Indexação sem verificação ¨ at(pos) Indexação com verificação ¨ front() Primeiro elemento ¨ back() Último elemento Renato Maia 224nov/2004 Operações do Contêiner Fila Dupla n Tamanho ¨ resize(n) Altera o número de elementos ¨ resize(n,val) Idem, val define o valor de inicialização n Alteração nas extremindades ¨ push_back(val) Adiciona ao final ¨ pop_back() Remove o último elemento ¨ push_front(val) Adiciona um novo primeiro elemento ¨ pop_front() Remove o primeiro elemento n Alteração na seqüência ¨ insert(pos,val) Insere cópia de val antes de pos ¨ insert(pos,n,val) Insere n cópias de val antes de pos ¨ insert(pos,beg, end) Insere os valores de [beg,end[ antes de pos ¨ erase(pos) Apaga elemento em p Renato Maia 225nov/2004 Contêiner Pilha n Adaptador de contêiner seqüencial para acesso FIFO n Cabeçalho ¨ #include <stack> n Parâmetros ¨ Tipo dos elementos armazenados ¨ Tipo dos contêiner seqüêncial utilizado (default deque<T>) n Exemplos ¨ stack<int> si; ¨ stack<MyClass, vector<MyClass>> stkobj; Renato Maia 226nov/2004 Operações do Contêiner Pilha template<class T, class C = deque<T> > class stack { protected: C c; public: typedef typename C::value_type value_type; typedef typename C::size_type size_type; typedef C container_type; explicit stack(const C& a =C()) : c(a) { } bool empty() const { return c.empty() ; } size_type size() const { return c.size() ; } value_type& top() { return c.back() ; } const value_type& top() const { return c.back() ; } void push(const value_type& x) { c.push_back(x) ; } void pop() { c.pop_back() ; } }; Renato Maia 227nov/2004 Contêiner Fila n Adaptador de contêiner seqüencial para acesso LIFO n Cabeçalho ¨ #include <queue> n Parâmetros ¨ Tipo dos elementos armazenados ¨ Tipo dos contêiner seqüêncial utilizado (default deque<T>) n Exemplos ¨ queue<int> qi; ¨ queue<MyClass, vector<MyClass>> queobj; Renato Maia 228nov/2004 Operações do Contêiner Fila template<class T, class C = deque<T> > class queue { protected: C c; public: typedef typename C::value_type value_type; typedef typename C::size_type size_type; typedef C container_type; explicit queue(const C& a =C()) : c(a) { } bool empty() const { return c.empty() ; } size_type size() const { return c.size() ; } value_type& front() { return c.front() ; } const value_type& front() const { return c.front() ; } value_type& back() { return c.back() ; } const value_type& back() const { return c.back() ; } void push(const value_type& x) { c.push_back(x) ; } void pop() { c.pop_front() ; } }; Renato Maia 229nov/2004 Contêiner Fila de Prioridades n Adaptador de contêiner seqüêncial para acesso de elementos de maior prioridade n Cabeçalho ¨ #include <queue> n Parâmetros ¨ Tipo dos elementos armazenados ¨ Tipo dos contêiner seqüêncial utilizado (default deque<T>) ¨ Comparador de elementos que define relação de prioridades n Exemplos ¨ priority_queue<int> qi; ¨ qi.push(2); ¨ qi.push(4); ¨ cout << qi.pop(); Renato Maia 230nov/2004 Operações da Fila de Prioridades template <class T, class C = vector<T>, class Cmp = less<typename C::value_type> > class priority_queue { protected: C c; Cmp cmp; public: typedef typename C::value_type value_type; typedef typename C::size_type size_type; typedef C container_type; explicit priority_queue(const Cmp& a1 =Cmp() , const C& a2 =C()) : c(a2) , cmp(a1) { } template <class In> priority_queue(In first, In last, const Cmp& =Cmp() , const C& =C()) ; bool empty() const { return c.empty() ; } size_type size() const { return c.size() ; } const value_type& top() const { return c.front() ; } void push(const value_type&) ; void pop() ; }; Renato Maia 231nov/2004 Utilitário Pares template <class T1, class T2> struct std::pair { typedef T1 first_type; typedef T2 second_type; T1 first; T2 second; pair() : first(T1()) , second(T2()) { } pair(const T1& x, const T2& y) : first(x) , second(y) { } template <class U, class V> pair(const pair<U,V>& p) : first(p.first) , second(p.second) { } }; Renato Maia 232nov/2004 Contêiners Mapa e Multimapa n Conjunto de pares (chave,valor) para acesso baseado na chave n Cabeçalho ¨ #include <map> n Parâmetros ¨ Tipo dos elementos da chave ¨ Tipo dos elementos armazenados ¨ Tipo do comparador dos elementos (opcional) ¨ Tipo do gerenciador de memória (opcional) n Exemplos ¨ map<string,int> m; ¨ ++m["int"]; ¨ cout << m["int"]; Renato Maia 233nov/2004 Operações do Cont. (Multi)Mapa n Construtores ¨ contêiner(op) vazio, usando op como comparação op ¨ contêiner(beg,end,op) Os pares em [beg,end[, usando op como comparação op n Acesso ¨ [k] Apenas para o contêiner mapa. Devolve uma referência para o valor mapeado por k Se não houver o elemento este é inserido com o valor default n Mapeamento ¨ count(k) Número de elementos com a chave k ¨ find(k) Devolve a primeira posição com a chave k ou end() ¨ lower_bound(k) Devolve a primeira onde um elemento com a chave k seria inserido ¨ lower_bound(k) Devolve a última posição onde um elemento com a chave k seria inserido ¨ equal_range(k) Devolve a primera e a última posição onde um elemento com a chave k seria inserido Renato Maia 234nov/2004 Contêiners Conjunto e Multiconjunto n Conjunto de valores para verificação de pertinência n Cabeçalho ¨ #include <set> n Parâmetros ¨ Tipo dos elementos armazenados ¨ Tipo do comparador dos elementos (opcional) ¨ Tipo do gerenciador de memória (opcional) n Exemplos ¨ set<int> conj; ¨ conj.insert(4); ¨ conj.insert(1); ¨ if (conj.find(2) == conj.end()) /* ... */ ; Renato Maia 235nov/2004 Operações do Cont.(Multi)Conjunto n Construtores ¨ contêiner(op) vazio, usando op como comparação op ¨ contêiner(beg,end,op) Os pares em [beg,end[, usando op como comparação op n Mapeamento ¨ count(e) Número de elementos com o valor e ¨ find(e) Devolve a primeira posição com o valor e ou end() ¨ lower_bound(e) Devolve a primeira onde um elemento com o valor e k seria inserido ¨ lower_bound(e) Devolve a última posição onde um elemento com o valor e seria inserido ¨ equal_range(e) Devolve a primera e a última posição onde um elemento com o valor e seria inserido Renato Maia 236nov/2004 Contêiner Conjunto de Bits n Conjunto de valores para verificação de pertinência n Cabeçalho ¨ #include <bitset> n Parâmetros ¨ Número de bits n Exemplos ¨ enum RGB { red, green, blue, count } ¨ bitset<count> bs; ¨ bs.set(red); ¨ bs.set(green); Renato Maia 237nov/2004 Operações do Conjunto de Bits n Construtores ¨ bitset(long) Ativa os bits do inteiro longo long ¨ bitset(str) Ativa os bits correspondentes aos caracteres '1' da string str ¨ bitset(str,i) Ativa os bits correspondentes aos caracteres nas posições após i da string str que tenham valor '1' ¨ bitset(str,i,j)Ativa os bits correspondentes aos caracteres nas posições em [i,j[ da string str que tenham valor '1' n Acesso ¨ size() Devolve o número de bits ¨ count() Devolve o número de bits ativos ¨ any() Informa se algum bit está ativo ¨ none() Informa se nenhum bit está ativo ¨ test(idx) Informa se o bit de indice idx está ativo Renato Maia 238nov/2004 Operações do Conjunto de Bits n Operadores (mesmo significado quando aplicado a inteiros) ¨ Relacionais n == != ¨ Boleanos n & | ^ << >> ~ ¨ Atribuição n &= |= ^= <<= >>= n [idx] Acessa o bit de índice idx Renato Maia 239nov/2004 Operações do Conjunto de Bits n Manipulação ¨ set() Ativa todos os bits ¨ set(idx) Ativa o bit de indice idx ¨ set(idx, val) Ativa o bit de indice idx de acondo com val ¨ reset() Desativa todos os bits ¨ reset(idx) Desativa o bit de indice idx ¨ reset(idx, val) Desativa o bit
Compartilhar