2. Visão Geral
● Histórico da Linguagem
● Programa C++: header, source – função main()
● GCC/G++
● Arquivos objeto, bibliotecas dinâmicas e estáticas
● #include, #define, namespaces, typedefs
● Ponteiros, Referências, arrays, primitivas,
estruturas de controle.
3. Características do C++
● Linguagem multi-paradigma
● Programação Procedural
● Orientação a objetos
● Meta Programação
● Desalocação memória – Decisão cabe ao
programador
4. Histórico
● Criada por Bjarne Stroustrup em 1979 no Bell Labs
da AT&T e inicialmente chamada de “C with classes”.
● Em 1983 passou a ser chamada C++.
● Ao longo do tempo incorporou novas funcionalidades
como:
– herança múltipla,
– sobreescrita de operadores,
– templates
– entre outras coisas que veremos ao longo do curso.
5. Histórico
● Possui compatibilidade com C
– um compilador C++ deve compilar um programa
escrito em C.
● Em 1998 foi definido um padrão ISO para a
linguagem, revisado em 2003 e novamente
revisado em 2011.
6. GCC/G++
● GNU Compiler Collection
● Compilador originalmente desenvolvido
focando a linguagem C, chamava-se GNU C
Compiler.
● Ao longo do anos passou a contemplar
outras linguagens, como C++.
7. Programa C++ - Arquivos
● Header – Definições / Visível a outros headers
● Sources – Corpo de métodos e funções
● Função Main – Função inicial evocada pelo
executável
8. Programa C++ - Hello World
//file – hello_world.cc
#include <iostream>
int main(){
std::cout<<”Hello World!”<<std::endl;
return 0;
}
9. Programa C++ - Compilando o Hello
World
$ g++ hello_world.cc -o hello_world
$ ./hello_world #executando
$ Hello World! #resultado
10. Bibliotecas Estáticas e Dinâmicas
● Estática:
– o código executável copia os trechos com
instruções que utiliza. O executável pode ficar
grande.
● Dinâmica:
– A linkagem ocorre em tempo de execução. O
executável acessa a biblioteca durante as
chamadas de funções.
11. Diretivas
● Informações sobre arquivos, símbolos e tipos
interpretadas no pré-processamento da compilação.
● #include
– Avisa ao compilador quais headers ele precisa carregar para
pré-processar as instruções do arquivo em questão, mais ou
menos como o import do Java
– Pode ser utilizado tanto no header quanto no source. Evite
incluir includes desnecessário no header, torna a etapa de
análise mais custosa.
12. Diretivas - Include
#include “structs/my_struct.h”
int main(){
myStruct ms;
}
$ g++ include.cc
#include “my_struct.h”
int main(){
myStruct ms;
}
$ g++ include.cc -I structs
13. Diretivas - Include
● #include <list>
– Procura o header nos diretórios do sistema e
aqueles passados como parâmetro ao compilador.
● #include “my_struct.h”
– Procura o header primeiro no diretório que contém
o arquivo sendo compilado, e depois nos diretórios
do sistema e aqueles passados como parâmetro ao
compilador.
14. Diretivas: #define
● Atribui um valor a um símbolo.
● Cada vez que o pré-processador encontra este
símbolo no código ele substitui o símbolo por
esse valor.
#define max_iterations 1000
15. Diretivas: #define
● Também pode ser usado para definir “macros”, pequenos
trechos de código que são colados cada vez que o pré-processador
identifica o símbolo associado.
#define getmax(a,b) ((a)>(b)?(a):(b))
int main(){
int x = 10;
int y = getmax(x,5);
//y vale 10
}
16. Diretivas: #define
#define getmax(a,b) ((a)>(b)?(a):(b))
/*int main(){
int x = 10;
int y = getmax(x,5);
//y vale 10
}*/
int main(){
int x = 10;
int y = ((x)>(5)?(x):(5));
//y vale 10
}
17. Diretivas: #define
● Quando e por que usar Macros?
– Quando o código é pequeno e existe um real
conhecimento do fluxo das instruções.
– Desgraças podem acontecer e o código colado pelo
pré-processador pode tomar um rumo inesperado.
– Como o código é “colado”, não existe ônus de ter que
colocar o endereço da instrução na pilha como em
uma chamada de função. Em uma próxima aula
discutiremos isso ao ver funções inline.
18. namespace
● Estabelecem o domínio ao qual declarações
(classes, structs, metaclasses) fazem parte.
● É utilizado para organizar o código em
diferentes domínios, que dependendo da
estrutura de diretórios do código fonte, podem
apresentar uma semelhança com a
organização em pacotes do java.
● Também serve para eliminar ambigüidades.
20. using
● Usada para suprimir a declaração de namespaces no código
#include <list>
#include <iostream>
#include “my_list.h”
using namespace std;
int main(){
cout<<”hello world”<<endl; //ok!
list<int> list1; //ambigüidade
list<int> list2; //ambigüidade
}
22. typedef
● Define um tipo a partir de outro existente.
#include <list>
#include “data_structure/my_list.h”
#include <iostream>
using namespace std;
typedef data_structure::list<int> mylist;
int main(){
cout<<”hello world”<<endl; //ok!
list<int> list1; //ok - std::list
mylist list2; //ok - data_structure::list
}
23. Tipos Primitivos
● Inteiros com e sem sinal e bits de
representação:
– char, unsigned char: 8 bits
– short, unsigned short: 16 bits (mínimo)
– int, unsigned int: 32 bits (mínimo)
– long, unsigned long: 32 bits (mínimo)
– long long, unsigned long long: 64 bits (mínimo)
24. Tipos Primitivos
● Ponto flutuante e bits de representação:
– float: 32 bits
– double: 64 bits
25. Ponteiros e referências
● int a = 10; //aloca espaço para a variável a
● int * b = &a;
● /*cria um ponteiro b para números inteiros.
Um ponteiro aloca espaço para e o reserva
para armazenar um endereço. */
● Memória:
10
6
26. Variáveis, Ponteiros e Referências
#include <iostream>
int main(){
int a = 5;
int * b = &a;
std::cout<<”O valor de a é”<<a<<” o endereço de a é“<<&a<<std::endl;
std::cout<<”b contém o endereço”<<b<<” o conteúdo do endereço de b
é:”<<*b<<std::end;
}
27. Variáveis, Ponteiros e Referências
*b += a;
a *= (*b);
std::cout<<a<<std::endl;
//O que foi impresso??
28. Variáveis, Ponteiros e Referências
● Uma referência é como um “apelido” a uma outra
variável.
● Tal qual um ponteiro, a referência apenas
“referencia” algum endereço de memória.
● Uma vez criada, não há como distinguir entre uma
referência e o dado por ela referenciado.
● Adicionalmente, uma referência só pode “apontar
para” um único dado durante sua existência.
29. Variáveis, Ponteiros e Referências
● int main(){
int a = 3;
int b = 4;
int * p = &b;
int & r = b;
r += 2; // b agora vale 6
p = &a; // p aponta para “a”
r = a; // b agora vale 3; r ainda referencia b.
}
30. Arrays – Alocação Estática
int main(){
int a[5];
a[0] = 0;
a[4] = -3;
}
31. Arrays – Alocação dinâmica
● int main(){
int a =5;
int * b = new int[a];
}
32. Arrays - Iterando
int main(){
int a = 5;
int * b = new int[a];
int * it = &b[0];
(*it++) = 8; //Quais operações são executadas
nessa linha?
}
33. Arrays - Iterando
int * it = &b[0]; //faz o iterador apontar para o endereço da
posição 0 de b;
//int * it = b;
(*it++) = 8;
//(*it) = 8 atribui o valor 8 a posição 0 do array b incrementa o
iterador, fazendo-o apontar para a posição 1 de b
34. Arrays - Iterando
int * it = &b[0]; //faz o iterador apontar para o
endereço 9;
(*it) = 8; //atribui o valor 8 ao dado contido no
endereço 9
it++;//incrementa o iterador, fazendo-o apontar
para o endereço 10
it
35. Statements
if( expressão booleana ){
//se a expressão é verdadeira executa este bloco
} else{
//se a expressão é falsa executa este bloco
}
36. Statements
while( expressão booleana ){
//enquanto a expressão for verdadeira executa este bloco
}
do{
//enquanto a expressão for verdadeira executa este bloco
}while( expressão booleana );
37. Statements
for( inicialização de variáveis ; expressão ;
operação executada a cada loop ){
//Para cada vez que a expressão for verdadeira,
executa esse bloco. Se a expressão for falsa, sai
do bloco.
}
38. enumerations
● Coleção de constantes definidas pelo usuário
enum Paises{
Argentina,
Brasil,
China,
Estados Unidos,
Inglaterra
}
39. enumerations
● Coleção de constantes definidas pelo usuário
enum Paises{
Argentina=9,
Brasil=6,
China=5,
Estados Unidos=13,
Inglaterra=10
}
40. switch case
int a;
switch (a){
case:1
//se a vale 1, executa este bloco
break;
case:2
//se a vale 2, executa este bloco
break;
default:
//se a vale qualquer outro inteiro, executa este bloco
}