Sei sulla pagina 1di 53

Programação Orientada a Visão geral

Objetos em C++


A programação orientada a objetos no
contexto geral do desenvolvimento de
Ivan Luiz Marques Ricarte
software


Do projeto de software para a
FEEC/UNICAMP
implementação em C++


Técnicas de implementação inerentes à
linguagem de programação C++

Formas de contato O desenvolvimento de software


orientado a objetos
e−mail
ricarte@fee.unicamp.br
URL
http://www.dca.fee.unicamp.br/~ricarte/
Uma breve visão da
endereço postal
evolução da Engenharia
DCA/FEEC/UNICAMP de Sofwtare
Caixa Postal 6101
13083−970 Campinas, SP
telefone
(19) 3788 3771
Por que tanta ênfase nas técnicas de A segunda era do desenvolvimento de
desenvolvimento de software? software


Sistemas computacionais onipresentes Software como um produto


software é componente essencial nesses primeiras bibliotecas de software


sistemas Alto custo de manutenção


Software é um produto em muitos casos, manutenção era


resultado do desenvolvimento entregue junto virtualmente impossível
ao sistema computacional


Software é um veículo para disponibilizar
o produto
1950 1960 1970 1980 1990 2000

Os primórdios do desenvolvimento de
software A terceira era

Desenvolvimento de software dirigido Complexidade de software crescente




pelo desenvolvimento de hardware sistemas distribuídos e concorrentes





software como um afterthought Amplo uso de microprocessadores




custom software sistemas embarcados



custo de hardware baixo
quase nenhum método sistemático de
desenvolvimento

1950 1960 1970 1980 1990 2000 1950 1960 1970 1980 1990 2000
A era atual no desenvolvimento de
software Mitos de software


Sistemas decentralizados e Precisa desenvolver software?


incorporando novas tecnologias Vamos comprar um computador da última


geração


Inteligência artificial, computação paralela,
realidade virtual, multimídia O que é preciso para começar a
software mais caro que hardware programar?


OO como tecnologia de integração Basta uma descrição genérica de objetivos


O desenvolvimento está atrasado?


Vamos acrescentar alguns programadores a
1950 1960 1970 1980 1990 2000
mais para agilizar e entrar em fase

Problemas recorrentes no
desenvolvimento de software E mais mitos



Maior parte do software ainda é Houve algumas mudanças nos requisitos do
projeto; algum problema?


desenvolvido sob medida


Não, software é flexível
como explorar potencial do hardware?



como atender às demandas por novas Como saber se o projeto obteve sucesso?




funcionalidades e programas? Basta ver se o programa rodou








como desenvolver software confiável? O programa rodou ?




como manter software existente? Fim do trabalho do desenvolvedor do software




Os mitos de software persistem Como certificar a qualidade do software?




Pode−se analisar agora que o programa está


rodando
Demanda pela Camadas da
Engenharia de Software Engenharia de Software



The establishment and use of sound engineering Processos


principles in order to obtain economically software that is
reliable and works efficiently on real machines. estabelecem a base para o controle
administrativo de projetos de software
Fritz Bauer, 1969


(1) The application of a systematic, disciplined, Métodos






quantifiable approach to the development, operation, and aspectos técnicos (os how to s ) da
maintenance of software; that is, the application of construção de programas


engineering to software.


Ferramentas


(2) The study of approaches as in (1).
IEEE, 1993 apoio automatizado a processos e métodos

O que é a
engenharia de software? Modelo de processo linear




A tecnologia que deveria ser utilizada por Modelo em etapas seqüenciais




aqueles que desenvolvem software t.c.c. modelo clássico ou waterfall

tools system/information
engineering and modeling
methods
process analysis design code test
a quality focus
maintenance
Etapas genéricas do processo: Etapas genéricas no processo:
Análise Codificação



Análise de requisitos Tradução do projeto de software em


ponte entre engenharia de sistemas e o programas


projeto de software uma ou mais linguagens de programação



reconhecimento do problema, avaliação, Incorporação de opções de
síntese, modelagem, especificação e revisão


implementação


Análise de software


fidelidade ao projeto, eficiência, reutilização
primeira representação técnica do sistema de código, adaptação a recursos disponíveis


modelagem dos dados, seus atributos e
relacionamentos, e das funções que os
manipulam

Etapas genéricas do processo: Etapas genéricas do processo:


Projeto Teste






Estabelecimento das opções de Processo destrutivo




desenvolvimento deve demonstrar que programa não atende


dados, procedimentos, interfaces e aos requisitos estabelecidos


arquitetura Estratégias






deve contemplar requisitos implícitos Depuração de código




Guia para implementador Teste de unidade




oferece visão completa do software, tanto no Teste de integração




aspecto estrutural como no comportamental


Teste de sistema e validação
Etapas genéricas do processo:
Manutenção Modelo de processo RAD
business


business modeling

Atividade de correção ou atualização de modeling data


business modeling
data process
parte do software modeling modeling modeling


application
generation
em decorrência do resultado de testes ou de data process
testing &
modeling turnover
novas demandas colocadas para o sistema modeling
application


process generation
Requer um ciclo completo de testing &
modeling turnover
desenvolvimento


application
análise, projeto, codificação e teste generation
testing &
turnover
60−90 days

Modelo de processo baseado em A metodologia de desenvolvimento de


prototipagem software estruturado


Quick design Modelos resultantes da análise


Requirements


gathering Listen to
customer Prototype Diagramas de fluxo de dados


construction
Build/revise Atividades no projeto


mock−up
Estabelecimento de arquitetura do sistema


Seleção das estruturas de dados


Requirements


refinement Sit with Codificação




customer
Linguagem de programação estruturada
Customer
test−drives Prototype
mock−up evaluation
Características de um bom projeto de A construção de software orientado a
software estruturado objetos



Abstração Uso de linguagem de programação que


de dados, de procedimentos e de controle suporte as mesmas primitivas da análise


refinamento top−down e projeto


classes, objetos, herança, relações, ...


Arquitetura modular


solução como integração de módulos com O modelo de orientação a objetos permite
alta coesão e baixo acoplamento levar naturalmente às boas características


de software


Ocultamento da informação


mas maus hábitos de programação podem
reduz impacto de alterações e propagação de levar tudo a perder!
erros

A metodologia de desenvolvimento de
software orientado a objetos Programação Orientada a
Objetos



A mesma linguagem na análise e
projeto


Análise: modelos conceituais


casos de uso


classes, atributos no domínio do problema
Do projeto para o


diagramas de seqüência e contratos
programa


Projeto: opções de desenvolvimento


uso de componentes e interfaces


visibilidade e organização em pacotes
Resultados da atividade de projeto Evolução dos paradigmas de
programação: orientada a objetos



Especificação detalhada do sistema Foco na definição de classes



Diagramas, descrições funcionais e estruturais definição estrutural de classes


Projeto estruturado classes básicas, atributos, declaração de métodos


classes derivadas


procedimentos, módulos, interface de
programação para módulos, estruturas de definição do comportamento de classes


dados internas definição de métodos



Projeto orientado a objetos Programas de teste e programa principal



classes, métodos, atributos, colaborações após definição completa de classes

Evolução dos paradigmas de


programação: tradicional Programação orientada a objetos




Foco nas descrições de procedimentos Um paradigma de programação





Abordagem top−down Técnica para escrever bons programas para


primeira descrição: programa principal um determinado conjunto de problemas



procedimentos usados no programa principal são Linguagem de programação orientada a
refinados sucessivamente até que procedimentos
primitivos sejam alcançados objetos



Arquitetura modular Linguagem de programação que oferece


mecanismos adequados ao estilo de
estrutura interna de organização


programação orientada a objetos
mecanismo para abstração
Características de linguagens de Linguagens recentes de
programação orientada a objetos programação orientada a objetos



Definição de classes C++



criação de tipos definidos pelo programador extensão da linguagem C para incorporar


conjunto de atributos e métodos associados mecanismos da programação orientada a


objetos


Herança meados da década de 1980



definição de classes a partir da Java


especialização de classes existentes


uma nova linguagem orientada a objetos
Criação e remoção de objetos usando uma sintaxe no estilo da linguagem C



manipulação da região de memória definida meados da década de 1990
pelo objeto

Primeiras linguagens de
programação orientada a objetos Programação orientada a objetos


Simula 67


aplicações em simulação


introduziu conceito de classes e objetos


Smalltalk 80 Introdução à


linguagem “completamente orientada a
objetos” desenvolvida na Xerox PARC linguagem C++


baixa eficiência


considerada uma “linguagem de brinquedo” por
“desenvolvedores de verdade”
Introduction to C++ C++ evolution



Programming language to improve the C C++ predecessor: C with classes (1980)


programming language supporting: Stroustrup approach to support development


data abstraction of event−driven simulation programs from C


object−oriented programming C++ first public appearance


Designed by Bjarne Stroustrup July 1983


AT&T Bell Labs since then, use of C++ has grown explosively


initial motivation C++ standardization effort


development of efficient simulation programs Starting 1987


ANSI committee, 1989−1996

C++ evolution C++: Class definition


C++ is mostly derived from C class class_name {


originally a systems programming language private:


Unix operating system project private−member−declarations


generated code is time and space efficient public:


derived from BCPL and B public−member−declarations


protected:
Concepts from many other languages


protected−member−declarations
Simula67: classes


};
Algol68: operator overloading


ADA and Clu: templates, exception handling
C++: Class definition C++: Class definition



Members are class attributes (variables) or Static member


class methods (functions) member of a class that is shared by all


private members can only be accessed from objects of the class


member methods keyword static


public members accessible from any function static attribute member


protected members accessible from derived same value viewed by all objects


classes static method member


applied to the class, not to objects

C++: Class definition C++: Objects





Attribute members are defined within the Instances of classes


scope of class definition access to class members: operator .




Method members are declared within class can be handled statically




definition but can be defined outside created by object declaration





method definition within class definition: inline deleted by end of scope




to define outside class definition: scope operator can be handled dynamically




returntype classname::methodname(args){body}
created by operator new


deleted by operator delete


C++: Objects C++: Polymorphism



Object initialization and finalization Abstract classes



constructors: contain at least one virtual function



same name of class concrete derived classes should provide


no return value (not even void), implementation for these functions


can have arguments


member functions bound dynamically, during
automatic invocation when object is created run time, to the function that will be called



destructors: when function invoked through reference to object



name of the class prefixed by ~ in C++, reference to object: pointer


no return value, no arguments


automatic invocation when object is destroyed

C++: Inheritance C++ syntax




Inheritance Minimal C++ program:


class derived : public base { main( ) { }


// only additions to derived class are specified defines a function main that takes no
... arguments and does nothing


} { and } express grouping in C++




Multiple inheritance block delimiters




class derived : public base1, public base2 { Every C++ program has a main function


...
starting point for program execution
}
C++ syntax C++ syntax



main function can present arguments and Fundamental types


return a value char


int main(int argc,char *argv[]){ short int or simply short Integral types


return 0; int


}


long int or simply long


argc: argument count


float Floating−point


argv: argument values double


numbers


return value: to the invoking program
long double


(operating system)
void

C++ syntax C++ syntax




Variables Arithmetic operators


declaration + − * / % ++ −−


type var_name[, var_name]; Comparison operators


also == != < > <= >=




initialization


Boolean connectives: && || !


const modifier


storage modifiers static and extern Bit operators: & | ~ ^


alter scope and lifetime of variables Assignment operator: = op=




sizeof operator
C++ syntax C++ syntax



Arrays Loops
char v[10]; while (logical condition) {


v has elements indexed from 0 to 9 ...


Pointers }


char *p; also


Operator address−of do while and for statements


p = &v[3]; break, goto, continue jump statements


Logical condition is an integer expression

C++ syntax C++ syntax




Tests Functions
if (logical condition) { return_type function (param_list) {
... function body
} }


else { also


... return statement




} function declarations




also argument passing




switch−case statement default: by value


ternary operator ? :
C++ syntax C++ programming



Functions Common design pitfalls



argument passing by reference is possible Ignore classes, using C subset only



pointer manipulation is implicit Ignore derived classes and virtual functions



operator & use data abstraction subset



different signatures for same function name Ignore static type checking



function signature determines which design constraining implementers to dynamic type
implementation is selected checking only


static (compile−time) checking

C++ programming Programação orientada a


objetos com C++


It is possible to use C++ and do
exclusively procedural programming


Trabalhando com objetos
C++ can be used as a dialect of C


Development of good object−oriented
programs in C++ depends on
programming discipline


supported by application of object−oriented
practices in analysis and design
A criação de objetos Exemplos de construtores default


Criação de um objeto de uma classe dá− class Xyz { class Xyz { class Xyz {
se por meio da invocação de um de seus ... ... ...
métodos construtores } public: public:


construtor default Xyz(int a); Xyz(int a=0);


invocado sem argumentos main() { } }


construtor de cópia Xyz o1; main() { main() {


invocado com um argumento da mesma classe Xyz o1; Xyz o1;


...
construtor com argumentos ... ...


}
invocado em outros casos
} erro! }

Construtor default Construtor de cópia




Automático Permite criação de objetos a partir de


construtor sem argumentos é disponibilizado outro objeto existente


pelo compilador se nenhum outro construtor recebe como argumento uma referência para
for definido um objeto da mesma classe


Definido pelo programador class Xyz {


sem argumentos ...


public:
com argumentos, desde que todos possam
receber algum valor por default Xyz(Xyz& a);
}
Construtor de cópia automático Construção de objetos



Construtor de cópia é automaticamente Estaticamente


definido pelo compilador declaração de objeto



quando programador não define escopo válido até o fim do bloco onde ocorre
explicitamente um construtor de cópia declaração


Comportamento do construtor automático Dinamicamente


cria novo objeto da classe declaração de ponteiro para objeto


faz cópia membro a membro criado com operador new


válido até invocação do operador delete para
o ponteiro

Construtor de cópia pelo


programador Exemplo de construção de objetos
#include <iostream.h>
class Xyz {


int x; int y;
Situações onde é necessário definir public:
Xyz(int a=0, int b=0);
explicitamente um construtor de cópia Xyz(Xyz& a);
};


Xyz::Xyz(int a, int b) {
quando parte do objeto faz uso de recursos x = a; y = b;
externos aos seus membros cout << "Xyz criado: (" << x << "," << y << ")" << endl;
}


áreas alocadas de memória, arquivos Xyz::Xyz(Xyz& a) {
x = a.x; y = a.y;


cout << "Xyz copiado: (" << x << "," << y << ")" << endl;
Opções de cópia com recursos externos }


int main(int argc, char *argv[]) {
cópia rasa Xyz o1;
Xyz o2(1,1);


com compartilhamento Xyz o3 = o2;
Xyz o4 = Xyz(2,2);


Xyz o5 = 1;
cópia profunda Xyz* o6 = new Xyz(3,3);


return 0;
com alocação de novos recursos }
Resultado da execução para
construção de objetos Operando com arranjos de objetos



Xyz criado: (0,0) Para a criação de a1 e a4, construtor sem


Xyz criado: (1,1) argumentos é utilizado


deve estar presente


Xyz copiado: (1,1)


A remoção de arranjos alocados
Xyz criado: (2,2)


dinamicamente deve ser explícita


Xyz criado: (1,0) delete [] a4;



Xyz criado: (3,3) de outro modo, apenas o primeiro elemento é
liberado


seria o comportamento padrão pelo fim do escopo

Criação de arranjos de objetos O operador new





Xyz a1[4]; Operador global e static



cria arranjo com quatro objetos (0,0) Obtém espaço da área livre



Xyz a2[] = {1, 2}; Pode ser redefinido na classe



cria arranjo com dois objetos, (1,0) e (2,0) void *operator new(size_t s);



Xyz a3[4] = {Xyz(1,1), Xyz(2,2)}; Pode incluir parâmetros



cria arranjo com (1,1), (2,2), (0,0) e (0,0) void *operator new(size_t s, params);



Uso: Xyz* x = new (args) Xyz(args_cons);


Xyz* a4 = new Xyz[4];


cria arranjo com quatro objetos (0,0) Pode ser sobrecarregado


para usar o original: ::new


Lista de inicializadores Destruição de objetos



Complementa informação para a Quando estado de objeto é descrito
construção do objeto exclusivamente por seus membros



Classe::Classe(params) : lista_inicializadores {...} locais , comportamento padrão de


Possíveis usos: remoção funciona bem


iniciar valores de membros constantes liberar a área de memória ocupada



iniciar objetos membros com construtores Quando outros recursos externos estão
diferentes do default


alocados ao objeto, uso de destrutores é
invocar construtores diferentes do default nas necessário
superclasses

Seqüência de construção Destrutores



Quando um objeto de classe T é criado Método destrutor para classe T é T::~T()


1. construtores das classes bases são sem argumentos

chamados não pode ser sobrecarregado

pela ordem de declaração, se não alterada na objetos criados estaticamente


lista de inicializadores


invocado automaticamente ao fim do escopo

2. se classe T contém membros que sãso objetos criados dinamicamente


objetos, estes são criados


invocado automaticamente pelo operador delete

usando construtor default, se não especificado de


outra forma na lista de inicializadores Exemplo de uso

3. corpo do construtor de T é executado remoção de área alocada:


cópia rasa vs. profunda


Invocação explícita de destrutor Cópia de objetos



É um método static da classe: Duas maneiras de copiar objetos


Abc* pa; por atribuição


... uso do operador de atribuição =


pa −> Abc::~Abc();




por inicialização


realiza um clean−up sem remover o objeto


na inicialização de objetos


neste caso, destrutor precisa ter sido incluindo declaração com valor inicial


declarado explicitamente na passagem de argumentos por valor



apenas um destrutor pode ser definido portanto não deve existir construtor T(T) para classe T



assinatura é fixa, não permite sobrecarga como retorno de funções e métodos

Seqüência de destruição Operador de atribuição

Quando um objeto da classe T é destruído Comportamento padrão

1. o destrutor da classe T é invocado cópia membro a membro

2. os destrutores dos objetos membros de T pré−definido


são invocados pode não ser adequado em alguns casos

3. os destrutores das classes bases são membros que são ponteiros para áreas alocadas

invocados


Sobrecarga do operador =
Processo inverso ao da criação de objetos Abc& Abc::operator =(Abc& rhs)

operador pode ser desabilitado


sobrecarregando−o como private
Sobrecarga de operadores: nem Exemplo: sobrecarga do operador
tudo é permitido +
class Xyz {


int x; int y;
Não é possível inventar novos operadores public:


...
restrito aos existentes em C++ Xyz operator +(Xyz a);


};
Não é possível redefinir alguns ...
Xyz Xyz::operator +(Xyz a) {
operadores Xyz z;


z.x = x + a.x;
. .* :: ?: z.y = y + a.y;


return z;
# ## }


int main() {
Não é possível mudar associatividade ou Xyz o1(2,2);
Xyz o2(1,1);
precedência de operadores Xyz o3 = o1 + o2;
Xyz o4 = o2 + 1;


Não é possível mudar número de // Xyz o5 = 1 + o2; <=== Situação de erro de compilação
}
operandos de operadores

Sobrecarga de operadores: casos Resultado da execução com


especiais sobrecarga do operador +

Operadores incremento (++) e Xyz criado: (2,2)


decremento (−−) Xyz criado: (1,1)

para diferenciar implementação pré−fixada da Xyz copiado: (1,1)


pós−fixada, nesta utiliza−se um parâmetro


extra do tipo int Xyz criado: (0,0)


para classe T, Xyz copiado: (3,3)

T operator ++(); // pré−fixada Xyz criado: (1,0)

T operator ++(int); // pós−fixada


Xyz criado: (0,0)

Xyz copiado: (2,1)


Forma funcional equivalente ao
uso do operador + Exemplos de amizade


Xyz o3 = o1 + o2; class X { class Y; class Y;


friend void f(); class X { class X {
o3 = o1.operator+(o2);


} friend void Y::f(); friend void Y;
todos os argumentos de acordo com assinatura


} }
Xyz o4 = o2 + 1; void f() { class Y { class Y {


o4 = o2.operator+(1); ... void f(); ...


sabe como criar Xyz a partir de um inteiro } } }


Xyz o5 = 1 + o2; métodos com direito void Y::f() { todos os métodos de


o5 = 1.operator+(o2); de acesso aos membros ... Y têm direito de


internos de X } acesso aos membros
não pode aplicar operador a um valor inteiro... internos de X

Características de funções e
Friends operadores amigos


Funções que são amigas de uma classe São globais

recebem direito de acesso aos membros podem pertencer a mais de uma classe

internos (private e protected) de objetos Não têm o ponteiro de auto−referência


dessa classe (this)


Quando uma classe é declarada como amiga não fazem referência a um objeto específico

dentro de outra, todos os métodos da classe não têm o parâmetro implícito


declarada recebem esse direito Se declaração está na parte pública ou


privativa da definição da classe é
irrelevante
Uso de funções/operadores
amigos: classes acopladas Mecanismos de conversão de tipos



Quando acesso a membros internos de Conversão pode ocorrer por meio de
mais de uma classe é desejado ou construtores e por meio de operadores
necessário class Xyz {
...


operação conjunta das classes está public:
fortemente relacionada Xyz (OutroTipo ot); // de OutroTipo para Xyz
operator OutroTipo( ); // de Xyz para OutroTipo


Exemplos }


...
Matriz e Vetor (aplicação em álgebra linear) Xyz x; OutroTipo w;


w = OutroTipo(x); // OK
Container e Iterator (coleções de objetos) w = (OutroTipo) x; // Também OK
w = x; // OK, conversão implícita

Uso de funções/operadores Exemplo de uso de operador


amigos: uso de conversão amigo: +
class Xyz {


...
Função amiga não é aplicada a um objeto public:


friend Xyz operator +(Xyz a, Xyz b);
recebe objeto como argumento ...



};
Pode ser aplicada tanto ao objeto da Xyz operator +(Xyz a, Xyz b) {
Xyz z;
classe especificada no parâmetro como a z.x = a.x + b.x;
z.y = a.y + b.y;
qualquer instância de outro tipo que possa return z;
ser convertido para ela }
int main() {


argumentos de funções e operadores amigos Xyz o1(2,2);
Xyz o2(1,1);
são tratados simetricamente Xyz o3 = o1 + o2;
Xyz o4 = o2 + 1;
Xyz o5 = 1 + o2; // Agora OK
...
}
Uso de funções/operadores
amigos: extensão streams Quando não usar friend?



Forma de uso desejada dos operadores Quando não houver nenhum motivo que
<< e >> justifique o uso de função amiga, dê
Xyz x; preferência ao método


cin >> x; reduz uso do espaço global de nomes


cout << x;


Se não há conversão definida


não devem ser membros de ostream e
istream Quando operador requer um lado


não seria possível prever todas as situações esquerdo que seja do tipo de objeto


não podem ser membros de Xyz = , += , −=, ..., ++ , −−


lado esquerdo não é objeto Xyz

Solução para extensão de streams Quando usar friend?


class Xyz {

... Duas ou mais classes fortemente


friend ostream& operator<<(ostream&, Xyz& a); acopladas

friend istream& operator>>(istream&, Xyz& a); praticamente impossível pensar que uma
} seria independente da outra

ostream& operator<<(ostream& os, Xyz& a) { Operador pode necessitar da conversão


os << “(“ << a.x << “”,”” << a.y << “”)”; implícita para qualquer um de seus
return os; operandos

istream& operator>>(istream& os, Xyz& a) { +, − , *, ...


is >> a.x >> a.y;
return is;
Programação Orientada a Quando usar herança?
Objetos com C++


Objetos da nova classe constituem um
subconjunto dos objetos da classe base




Reaproveitando
associação do tipo é−um


funcionalidades definidas
em outras classes Princípio da substituição de Liskov


Relacionamento hierárquico é
estabelecido entre as classes


classe base: funcionalidades genéricas


classe derivada: funcionalidades
especializadas

Projeto com reuso de classes Estratégias de herança

Mecanismos para definir novas classes Extensão


usando classes existentes: classe derivada acrescenta atributos e


Derivação de classes funcionalidades à definição da classe base


implementação do conceito de herança Especificação

Composição de classes classe derivada oferece implementação a


implementação do conceito de associações entre funcionalidades declaradas na classe base

classes Herança polimórfica


classe derivada implementa especificação e


reaproveita funcionalidades da classe base
Mecanismos de herança em C++ Exemplo de classe Base privativa
private implícito


Especificação de classe derivada: class Base {
class Derivada : especificador_acesso Base { int a;
class Deriv1 : Base {
... protected:
public:
}; int b;
void fd();


objetos de Derivada podem manipular public:
};
diretamente membros public e protected int c;
void Deriv1::fd() {
definidos em Base };


mas não têm acesso a membros private ...
} Base::a is not accessible
in function Deriv1::fd()

O especificador de acesso na Restrições em funções externas à


derivação de classes hierarquia Base−>Derivada


private (default) int main() {


todos os membros public e protected da classe Base b1;
Base tornam−se membros private de Derivada Deriv1 d1;


Base::c is not accessible in
protected b1.c++; function main()


todos os membros public e protected da classe d1.c++;
Base tornam−se membros protected de Derivada


d1.fd();


public Cannot convert Deriv1 * to




Base* bp = &d1;
membros public e protected da classe Base Base * in function main()
mantêm visibilidade na classe Derivada bp−>c++;
}
Reajuste de permissões de acesso O que era público na base continua
a membros público na derivada


Visibilidade da classe base pode ser int main() {
individualmente restaurada na classe Deriv2 d1; Agora OK.
derivada d1.c++;
class Deriv1 : private Base { d1.fd();
protected:
Base* bp = &d1;
Base::b;
bp−>c++; Também OK.
public:
void fd(); }
};

Exemplo de classe Base pública O que se herda da classe base?


class Base { A classe derivada recebe


int a; class Deriv2 : public


Base { Todos os membros de dados

protected: mesmo que não tenha acesso a eles


public:
int b; Todos os métodos (funções membros)
void fd();

public: Mas não recebe de herança


};

int c; Construtores
void Deriv2::fd() {

}; Destrutores
...
} Base::a is not accessible
in function Deriv1::fd()
Especificando a construção da
Objetos derivados e construtores parte base



Construção de objeto começa pela parte Incluir construtor default na classe base


derivada da classe base se tiver acesso à classe base



Construtor da classe derivada sempre invoca se fizer sentido


construtor da classe base


Referenciar construtor válido na lista de
Construtor default (sem argumentos) é
invocado automaticamente
inicializadores


Caso não exista construtor default na classe Deriv1::Deriv1( ) : Base(0) {
base, invocação explícita deve estar na lista ...
de inicializadores do construtor derivado }

A busca pelo construtor default Definindo o construtor de cópia


class Base { Construtor de cópia automático


public: Base(int i);


invoca construtor de cópia da classe base

};
complementa cópia com parte específica

Base::Base(int i) { ... }
class Deriv1 : public Base { Construtor de cópia definido pelo
... programador

}; responsabilidade de invocar cópia da base


int main() { Deriv::Deriv(Deriv& d) : Base(d) {
Deriv1 d1; Cannot find default constructor to ...



} initialize base class Base in function }
Deriv1::Deriv1()
Atribuição entre objetos de classes Usando operador de atribuição
bases e derivadas automático


class Base {
De classe derivada para classe base


public:
ocorre sem problemas Base& operator=(Base& b);


descarta parte especializada };


Base& Base::operator=(Base& b) {
De classe base para derivada cout << "Atribuicao base" << endl;


não é permitida (parte indefinida) return b;
int main() { }
Deriv d1; Base b1; Ok class Deriv1 : public Base {...};
b1 = d1; int main() {


Deriv1 d1, d2;


d1 = b1; Atribuição base é
Cannot convert Base to


} d2 = d1; invocada
Deriv in function main() }

O operador de atribuição em Usando operador de atribuição


classes derivadas especificado


class Base { public: Base& operator=(Base& b); };
Semântica para operador definido
Base& Base::operator=(Base& b) { ... }
automaticamente: class Deriv : public Base {


invoca operador de atribuição para classe public: Deriv& operator=(Deriv& d); };
base Deriv& Deriv::operator=(Deriv& d) {


executa atribuição membro a membro para a cout << "Atribuicao da parte derivada" << endl;
parte específica da classe derivada return d;


}
Semântica para operador é redefinido: int main() {


responsabilidade do programador Deriv d1, d2; Atribuição base
d2 = d1; não é invocada
}
Usando todos operadores de
atribuição especificados Cuidados com uso de ponteiros


class Base { ... };
Porquê dos ponteiros


Base& Base::operator=(Base& b) { ... }
class Deriv : public Base { ... }; permitem programação mais flexível


Deriv& Deriv::operator=(Deriv& d) { definição do objeto manipulado apenas no
(Base&) (*this) = d; momento da execução


cout << "Atribuicao da parte derivada" << endl;
permitem aplicação do princípio da
return d;
}
substituição de Liskov


int main() { onde houver ponteiro para classe base, objeto de
Deriv d1, d2; qualquer classe derivada pode ser referenciado
Atribuição base é invocada e,
d2 = d1;
depois, atribuição derivada
}

Destruição de objetos derivados e


Objetos derivados e destrutores ponteiros

O processo de destruição de objeto ocorre Destrutores não são redefinidos:


na ordem inversa ao processo de criação
Base::Base(int i) { cout << "Construtor Base" << endl; }
Base::~Base() { cout << "Destrutor Base" << endl; } int main() { Construtor Base
Deriv1::Deriv1() : Base(0) { cout << "Construtor Deriv1" << endl; } Base* pb = new Deriv1; Construtor Deriv1
Deriv1::~Deriv1() { cout << "Destrutor Deriv1" << endl; }
...
int main() {
Deriv1 d1; Construtor Base delete pb;
... Construtor Deriv1 }
} Destrutor Base
Destrutor Deriv1
Destrutor Base
Destruição de objetos derivados e Métodos de mesmo nome na
ponteiros seção pública


Se destrutor base for declarado virtual Definição derivada esconde original
class Base { ... mesmo que assinatura seja diferente
class Base {public: void f(); };
virtual ~Base();
void Base::f() { ... }
} class Deriv : public Base {public: void f(int x); };
int main() { Construtor Base void Deriv::f(int x) { ... }
Construtor Deriv1 int main() {
Base* pb = new Deriv1; Deriv d1;
... d1.f(); Erro de compilação:
delete pb; Destrutor Deriv1 d1.f(1); Too few parameters in call to
Destrutor Base } Deriv1::f(int) in function main()
}

Definição de membros com Acesso a membros de mesmo


mesmo nome nome

Membro de classe derivada com mesmo O operador de escopo permite acesso às


nome de membro da classe base definições originais



esconde o membro original ...
class Base {public: void f(); }; void Deriv::f() { Referência à
void Base::f() { cout << "Base::f()" << endl; } Base::f();
definição original
class Deriv : public Base {public: void f(); }; cout << "Deriv::f()" << endl;
void Deriv::f() { cout << "Deriv::f()" << endl; } }
int main() { int main() {
Base::f( )
Base b1; b1.f(); Deriv d1;
Deriv d1; d1.f(); d1.f(); Base::f()
} Deriv::f( ) } Deriv::f()
Acesso a membros de mesmo Conversão entre classes bases e
nome por ponteiros derivadas



No caso geral, o tipo do ponteiro é que Ponteiro para objeto de classe derivada é
predomina automaticamente convertido para ponteiro
... de classe base


int main() { apenas membros da classe base são
Base *b1, *b2; referenciáveis através do ponteiro


b1 = new Base; Base::f()
para métodos declarados como virtuais, se
b1 −> f( );
um método redefinido com mesma assinatura
b2 = new Deriv;
b2 −> f( );
estiver presente na classe derivada então
} Base::f() será usado. Senão, usa método da classe
base

Polimorfismo: usando funções


membros virtuais Funções virtuais puras

Quando método é virtual, vale a definição Funções virtuais que devem


para o tipo efetivo do objeto apontado obrigatoriamente ser redefinidas em
class Base { classes derivadas

public:
virtual void f(); não contém nenhuma implementação
}; class Base {
int main() { public:
Base *b1, *b2;
virtual void f( ) = 0;
b1 = new Base; Base::f()
};
b1−>f();
b2 = new Deriv;
b2−>f();
}
Deriv::f()
Herança múltipla com base
Classes abstratas repetida


Contêm funções virtuais puras class Base { ... };


class Base1 : public Base { ... };
Só podem ser utilizadas como base para
class Base2 : public Base { ... };
a definição de outras classes


class Deriv : public Base1, public Base2 {
não é possível criar objetos de classe
...
abstrata
class Abst {
}; construtor de Base
construtor de Base1
public: int main() {
construtor de Base
virtual void f() = 0; Deriv d1; construtor de Base2
destrutor de Deriv construtor de Deriv
}; ...
Cannot create instance of abstract destrutor de Base2



int main() { class Abst in function main() destrutor de Base
}



Abst a1; Class Abst is abstract because of destrutor de Base1



} Abst::f( ) = 0 destrutor de Base

Herança múltipla com base


Herança múltipla compartilhada


Mesmos princípios da herança simples class Base { ... };
class Base1 { ... }; class Base1 : public virtual Base { ... };
class Base2 { ... }; class Base2 : public virtual Base { ... };
class Deriv : public Base1, public Base2 { class Deriv : public Base1, public Base2 {
... ...
construtor de Base1 };
};
construtor de Base2 int main() { construtor de Base
int main() { construtor de Base1
construtor de Deriv Deriv d1; construtor de Base2
Deriv d1;
... construtor de Deriv
... destrutor de Deriv destrutor de Deriv
destrutor de Base2 } destrutor de Base2
} destrutor de Base1
destrutor de Base1 destrutor de Base
Quando não usar herança Programação Orientada a
Objetos com C++


Hierarquia de classes contém contração


redução de funcionalidades nas classes
derivadas Tratamento de


Relação entre as classes pode ser melhor exceções
descrita por composição






é parte de , tem um

Mecanismo para manipulação de


Usando composição em C++ erros

class Part1 { ... }; Motivação


class Part2 { ... }; Comp não oferece os mesmos separar código para tratamento de erros do



métodos que Part1 e Part2


class Comp { código normal

... Mas os métodos de Comp têm evitar verificação desnecessária por


Part1* p1; acesso a essas funcionalidades condições de erro

através dessas referências,


Part2* p2; possivelmente inicializadas na desatrelar ocorrência do erro de seu
construção do objeto Comp tratamento
public:
Se Part1 e Part2 declararem Comp
... como classe amiga, métodos de
}; Comp terão acesso às suas
estruturas internas
O modelo padrão de exceções Aplicando uma exceção



Modelo baseado em dois eventos Uso do comando throw
síncronos throw expressão;



sinalização da ocorrência da situação de Comando executado quando a situação de
exceção


erro é detectada


throwing an exception


Encerra a execução do código corrente


resposta à situação de exceção sinalizada Similar a um comando return


catching an exception


Ocorrência do evento de sinalização
transfere controle do ponto de execução
para um tratador de exceções previamente
cadastrado

Por que exceções? Identificando a exceção ocorrida

Código pode encontrar uma condição que O tipo resultante da expressão throw
não pode suportar identifica a exceção

Retorna a algum código que o chamou e Objeto estático temporário do tipo da


sabe como tratar o erro. expressão é criado


Eventos ocorrem em partes distintas do Seu conteúdo é inicializado para o valor da
código expressão


Podem até mesmo ter sido definidos por Objeto estático: garante que mesmo erros
programadores distintos associados à manipulação da área livre
podem ser tratados
Reconhecendo a ocorrência da
exceção Múltiplos catches


try {
Instrução try−catch ...
try { }
... // código que pode gerar a exceção catch (tipo1 e1) {
... // em algum método utilizado ...
} }
catch (tipo_de_exceção e) { catch (tipo2 e2) {
... // código de tratamento para esse Catch genérico
...
... // tipo de exceção }
} catch (...) {
...
}

Exemplo de geração e captura de


exceção Efeito da exceção

Aplicação Captura e tratamento Quando exceção é gerada, controle de


... try { execução passa para o bloco try−catch



throw Socorro! ; // ... mais recentemente definido

... } A pilha é "esvaziada"


catch(char *p) { Destrutores são invocados para todos os objetos


// tratamento automáticos introduzidos desde a introdução do
bloco try

}
Mesmo para objetos parcialmente construídos o
compilador deve tratar corretamente a destruição
parcial
Tratando a exceção Continuando a execução



Ativa código do catch correspondente ao Após código do tratamento, execução
tipo da exceção gerada continua após o bloco try



Correspondente: Não há retorno para ponto de ocorrência do


Catch e throw têm mesmo tipo erro


Catch tem classe que é base para tipo de throw Se execução das instruções no corpo do


Catch é ponteiro e throw gera ponteiro que pode bloco try não causa a geração de
ser convertido para o ponteiro capturado por uma
conversão padrão de ponteiros nenhuma condição de exceção, blocos
catches são ignorados

Definindo múltiplos catches Especificação de exceções

Os tipos de tratadores são testados na Indicação presente na declaração e


ordem de aparecimento definição de funções

Os mais genéricos devem aparecer após Que exceções podem ocorrer no corpo da
casos especializados função


A declaração genérica (...), se presente, deve tipo func(param) throw (lista_tipos_exceções);
ser a última


Se não houver nenhuma combinação, tipo func(param) throw (lista_tipos_exceções) {
propaga exceção ... // código que pode gerar ou propagar


Equivale a ter "catch(...) { throw; }" ... // as exceções indicadas
}
Unexpected Propagação de exceções



Função unexpected() é invocada quando No tratamento de uma exceção, o código
uma função gera uma exceção não de manipulação pode optar por repassar a
especificada exceção que o ativou:


Efeito default de unexpected(): invocar ...
terminate() throw;


Efeito default de terminate(): invocar abort() ...


Reflete um erro sério de projeto encerra execução do manipulador e de seu
correspondente bloco try−catch


repassa controle ao próximo bloco try−catch

Variantes de especificação Comentários sobre exceções

Função sem lista de especificação pode Exceções são objetos


aplicar qualquer exceção podem carregar informação extra sobre a


Função com lista de especificação vazia, condição de erro além da simples sinalização
de sua ocorrência

throw(), não pode aplicar exceções


podem ser agrupadas em hierarquias de
Função com lista de especificação exceções

contendo a classe B pode gerar exceções permite tratamento genérico para um grupo de
associadas a objetos de qualquer classe exceções de mesma raiz
derivada publicamente de B
Programação Orientada a Saída
Objetos com C++


Classe ostream


Sobrecarrega operador <<



Streams inserção ou put to


Definido na classe base com lado direito
correspondente a todos os tipos básicos da
linguagem


qualquer outro tipo: deve ser definido como
apresentar valores

Classes de entrada e saída Entrada

Funcionalidades que não fazem parte do Classe istream


núcleo da linguagem Sobrecarrega operador >>

Definidas através do arquivo de cabeçalho extração ou get from


iostream.h Definido na classe base com lado direito


correspondente a todos os tipos básicos da
declara os objetos associados aos linguagem


dispositivos padrões de entrada e saída qualquer outro tipo: deve ser definido como obter valores

cin − entrada padrão por default, ignora espaços em branco

cout − saída padrão se não quiser ignorar, usar métodos da classe

cerr −saída padrão de erros (sem buffer) get(), getline(), read()


clog − saída padrão de erros (com buffer)
Manipuladores de streams Formatação



ostream& flush(ostream&) métodos da classe ios



efetiva qualquer pendência nos buffers de afetam próxima operação apenas


saída width(int w) e int width()



ostream& endl(ostream&) largura de campo de apresentação


escreve nova linha e flush fill(char) e char fill()


setw(int) caráter de preenchimento da largura


precision(int) e int precision()


define máxima quantidade de elementos na
leitura precisão de apresentação de valores reais


char name[MAX];


cin >> setw(MAX−1) >> name;

Estados de streams Formatação

Definidos na classe base ios métodos da classe ios

comum a istream e ostream flags(long) e long(flags)



Métodos flags para controle de formato:



left, right


int eof() dec, oct, hex

fim de arquivo showbase

int fail() uppercase





scientific, fixed

próxima operação falhará


associados a manipuladores


int bad() cout << hex << 27 << endl;


stream corrompido
Arquivos de leitura Arquivos de entrada e saída



Declarações em fstream.h Classe fstream



arquivo seqüencial de entrada: ifstream Derivada de fstreambase e de iostream



construtor recebe um argumento char* (nome):
class ifstream : public fstreambase, public istream {
Todas as classes incorporam um método
ifstream(const char *nome, int mode=ios::in, int
open() com a mesma assinatura do
prot=0664) : fstreambase(nome, mode, prot); construtor


...
Método close() definido na classe base
}


(virtual) ios
modos alternativos de abertura


segundo argumento com valores de constantes
definidas em ios (ios::binary)

Arquivos de saída Programação orientada a


objetos com C++


Arquivo seqüencial de saída: ofstream


construtor recebe um argumento char* (nome)
class ofstream : public fstreambase, public ostream {
ofstream(const char *nome, int mode=ios::out, int
prot=0664) : fstreambase(nome, mode, prot); Templates
...
}


segundo argumento com valores de constantes
definidas em ios


ios::binary, ios::nocreate, ios::ate, ios::trunc
O que é um template? Motivação



Mecanismo específico de C++ para Considere a definição de uma classe
definição de classes e algoritmos que ArrayInt que verifica se índice de acesso
manipulem qualquer tipo está entre limites válidos



originalmente, baseado em macros e pré− internamente mantém um arranjo de inteiros


processamento tamanho do arranjo definido no construtor



posteriormente, incorporado ao compilador método size() retorna tamanho do arranjo


de C++


operador de indexação [ ] sobrecarregado
Reuso de código−fonte


classes ou funções

Em outras linguagens orientadas a


objetos... Classe ArrayInt


Hierarquia de classes com raiz comum class ArrayInt {
(Object) int* A;


Smalltalk, Java


const int limite;
Estruturas de dados e algoritmos
public:
genéricos manipulam objetos da classe
raiz ArrayInt(int n=100);


uso de polimorfismo int& operator[](int index);


manipulação do tipo efetivo do objeto em int size() { return limite; }
tempo de execução
};
Métodos de ArrayInt Uso de ArrayInt
int main() {
ArrayInt::ArrayInt(int n) : limite(n) { ArrayInt ia(20);
try {
A = new int[n]; for (int i=0; i<ia.size(); ++i) ia[i] = i+1;
cout << "ia[5] = " << ia[5] << endl;


}
cout << ia[35] = " << ia[35] << endl;
int& ArrayInt::operator[](int index) { }
catch(IndexOutOfBounds* iof) {


if (index < 0 || index >= limite) cout << Acesso a posicao " << iof−>pos() <<


throw new " em array de "<< iof−>max() << " posicoes.


<< endl;
IndexOutOfBounds(index,limite); }
return A[index]; }
}

Classe auxiliar: IndexOutOfBounds Reuso de código


class IndexOutOfBounds { Como oferecer a mesma funcionalidade


int index; para outros tipos de arranjos?

int limite; definir classes similares para cada tipo


public: básico: ArrayChar, ArrayShort, ...,
IndexOutOfBounds(int i, int l) { ArrayDouble

repetir procedimento para classes de outros tipos:


index = i; limite = l;
ArrayOstream, ArrayIstream, ArrayComplex, etc.

}
usar o mecanismo de template
int pos() { return index; }
int max() { return limite; }
};
Definição de template de classes Métodos da classe parametrizada



Definição da classe é precedida pela Método size( ) foi definido inline


palavra−chave template nenhuma indicação especial foi necessária



Após a palavra−chave template, indicação Para os métodos definidos externamente
do tipo de parâmetros para a definição à classe, é preciso indicar que definição é
entre < e > de classe parametrizada






class ou typename usar template<class tipo>



Segue a definição da classe, usando o


mesmo que parâmetro tipo não esteja sendo
parâmetro indicado no lugar do tipo


utilizado no método
variável

Classe parametrizada Array Métodos de Array

template<class T> template<class T>


class Array { Array<T>::Array(int n) : limite(n) {
T* A; A = new T[n];
const int limite; }
public: template<class T>
Array(int n=100); T& Array<T>::operator[](int index) {
T& operator[](int index); if (index < 0 || index >= limite)
int size() { return limite; } throw new IndexOutOfBounds(index,limite);
}; return A[index];
}
Uso de Array Constantes em templates
int main() {


Array<int> ia(20); // arranjo de 20 ints Constantes podem ser passadas como
Array<double> da(30); // arranjo de 30 doubles argumentos para template
try {
template<class T, int limite=100>
for (int i=0; i<ia.size(); ++i) da[i] = ia[i] = i+1;


cout << ia[35] = " << ia[35] << endl;
class Array {
} T A[limite];
catch(IndexOutOfBounds* iof) { public:


cout << Acesso a posicao " << iof−>pos() << T& operator[](int index);


" em array de "<< iof−>max() << " posicoes.
<< endl; int size() { return limite; }
} };
}

Templates e arquivos de
cabeçalho Constantes em templates


template<class T, int limite>
Definições de classes parametrizadas e T& Array<T,limite>::operator[](int index) {
seu código podem normalmente estar
if (index < 0 || index >= limite)
presentes em um arquivo de cabeçalho


throw new IndexOutOfBounds(index,limite);
código de template não é a definição ainda,
que ocorrerá com a instanciação do template return A[index];
no código da aplicação }


pode haver necessidades especiais em int main() {
colocar as definições de código de template Array<int,20> ia;
em arquivos fonte; checar compilador
Array<double,30> da;
...
Templates de funções Uso das funções parametrizadas



Definição de métodos de uma classe Seleção da função instanciada ocorre de
parametrizada especifica uma família de acordo com os tipos dos argumentos da
métodos função



um membro para cada instanciação do Exemplo 1: swap de inteiros
template int i=10, j=11;


Mesmo mecanismo pode ser aplicado a swap(i,j);


funções globais com corpo similar exceto Exemplo 2: swap de complexos
pelos tipos manipulados


complex<double> c(1,1), h(2,2);
funções parametrizadas swap(c,h);

Definindo uma função Sobrecarga de funções


parametrizada parametrizadas

Exemplo: troca de valores entre duas Se função parametrizada coexiste com


variáveis de mesmo tipo outras funções de mesmo nome

Inicialmente, procura por função com tipos na


lista de argumentos idênticos à invocação

template<class T> void swap(T& a, T& b) {


Caso falhe, procura por função
T temp = a; parametrizada que possa gerar função com
a = b; tipos na lista de argumentos idênticos à
invocação

b = temp; Caso falhe, aplica resolução padrão de


} sobrecarga com conversão de tipos

Caso falhe, sinaliza erro


Resolução de sobrecarga O que é a STL



Exemplo C++ Standard Template Library


int main( ) { conjunto de classes e algoritmos
int i=10; parametrizados


containers


double d=21;
algoritmos genéricos


swap(i,d);
iterators


} objetos função


adaptadores



Erro: não é possível gerar swap(int,double); alocadores

Programação Orientada a Containers


Objetos com C++

Um container é um objeto que armazena


coleções de outros objetos

Uma visão geral da


eventualmente, outros containers

biblioteca de templates
padrões Dois tipos de containers em STL

containers de seqüências

(STL)
containers associativos ordenados
Containers de seqüências deque<T>



Organizam uma coleção de objetos de Oferece acesso direto a uma seqüência
mesmo tipo em uma estrutura linear de de comprimento variável


tamanho variável tempo de leitura de um elemento em


Podem ser de três tipos: qualquer posição não depende da posição


vector<T> Tempo de inserção e de remoção de


deque<T> elementos é constante para o início e para


list<T> o final da seqüência

vector<T> list<T>

Oferece acesso direto a uma seqüência Tempo de acesso a uma posição na


de comprimento variável seqüência varia linearmente com o


tempo de leitura de um elemento em comprimento da seqüência

qualquer posição não depende da posição Tempo de inserção e de remoção de


Tempo de inserção e de remoção de elementos é constante para qualquer
elementos é constante apenas para o final posição da seqüência
da seqüência
Containers associativos ordenados map<Key, T>, multimap<Key, T>



Definem coleções de objetos de tamanho map<Key, T>


variável com rápida recuperação baseada permite a recuperação rápida de um tipo T
em valores de chaves com base no valor da chave de tipo Key


set<Key> sem repetição de valores de chaves


multiset<Key> multimap<Key, T>



map<Key, T> como map<Key, T>, porém permitindo a


multimap<Key, T> replicação de valores de chaves

set<Key>, multiset<Key> Algoritmos genéricos

set<Key> Complementam a definição de containers

define coleções de objetos (chaves) sem oferecem funcionalidade genérica


repetição de valores (algoritmo)

rápido tempo de recuperação Trabalham igualmente com containers,


multiset<Key> arranjos e strings

define coleções de objetos onde a repetição classe string


de chaves é permitida definida com uma seqüência de caracteres


rápido tempo de recuperação
Exemplos de algoritmos genéricos Exemplos de algoritmos genéricos


fill search


preenche um trecho de uma coleção com o tenta localizar a ocorrência de uma faixa de
mesmo valor repetido múltiplas vezes valores em uma faixa da coleção


generate min_element


preenche um trecho de uma coleção com o localiza o menor valor em uma faixa da
valor de retorno de uma função especificada coleção


count max_element


produz o número de elementos que, em um localiza o maior valor em uma faixa da
trecho da coleção, satisfaz um predicado coleção

Exemplos de algoritmos genéricos Exemplos de algoritmos genéricos

copy replace

copia trechos de uma coleção especificada varre uma faixa da coleção trocando o valor
para outra coleção especificado (se ocorrer) pelo novo valor

copy_backward replace_if

como copy, mas em ordem inversa como replace, mas em função de um


predicado especificado ser verdadeiro para o
reverse


valor armazenado na coleção

reverte a ordem de um trecho da coleção


equal

rotate


verifica se duas faixas têm os mesmos
troca dois trechos de uma coleção valores na mesma ordem
Exemplos de algoritmos genéricos Iteradores



remove Base para operação dos algoritmos


rearranja a coleção de forma que os



genéricos


elementos removidos estejam no final,
retornando a indicação da nova posição final oferecem referências a posições nas
coleções



unique


Cinco categorias


remove elementos duplicados da coleção
Input iterators



sort, stable_sort Output iterators



ordenam elementos na faixa especificada da Forward iterators


coleção
Bidirectional iterators


Random access iterators

Exemplos de algoritmos genéricos Input e output iterators

binary_search Input iterator

realiza busca binária em faixa ordenada da Requer a implementação dos operadores


coleção


igualdade: ==, !=

merge conteúdo de (leitura): *

combina elementos de duas coleções avanço: ++ (forma pré−fixa e pós−fixa)


ordenadas, com resultado ordenado


Output iterator

set_union, set_intersection, set_difference Requer a implementação dos operadores

operações de conjuntos sobre coleções conteúdo de (escrita): *


ordenadas avanço: ++ (forma pré−fixa e pós−fixa)


Forward, bidirectional e random
access iterators Adaptadores



Forward iterator Componente que modifica a interface de


avanço: ++ (forma pré−fixa e pós−fixa) outro componente


Bidirectional iterator exemplos:


reverse_iterator, para inverter a ordem de
engloba forward iterator varredura de um iterador



retrocesso: −− (forma pré−fixa e pós−fixa) stack_adaptor ou queue_adaptor, para restringir a


política de acesso a um container


Random access iterator


binder, para converter um objeto função de binário
engloba bidirectional iterator para unário fixando o valor de um dos operandos


+, − , +=, −=, <, >, <=, >=

Objetos função Alocadores

Funções que podem ser passadas como Classes associadas a containers com o
argumentos para os algoritmos genéricos objetivo de isolar os detalhes internos de


especificando operações binárias, predicados armazenamento


Genericamente, pode ser também manipulação de ponteiros e referências é
oculta pelos métodos dos alocadores

qualquer objeto de uma classe cujo


eventualmente (raramente), classe poderia
operador de chamada de função, ( ), ter implementação alternativa ao default de
tenha sido sobrecarregado STL para suportar outro modelo de alocação
Programação Orientada a Para onde ir daqui?


Objetos com C++
Prática


não se domina uma linguagem de
programação na teoria


Comentários finais
Domínio da linguagem de programação
não garante sucesso de desenvolvimento


aplicação de técnicas sólidas de projeto e de
implementação


design patterns, extreme programming


trabalho em equipes


com forte gerência de projetos

C++ e outras linguagens


Tempo de desenvolvimento de aplicações
relativamente longo


Uso eficiente de memória


metade do uso de código equivalente em
linguagem script, um terço de Java


Execução mais rápida


cerca de duas vezes mais rápido que Java


Fonte: An empirical comparison of seven programming
languages (Lutz Prechelt), IEEE Computer, October
2000

Potrebbero piacerti anche