Buscar

Curso C++

Esta é uma pré-visualização de arquivo. Entre para ver o arquivo original

PROG003.CPP
// Terceiro programa C++
// Curso de Linguagem de Programa‡Æo C++ PROG003.CPP - Silvio Sabino
#include<iostream.h> // incluindo iostream.h para utilizar a classe cout
// fun‡Æo que retorna a soma de 2 n£meros cujos valores
// sÆo passados como parƒmetros
int adicao (int a, int b){
	// declarando a vari vel que conter  o valor da soma
	// dos dois parƒmetros "a" e "b"
	int resultado;
	// atribuindo o valor da adicao de "a" e "b" … vari vel resultado
	resultado = a + b;
	// retornando o valor contido na vari vel "resultado" para
	// o processo anterior, que nesse caso ‚ a fun‡Æo main( )
	return resultado;
	}
	// fun‡Æo principal do programa onde ‚ iniciada a execu‡Æo
	void main(void){
		// declarando duas vari veis do tipo inteiro
		int n , m, soma;
		// pedindo para o usu rio o valor de "n"
		cout << "\nDigite o 1§ n§: ";
		cin >> n;
		// pedindo para o usu rio o valor de "m"
		cout << "Digite o 2§ n§: ";
		cin >> m;
		// passando "n" e "m" como parƒmetros para que a fun‡Æo soma(int, int)
		// calcule a soma dos dois valores e retorne o resultado que ‚ atribu¡do
		// … vari vel soma
		soma = adicao (n, m);
		// imprimindo o valor de "soma" na tela
		cout << "A soma ‚: " << soma;
		// retornando o processo anterior, no caso o sistema operacional
		return;
		}
		// Fim do programa
PROG023.CPP
// Introdu‡Æo ao modo gr fico - Fun‡Æo do 2o. grau
// Curso de Linguagem de Programa‡Æo C++ PROG023.CPP - Silvio Sabino
#include<graphics.h>
#include<iostream.h>
#include<conio.h>
// parƒmetros e vari vel da fun‡Æo
float *p, x;
// retornando o valor da fun‡Æo do segundo grau
float bhaskara(void){
	return(p[0]*x*x+p[1]*x+p[2]);
}
// desenhando o gr fico na tela em escala 10:1
// observe o uso de continue
void plot(float (*funcao)(void)){
	float y;
	for(x=-32;x<32;x+=0.0001){
		if((y=funcao())>24||y<-24)continue;
		putpixel(x*10+320,y*10+240,15);
	}
}
void main(void){
	//declarando um int register para uso nos la‡os
	 register int i;
	// para a fun‡Æo espec¡fica
	float (*funcao)(void)=bhaskara;
	// alocando espa‡o para 3 parƒmetros da fun‡Æo
	p=new float[3];
	// limpando a tela
	clrscr();
	//solicitando os dados para o usu rio
	for(i=0;i<3;i++){
		cout << "Digite o parƒmetro \""<<(!i?"A":i==1?"B":"C")<<"\": ";
		cin >> p[i];
	}
	//iniciando o modo gr fico
	int d=DETECT,m;
	initgraph(&d,&m,"C:\\ARQUIV~1\\TC\\BGI");
	// especificando azul como cor de fundo azul e
	// cinza claro como cor da linha
	setbkcolor(1);
	setcolor(7);
	// desenhando os eixos na tela
	line(0,240,639,240);
	line(320,0,320,479);
	for(i=0;i<640;i+=10){
		line(i,238,i,242);
		if(i<480)line(318,i,322,i);
	}
	// chamando a fun‡Æo que desenha o grafico
	plot(funcao);
	// esperando o usuario pressionar um tecla
	getch();
	// fechando o modo grafico
	closegraph();
}
PROG020.CPP
// Sobrecarga de operador, uso da classes, construtor e destrutor
// Curso de Linguagem de Programa‡Æo C++ PROG020.CPP - Silvio Sabino
#include<string.h>
#include<iostream.h>
// criando uma struct para representar n£meros complexos
struct complex{
	double real; // parte real
	double imag; // parte imagin ria
	// construtor para a classe complex com argumento padrÆo
	complex(double real, double imag=0){
		this->real=real;
		this->imag=imag;
	}
	// construtor sobrecarregado sem argumentos
	complex(void){
		real=0;
		imag=0;
	}
};
// criando a classe string para ser utilizada como parƒmetro
// de operator
class string {
	// ponteiro para char manipulado pelo objeto
	// nenhuma outra parte do programa pode acessar diretamente
	// o conte£do desse ponteiro
	char *str;
	//comprimento m ximo permitido
	int n;
	// tornando p£blicas as fun‡äes do objeto para que o programa
	// possa invoc -las
	public:
	// atribuindo uma cadeia … str
	// note como o argumento str ‚ diferenciado do ponteiro str que
	// faz parte do objeto usando-se o ponteiro this
	int setstr(char *str){
		if(!this->str||n<strlen(str))return(1);
		strcpy(this->str,str);
		return(0);
	}
	//obtendo o conte£do de str
	// o uso do ponteiro temp evita que o processo externo
	// obtenha o endere‡o de str, podendo obter apenas o
	// conte£do apontado por ele
	char *getstr(void){
		char *temp=new char[strlen(str)+1];
		return(strcpy(temp,str));
	}
	// sobrecarregando + para concatenar strings
	char *string::operator+(string &str1){
		char *temp=new char[strlen(str)+1];
		strcpy(temp,str);
		return(strcat(temp,str1.getstr()));
	}
	// construtor da classe, que aloca mem¢ria
	// de acordo com o n£mero de itens informado
	// pelo processo anterior
	string(int itens=0){
		n=itens;
		str=n?new char[n]:NULL;
	}
	// liberando o espa‡o alocado para o ponteiro str
	// e destruindo o objeto
	~string(void){
		if(str)delete(str);
	}
};
// sobrecarregando o mesmo operador para somar as partes real
// e imagin ria de dois n£meros complexos
complex operator+(complex n1, complex n2){
	return(complex(n1.real+n2.real,n1.imag+n2.imag));
}
// programa principal
void main(void){
	// declarando objetos de classe string
	string string1(11),string2(11),string3(22);
	// declarando estruturas do tipo complex
	complex c1(5,8), c2(2.4), c3;
	string1.setstr("string1");
	string2.setstr(" + string2");
	// utilizando a sobrecarga do operador + para concatenar as strings
	string3.setstr(string1+string2);
	c3=c1+c2;
	cout << "\nresultado com *char : " << string3.getstr();
	cout << "\nresultado com complex: " << c3.real << " " << c3.imag;
}
PROJ01.PRJ
PROG022.CPP
// Arquivos em C++
// Curso de Linguagem de Programa‡Æo C++ PROG022.CPP - Silvio Sabino
// inserindo arquivos cabe‡alho necess rios
#include<iostream.h>
#include<stdio.h>
#include<conio.h>
#include<ctype.h>
#include<string.h>
// definindo constantes para facilitar o entendimento
#define ALTERA 0
#define EXCLUI 1
#define LISTA 2
FILE *arq; //arquivo onde serÆo armazenados os dados
size_t tamanho; //vari vel que guardar o tamanho da estrutura "colaborador"
// estrutura para referenciar o registro
struct colaborador{
	int reg;		// registro na empresa
	char nome[41]; 	// nome do colaborador
	char CPF[12]; 	// cadastro de pessoa f¡sica(CPF)
};
// testa fim de arquivo e leitura
int teste_fluxo(colaborador &empr,FILE *str){
	return(!feof(str)&&fread(&empr,tamanho,1,str)==1);
}
// exibe os dados de um colaborador na tela
void exibir(colaborador c){
	cout <<c.reg<<" - "<<c.nome<<" - "<<c.CPF<<"\n";
}
// testa abertura do arquivo
int abrir(void){
	//tenta abrir o arquivo para atualização ou cria novo arquivo
	if(!(arq=fopen("C:\\exemplo.txt","a+"))){
		cout << "Erro não abrir arquivo. Pressione qualquer tecla p/ voltar";
		getch();
		return(1);
	}
	return(0);
}
// exibe um menu na tela para que o usu rio realize a escolha
char menu(void){
	// variável estática para identificar a primeira chamada
	static char opcao=0;
	// testando se ‚ a primeira chamada ou o usu rio encerrou a sessÆo
	if(opcao&&opcao!=54)fclose(arq);
	// limpando a tela
	clrscr();
	// exibindo o menu
	cout << "\nPrograma exemplo de manipula‡Æo de arquivos\n\n";
	cout << "1) Inserir\n";
	cout << "2) Consultar\n";
	cout << "3) Alterar\n";
	cout << "4) Excluir\n";
	cout << "5) Listar\n";
	cout << "6) Sair";
	// esperando a op‡Æo do usu rio.
	// o programa nÆo ir  adiante enquanto o usu rio nÆo efetuar
	// uma escolha v lida
	do{
		gotoxy(1,10);
		cout << "Tecle a sua op‡Æo.";
		opcao=getch();
	}while(opcao<49||opcao>54);
	// se o usu rio nÆo deseja encerrar a sessÆo, abre-se o arquivo
	// e se houver erro o usu rio ser  avisado, voltando para o menu
	if(opcao!=54&&abrir())return(-1);
	// retornando para main()
	return opcao;
}
// inserindo um colaborador
void insere(void){
	colaborador novo;
	// solicitando
a entrada de dados para o usu rio
	cout << "\nInforme o registro: ";
	cin >> novo.reg;
	cin.getline(novo.nome,40);
	cout << "\n\nInforme o nome: ";
	cin.getline(novo.nome,40);
	cout << "\nInforme o CPF: ";
	cin.getline(novo.CPF,11);
	// gravando os dados em arquivo
	fwrite((void*)&novo,tamanho,1,arq);
}
// consultando os dados armazenados
void consulta(void){
	char opcao;
	//perguntando ao usu rio qual o chave de consulta desejada
	//a instru‡Æo do-while somente terminar  quando a resposta for v lida
	do{
		gotoxy(1,12);
		cout << "Deseja consultar por nome, CFP ou registro (N/C/R)?";
		opcao=toupper(getch());
	}while(opcao!='N'&&opcao!='C'&&opcao!='R');
	//solicitando agora a entrada do dado a ser consultado
	//observe o uso do operador tern rio ?:
	cout <<"\n\n"<<(opcao=='N'?"Nome: ":opcao=='C'?"CPF: ":"Registro: ");
	colaborador cons,temp;
	if(opcao=='R')cin >> cons.reg;
	else cin.getline(opcao=='N'?cons.nome:cons.CPF,opcao=='N'?40:11);
	cout <<"\n";
	rewind(arq);
	//pesquisando o arquivo e exibindo os dados que satisfazem … consulta
	while(teste_fluxo(temp,arq))if(
		(opcao=='N'&&!strcmp(cons.nome,temp.nome))||
		(opcao=='C'&&!strcmp(cons.CPF,temp.CPF))||
		(opcao=='R'&&cons.reg==temp.reg)){
			exibir(temp);
	}
	//deixando o usu rio decidir quando voltar ao menu
	cout <<"\nPressione qualquer tecla para voltar ao menu";
	getch();
}
//alterando, excluindo ou listando os dados gravados
void modifica(int z=ALTERA){
	int reg,opcao;
	colaborador temp;
	//como o registro ‚ £nico para cada colaborador, as opera‡äes de
	//altera‡Æo e exclusÆo sÆo direcionadas por esse campo
	if(z!=LISTA){
		cout <<"\nInforme o no. do registro: ";
		cin >>reg;
	}
	else cout <<"\n\n";
	//criando um arquivo tempor rio para auxiliar as opera‡äes de
	// altera‡Æo e exclusÆo
	FILE *tmp=tmpfile();
	// pesquisando o arquivo e efetuando a opera‡Æo desejada
	while(teste_fluxo(temp,arq)){
		// se foi pedida a listagem, entÆo todos os dados sÆo exibidos
		if(z==LISTA)exibir(temp);
		//senÆo, ‚ executada a a‡Æo somente no colaborador informado
		else if(temp.reg==reg){
			if(z==ALTERA){
				do{
					gotoxy(1,11);
					cout <<"\n\nAlterar nome ou CPF (N/C)?";
					opcao=toupper(getch());
				}while(opcao!='N'&&opcao!='C');
				// novamente o uso extensivo do operador tern rio ?:
				cout <<"\n"<<"Novo "<<(opcao=='N'?"nome: ":"CPF: ");
				cin.get(temp.CPF[11]);
				cin.getline(opcao=='N'?temp.nome:temp.CPF,opcao=='N'?40:11);
			}
			cout 	<<"Registro "<<(z==ALTERA?"alterado. ":"exclu¡do. ");
		}
		if(temp.reg!=reg||z==ALTERA)fwrite(&temp,tamanho,1,tmp);
	}
	//reescrevendo os dados reorganizados no arquivo de origem
	if(z!=LISTA){
		fclose(arq);
		arq=fopen("C:\\Exemplo.txt","wb+");
		rewind(tmp);
		while(teste_fluxo(temp,tmp))fwrite(&temp,tamanho,1,arq);
	}
	// se foi pedida a lista, entÆo somente ‚ impresso o caractere nova linha
	else cout <<"\n";
	fclose(tmp);
	cout <<"Pressione qualquer tecla p/ voltar.";
	getch();
}
// programa principal
void main(void){
	// obtendo o tamanho da estrutura colaborador
	// isto ‚ £til porque economiza c¢digo e chamadas de fun‡Æo
	tamanho=sizeof(colaborador);
	// o programa fica esperando o usu rio escolher a a‡Æo
	// e direciona a a‡Æo conforme e sua op‡Æo
	for(;;)switch(menu()){
		case '1': insere();
				break;
		case '2': 	consulta();
				break;
		case '3': 	modifica();
				break;
		case '4': 	modifica(EXCLUI);
				break;
		case '5': 	modifica(LISTA);
		case -1:	break;
		case '6': 	return;
	}
}
// fim do programa
PROJ01.DSK
C++.doc
Linguagem de Programação	C++
Básico�
Sumário
		Linguagens de programação – História de C	____________
		3
		Características da linguagem C	______________________
		4
		A linguagem C++	________________________________
		5
		Fundamentos de C++	___________________________
		6
		Dados Padrões	________________________________
		10
		Tipos definidos e estruturas de dados	_________________
		11
		Modificadores de dados	___________________________
		13
		Conversões de dados	___________________________
		14
		Classes de armazenamento	______________________
		15
		Matrizes	_____________________________________
		16
		Operadores	_____________________________________
		17
		Controle de fluxo	________________________________
		22
		Ponteiros	_____________________________________
		27
		Funções	_____________________________________
		30
		Diretivas do pré-processador	______________________
		36
		Arquivos	_____________________________________
		37
		Introdução ao modo gráfico	______________________
		41
		Palavras reservadas	___________________________
		43
�
Linguagens de programação – História de C
O computador é uma ferramenta poderosa que possui as mais variadas aplicações no mundo moderno. Encontramos sistemas controlados por computadores em quase todas as áreas do conhecimento humano, como telecomunicações, indústrias, internet, medicina, etc. Entretanto, por mais potentes e flexíveis que sejam os computadores, eles nada fariam sem que fossem orientados por listas de instruções detalhadas, interpretadas e executadas pelo processador: os programas.
Tudo que é físido em um computador é chamado hardware, e tudo que ele entende são dois estados de tensão que chamaremos, simbolicamente, de 0 e 1 (esses valores foram adotados somente para facilitar o entendimento). Todos os processadores possuem a sua linguagem de máquina (ou código binário), um conjunto de sequências de “zeros” e “uns” que produzem determinadas ações. É possível escrever programas em linguagem de máquina, mas seria uma tarefa improdutiva porque para que o processador execute tarefas comuns é necessário escrever muito código. Com o aumento da necessidade de programas, criaram-se as linguagens de programação, códigos intermediários entre a linguagem humana e a da máquina. Assim surgiram as linguagens Assembly, ADA, PL/I, CPL, BCPL, B, C, C++, Pascal, e muitas outras. As linguagens de programação podem estar mais próximas da linguagem de máquina ou da humana. Quanto mais próxima da linguagem humana, maior o nível de uma linguagem de programação. A linguagens sofisticadas para ambientes visuais como Visual Basic e Delphi são de altíssimo nível por estarem muito longe do código binário. Os programas de computador também podem ser chamados de softwares.
Para que o computador interprete os programas escritos em uma linguagem de programação, eles devem ser traduzidos em linguagem de máquina. Isso pode ser feito por compilação ou interpretação. A linguagem é compilada quando o programa é traduzido inteiramente para a linguagem de máquina antes da execução, e interpretada quando a tradução é feita linha por linha durante a execução. Linguagens interpretadas tendem a ser mais lentas porque a tradução durante a execução representa um trabalho extra.
A linguagem C foi desenvolvida nos Laboratórios Bell por Dennis Ritchie em 1972. Sua origem está muito ligada ao sistema operacional UNIX, escrito inicialmente em 1969 em linguagem montadora. 
Para entendermos como a linguagem C surgiu, devemos retroceder para o Algol 60, projetado em 1960 por um Comitê Internacional. Essa linguagem possuía objetivos elevados para os computadores da época e por isso nunca foi muito utilizada. Para trazer o Algol 60 mais próxmo da realidade, surgiu tanto em Londres quanto em Cambridge em 1963 a linguagem CPL, que também fracassou por ser muito difícil. Por isso Martim Richards criou em 1967 a linguagem BCPL, uma versão mais simples do CPL. Logo depois, Ken Tompson desenvolveu linguagem B, ainda mais simples que a BCPL, para reescrever o sofisticado sistema UNIX. Ainda havia uma problema: B e BCPL tornaram-se linguagens
limitadas, úteis apenas para alguns tipos de problemas.
Devido a esses e outros contratempos, como imcompatibilidade com alguns tipos de hardware, Dennis Ritchie desenvolveu a sucessora de B, chamada de C.
Com a nova linguagem, um mundo rico em possibilidades foi aberto aos novos programadores de sistemas. C permitia o contato íntimo com a máquina enquanto possibilitava implementar instruções de alto nível nos mesmos programas, ou seja: uma linguagem de baixo e alto nível simultaneamente.
�
Características da linguagem C
C pode ser considerada a principal linguagem orientada para máquinas. Diversamente de linguagens criadas para aplicações específicas, como FORTRAN, que são orientadas para problemas, C possui flexibilidade suficiente para implementar soluções para os mais variados tipos de problemas nos mais diversos hardwares.
As linguagens de alto nível permitiram que o programador se concentrasse no problema que tinha que resolver, deixando a manipulação da máquina para o compilador ou interpretador. Para a engenharia ou administração, são excelentes. No entanto, os programadores que desenvolviam sistemas ainda dependiam das indigestas linguagens montadoras de suas máquinas. Para essa classe, C foi a solução definitiva em termos de produtividade e eficiência: está distante o suficiente da máquina para implementar rotinas de alto nível, e próxima o suficiente para especificar detalhes necessários para o sistema operacional. Talvez por isso a popularidade de C seja tão grande.
Dentre as vantagens de C, podemos citar: 
É uma linguagem pequena;
Pode ser de alto ou baixo nível, dependendo do ponto de vista;
Produz um código muito eficiente, comparável ao código Assembly;
Fracamente figurada, possuindo alta flexibilidade para manipulação de dados;
É estruturada, antecipando o surgimento formal desse conceito;
Suporta programação modular;
Possibilita interfaces com as linguagens Assembly e Pascal;
Apresenta operadores para manipulação de bits;
Permite notáveis implementações de aritmética de ponteiros;
Contém estruturas flexíveis de dados, limitados apenas pela necessidade;
Portabilidade para funcionar em máquinas e sistemas operacionais diferentes;
Como nenhuma linguagem de programação é perfeita, as principais desvantagens de C são:
Fracamente figurada, podendo produzir efeitos colaterais inesperados e bizarros;
Ausência de verificação de tempo de processamento.
Como surgiram muitos compiladores para a linguagem C e as variações da linguagem começaram a ameaçar a grande portabilidade de flexibilidade de C, em 1983 o ANSI padronizou a linguagem para que todos os compiladores fossem implementados segundo as mesmas regras. O ANSI manteve alguns conceitos que são conhecidos como “espírito de C”, como:
Confie no programador.
Não impeça que o programador faça o que precisa ser feito.
Mantenha a linguagem pequena e simples.
�
A Linguagem C++
Em 1980, o Dr. Bjarne Stroustrup desenvolveu a sucessora de C, a linguagem C++, que possui a base na linguagem C com idéias do Algol 68 e Simula67: operadores podem ser sobrecarregados e variáveis podem ser declaradas em qualquer ponto dentro do bloco de instruções como no Algol 68; objetos podem ser criados com funções virtuais e classes derivadas como no Simula67.
Quando foi necessário realizar algumas simulações orientadas a eventos, muito rigorosas e com conceitos inexistentes nas linguagens de programação da época como objetos e eventos, e exigindo eficiência que nenhuma linguagem existente era capaz de fornecer, nem mesmo C, um grupo liderado pelo Dr. Stroustrup começou a trabalhar na implementação de uma nova linguagem, versátil e poderosa, mas que deveria manter a compatibilidade com programas e bibliotecas escritos em C. Devido ao alcance absoluto desse objetivo, a linguagem que nascia foi considerada sucessora de C e chamada C++.
Dentre as melhorias, a mais significativa é a orientação ao objeto, mudando radicalmente os conceitos avançados de programação estruturada orientada para procedimentos, que era o caso de C. No entanto, para manter o “espírito de C”, o programador ainda é responsável por muitas verificações que são dispensáveis em outras linguagens mais rigorosas e também mais limitadas, como tamanho de vetores e matrizes, endereçamento de ponteiros, etc.
Para que possamos ter idéia do que foi modificado em relação à linguagem C, citamos as principais melhorias de C++:
Estruturas passam a ser de tipo nome, não exigindo o uso da palavra reservada na declaração;
Declarações de variáveis em qualquer lugar do bloco, desde que antes da utilização;
Operador resolução de escopo, permitindo variáveis locais de globais de mesmo nome;
Especificador const, bloqueando o valor de variáveis;
Uniões anônimas, recurso que economiza tempo e memória;
Conversões explícitas, que diminuem os efeitos colaterais de uma linguagem fracamente figurada;
Modelagem de função, especificando no cabeçalho da função os tipos de cada argumento;
Sobrecarga de função, permitindo que mais de uma função com o mesmo nome, desde que tenham tipo de retorno e/ou argumentos de tipos diferentes;
Funções com número de argumentos indefinido;
Tipo referência, facilitando o entendimento e a sintaxe;
Especificador inline, deixando que o compilador decida se pode inserir o código de um função no código em linha, economizando o tempo de chamada e armazenamento na pilha;
Operadores new e delete, melhorando a alocação dinâmida de memória;
Ponteiros void e funções tipo void, aumentando o poder dos ponteiros e formalizando funções void;
Programação orientada ao objeto;
Biblioteca stream, melhorando sensivelmente as operações de I/O.
�
Fundamentos de C++
Os programadores frequentemente relatam a dificuldade no aprendizado da linguagem C++ (bem como C), provavelmente devido à sintaxe simbólica e intimidativa. Essa queixa dificilmente acontece com Pascal, que possui uma sintaxe didática. O fato é que C e C++ foram projetadas para programadores de sistemas, ou seja, pessoas que já possuem um amplo conhecimento de lógica de programação, arquitetura e funcionamento do hardware. Mesmo assim, nada disso impede que a primeira linguagem de um programador seja C ou C++.
Todos os programas devem receber dados de alguma fonte de entrada; processar as informações recebidas por meio de instruções que podem ser divididas genericamente em: simples, condicionais, laços e funções; expressar os resultados da manipulação dos dados de entrada; possuir uma estrutura modular e nomes autodocumentados (com significado) para facilitar a manutenção e a leitura posterior feita por outros programadores.
Um programa C++ é constituído de funções, que são blocos de código cujas instruções executam ações de rotina. Também existem variáveis que são locais da memória RAM onde são armazenadas informações. Outros itens estarão presentes em um programa C++ e serão introduzidos oportunamente na compreensão da linguagem. Vamos escrever nosso primeiro programa C++, que imprime uma mensagem na tela:
// Primeiro programa C++
// Curso de Linguagem de Programação C++ PROG001.CPP - Silvio Sabino
#include<iostream.h>
void main(void){
	cout << "\nMeu primeiro programa!";
	return;
}
// Fim do programa
Vamos analisar linha a linha o conteúdo desse programa:
// Primeiro programa C++
// Curso de Linguagem de Programação C++ PROG001.CPP – Silvio Sabino
Todo programa deve possuir comentários significativos para facilitar o acompanhamento de outros programadores ou para manutenção posterior, que pode ocorrer muitos anos depois da criação do programa. Esse comentário explica o que é o programa.
#include<iostream.h>
Essa instrução
é uma diretiva do pré-processador que inclui o arquivo IOSTREAM.H no código do programa. Esse arquivo é um dos vários arquivos de cabeçalho da linguagem C++, que são bibliotecas com rotinas implementadas pelos programadores da linguagem.
void main (void){
...
}
Esse bloco de código é uma função C++. O símbolo { abre o código e } fecha o mesmo. Esses símbolos também são utilizados para laços e estruturas de controle, que veremos mais adiante. A palavra void no início da linha representa o tipo de retorno da função. Nesse caso a função não retorna nenhum valor, fato evidenciado pela palavra void. A palavra main é o identificador (nome) da função. Todos os programas C++ possuem uma única função main e a execução do programa começa sempre a partir dessa função. A palavra entra parênteses void representa os argumentos da função. Nesse caso, a função não tem nenhum argumento, o que é indicado pela mesma palavra void. Entre os delimitadores { e } do bloco, podem existir instruções que são chamadas corpo da função:
cout << "\nMeu primeiro programa!";
Essa linha invoca a stream cout (console out) definida em IOSTREAM.H, que imprime o argumento “Meu primeiro programa!” na tela. Merece atenção a presença da sequência \n que significa nova linha. C e C++ possuem uma série de caracteres especiais que são formados por barra invertida (\) seguido de uma letra ou símbolo. Eis os mais comuns:
		\a
		Beep
		\n
		nova linha
		\t
		tabulação horizontal
		\v
		tabulação vertical
		\r
		retorno de carro
		\b
		retrocesso (backspace)
		\’
		aspas simples
		\”
		aspas duplas
		\\
		barra invertida
		\f
		salta uma página
		\0
		nulo (NULL)
return;
Retorna da função para o processo anterior, no caso o sistema operacional. Essa instrução pode ser dispensada nesse caso sem nenhum aviso do compilador.
// Fim do programa
Comentário para evidenciar que o programa terminou nesse ponto.
O compilador C++ ignorará espaços repetidos, tabulações ou linhas em branco em quase todos os pontos do programa. Portanto, o mesmo programa anterior pode ser escrito de várias formas, como por exemplo:
// Primeiro programa C++
// Curso de Linguagem de Programação C++ PROG0011.CPP - Silvio Sabino
#include <IOSTREAM.H>
void main (void) {cout << "\nMeu primeiro programa!";return;}// Fim do programa
Esse programa é igualmente válido. Devemos observar que na diretiva do pré-processador não podem haver espaços entre os símbolos < > e o nome do arquivo de cabeçalho IOSTREAM.H pode ser escrito em maiúsculas. Todas as instruções C++ são terminadas em ponto-e-vírgula. Outra característica marcante na sintaxe C e C++ é a diferença entre letras minúculas e maiúsculas. Em muitas linguagens, como Pascal, não existe nenhuma diferença, mas em C++ isso é sentido pelo compilador.
Vamos agora analisar um segundo programa C++. O código apresenta declarações de variáveis e a função adicao, cuja tarefa é calcular o valor da soma de dois números passados como parâmetros. As explicações estão inseridas em forma de comentário:
// Segundo programa C++
// Curso de Linguagem de Programação C++ PROG002.CPP - Silvio Sabino
#include<iostream.h> // incluindo iostream.h para utilizar a classe cout
// função que retorna a soma de 2 números cujos valores
// são passados como parâmetros
int adicao (int a, int b){
	// declarando a variável que conterá o valor da soma
	// dos dois parâmetros "a" e "b"
	int resultado;
	// atribuindo o valor da adicao de "a" e "b" à variável resultado
	resultado = a + b;
	// retornando o valor contido na variável "resultado" para
	// o processo anterior, que nesse caso é a função main()
	return resultado;
}
// função principal do programa onde é iniciada a execução
void main(void){
	// declarando duas variáveis do tipo inteiro
	int n , m, soma;
	// atribuindo o valor 2 à variável "n" e 4 à variável "m"
	n = 2;
	m = 4;
	// passando "n" e "m" como parâmetros para que a função soma(int, int)
	// calcule a soma dos dois valores e retorne o resultado que é atribuído
	// à variável soma
	soma = adicao (n, m);
	// imprimindo o valor de "soma" na tela
	cout << soma;
	// retornando o processo anterior, no caso o sistema operacional
	return;
}
// Fim do programa
O próximo programa melhora a interface com o usuário solicitando os valores das variáveis n e m para que a função adicao calcule a soma dos dois valores:
// Terceiro programa C++
// Curso de Linguagem de Programação C++ PROG003.CPP - Silvio Sabino
#include<iostream.h> // incluindo iostream.h para utilizar as classes cout e cin
// função que retorna a soma de 2 números cujos valores
// são passados como parâmetros
int adicao (int a, int b){
	// declarando a variável que conterá o valor da soma
	// dos dois parâmetros "a" e "b"
	int resultado;
	// atribuindo o valor da adicao de "a" e "b" à variável resultado
	resultado = a + b;
	// retornando o valor contido na variável "resultado" para
	// o processo anterior, que nesse caso é a função main()
	return resultado;
}
// função principal do programa onde é iniciada a execução
void main(void){
	// declarando duas variáveis do tipo inteiro
	int n, m, soma;
	// pedindo para o usuário o valor de "n"
	cout << "\nDigite o 1o. no.: ";
	cin >> n;
	// pedindo para o usuário o valor de "m"
	cout << "Digite o 2o. no.: ";
	cin >> m;
	// passando "n" e "m" como parâmetros para que a função soma(int, int)
	// calcule a soma dos dois valores e retorne o resultado que é atribuído
	// à variável soma
	soma = adicao (n, m);
	// imprimindo o valor de "soma" na tela
	cout << "A soma é: " << soma;
	// retornando o processo anterior, no caso o sistema operacional
	return;
}
// Fim do programa
Nos programas acima, vimos como é a sintaxe de declaração de funções e variáveis, como passar parâmetros para uma função e como retornar valores para o processo anterior que chamou a função.
Depois disso, provavelmente será possível reconhecer um programa C++ se alguém nos apresentar um. Passaremos agora a detalhar os aspectos específicos da linguagem C++.
�
Dados padrões
Todo programa C++ deve ter pelo menos a função main( ), e podem também conter dados que podem ser variáveis ou constantes.
	
Todos os dados e funções C++ são referenciados por identificadores (nomes). Os identificadores não podem começar com dígitos numéricos porque assim o compilador não poderia separar tais identificadores de constantes.Eis a descrição suscinta dos tipos de dados padronizados C++:
char: utilizado para armazenar caractares alfanuméricos, o tipo char ocupa um byte na memória. Devido ao fato de C++ ser fracamente figurada, um dado char pode ser visto como número ou caractere, dependendo do desejo do programador na aplicação específica. Seu valor padrão pode variar de –128 a 127.
int: ocupa no modelo padrão uma palavra (nas máquinas da plataforma PC, isso corresponde a dois bytes) na memória e seu valor padrão pode variar entre –32768 a 32767. Pode armazenar números inteiros ou pode ser visto como caractere, dependendo da aplicação, mas o valor do segundo byte não é considerado nesse caso.
float: pode armazenar valores em ponto flutuante e correspondem aos números reais. Ocupam duas palavras na memória e seu valor padrão pode variar entre 3,4x10-38 até 3,4x10+38.
double: armazena valores em ponto flutuante de
precisão dupla. Ocupam quatro palavras na memória e seu valor padrão pode variar entre 1,7x10-308 e 1,7x+308.
enum: tipo de dado associado a um conjunto de constantes inteiras chamadas de conjunto de enumeração (enumeration set), que possuem valor presumido mas que podem ser especificados pelo programador. A sintaxe é:
enum semana {domingo, segunda, terça, quarta, quinta, sexta, sábado} dias;
A declaração acima cria o tipo enum semana e a variável dias, do tipo semana. A constante domingo tem valor 0 e as seguintes têm o valor da anterior mais um.
void: tipo vazio para retorno e argumentos de funções. Seu uso é importante para ponteiros, definindo ponteiros genéricos. Isso será visto quando tratarmos de dados dinâmicos.
Dados padrão podem ser iniciados com algum valor quando são declarados, como na declaração:
int inteiro = 7;
Se o programador esquecer de iniciar a variável na declaração ou fora dela, seu valor será desconhecido até que lhe seja atribuído algum valor.
Os dados variáveis, em suma, são os que podem estar no lado esquerdo de uma instrução de atribuição, ou em outros termos, são lvalues. Quaisquer outras expressões não são lvalues (localizador de objeto)
Pode-se conhecer o tamanho de qualquer tipo de dado C++ utilizando-se o operador sizeof que retorna o tamanho em bytes do operando. Por exemplo: sizeof(int) retorna 2, que é o tamanho em bytes do tipo int.�
Tipos definidos e estruturas de dados
typedef
Além dos dados padronizados, podem ser definidos outros tipos de dados com a palavra reservada typedef:
typedef int inteiro;
Com essa definição, poderemos declarar um dado inteiro a como int a ou inteiro. Já que inteiro foi definido como sendo equivalente ao tipo int. Na maioria dos casos, typedef é utilizado para conferir significado aos tipos criados pelo usuário e facilitar a sintaxe, nos poucos casos restantes é uma necessidade para que a linguagem suporte certas declarações ou passagem de argumentos para funções.
Estruturas de dados
Podem ser definidos tipos de dados heterogêneos, ou estruturas de dados, formados por combinações de tipos válidos, padrões ou não. Existem três tipos de estruturas de dados em C++:
struct: a estrutura segue o conceito de registro: dados relacionados logicamente referenciados por um único nome, e cada dado representa um campo. Considere um número complexo com a parte real e imaginária. As duas partes podem ser referenciadas por um só nome, desde que declarada uma estrutura, como por exemplo:
struct complexo {
	double real;
	double imag;
};
class: tipo de dado concebido para a criação de objetos e pode ser entendida com a uma evolução de struct. As funções de uma classe são conhecidas como métodos. A classe abaixo possui dados (campos ou instâncias) e métodos:
class exemplo{
	int n,u;
	float t;
	public:
	char letra;
};
int exemplo::metodo1(void){
	return(0);
}
As instâncias e métodos de uma classe somente podem ser acessadas pelo programa diretamente se especificadas com o modificador public. No exemplo, somente letra pode ser acessada fora da classe. Em C++, tipos de dados struct também podem ter métodos, e suas instâncias são sempre presumidas públicas. Para impedir o acesso de alguma instânca pelo programa, utilizamos o modificador private. A palavra reservada this representa um ponteiro que aponta para o objeto atual.
Quando criamos uma class, não criamos um objeto, mas apenas um tipo de dado. Quando em algum lugar do programa declaramos um dado do tipo de uma class definida, então criamos um objeto na memória.
Para que o objeto seja construído na memória, existe sempre uma função especial denominada construtor do objeto e para dealocar o espaço reservado, o programa chama uma outra função, chamada destrutor. O programador pode criar seus próprios construtores de destrutores, como veremos mais adiante.
union: um tipo interessante de estrutura de dados. Em uma union, todos os dados ocupam a mesma área de memória, sendo que a memória ocupada pela union é igual ao tamanho do maior tipo de dado. Consideremos a union abaixo:
union teste {
	char caractere;
int inteiro;
float flutuante
	double flutuante_duplo;
};
O maior tipo de dado é o campo flutuante_duplo, que ocupa 8 bytes. Na memória, esses campos estariam de forma parecida com o esquema abaixo:
		C45D:0780
		C45D:0781
		C45D:0782
		C45D:0783
		C45D:0784
		C45D:0785
		C45D:0786
		C45D:0787
Em uma união, os campos estão no mesmo endereço, portanto se um deles tiver seu valor alterado, todos podem sofrer a alteração.
Para acessar bits em um local de memória, C e C++ possuem uma forma de acessá-los com um tipo especial de estrutura denominada campo de bits:
struct campo{
	unsigned c1:1; // 1 bit
	unsigned c2:1; // 1 bit
	unsigned c3:4; // 4 bits 
	unsigned c4:2; // 2 bits
};
Os campos de bits em uma estrutura pode ocupar no máximo 16 bits. A configuração na memória seria algo parecido com o esquema abaixo:
		c4					c3				 c2		c1
		Bit 8
		Bit 7
		Bit 6
		Bit 5
		Bit 4
		Bit 3
		Bit 2
		Bit 1
Se o número total de bits ocupado pelos campos de bits da estrutura for diferente de um múltiplo de 8, os bits restantes até completar um múltiplo de 8 são “desperdiçados”, pois não será possível acessar os bits restantes porque o processador só poderá endereçar bytes e não bits.
�
Modificadores de dados
Os tipos padrões char e int podem ter seus intervalos de valores alterados pelos modificadores signed e unsigned. O modificador signed (sinalizado) é o estado padrão e não é necessário expressá-lo na declaração. Já unsigned (sem sinal) deve ser explicitado para que o compilador saiba que o dado será considerado sempre positivo. Nos dados signed o bit mais significativo representa o sinal, e quando declaramos um dado unsigned o compilador utiliza todos os bits disponíveis para guardar a informação. O efeito é a alteração dos intervalos de valores: unsigned int pode variar de 0 a 65535 e unsigned char de 0 a 255.
O modificador long dobra o tamanho em bytes ocupado pelos tipos int e double. E short pode modificar o tipo int, mas nenhum efeito ocorre na plataforma PC.
O resumo abaixo mostra o efeito nos intervalos e no tamanho em bytes dos modificadores de sinal e tamanho nos tipos padrões C++:
		Tipo
		Tamanho
		Intervalo
		
		unsigned char
		8 bits
		0 a
		 255
		Char
		8 bits
		-128 a
		 127
		Enum
		16 bits
		-32768 a
		 32767
		unsigned int
		16 bits
		0 a
		 65535
		short int
		16 bits
		-32768 a
		 32767
		Int
		16 bits
		-32768 a
		 32767
		unsigned long
		32 bits
		0 a
		 4294967295
		Long
		32 bits
		-2147483648 a
		 2147483647
		Float
		32 bits
		3,4x10-38 a
		 3,4x10+38
		Double
		64 bits
		1,7 x10-308 a
		 1,7 x10+308
		long double
		80 bits
		3,4 x104932 a
		 1,1 x104932
Os dados podem ter seus valores inalteráveis pelo programa se modificados pela palavra reservada const, e podem ter seu valor modificado por algum evento externo através do modificador volatile. Se um dado variável é declarado normalmente como:
int a=0;
O valor contido na variável pode ser alterado pelo programa em uma instrução de atribuição qualquer, mas se ele a variável for declarada com o modificador const:
const int a=0;
O programador não poderá alterar o valor dessa variável, entretanto um processo externo pode se ela for declarada como volatile, mesmo sendo especificado o modificador
const:
const volatile a=0;
Nesse caso, o compilador não presumirá qualquer valor para a constante, que pode estar sendo atualizada por algum processo externo.
�
Conversões de dados
Quando escrevemos instruções que envolvem mais de um tipo de dado, eles são convertidos automaticamente seguindo uma ordem hierárquica para que o compilador possa executar a instrução. Essas operações são chamadas de modo misto. Essa necessidade de conversão existe porque tipos de dados diferentes são armazenados de modos diferentes na memória. Os dados originais não são alterados, pois é somente durante o cálculo da instrução que os tipos são alterados influenciando no resultado. Consideremos a instrução abaixo:
float termo1=2.0, resultado;
int termo2=3;
resultado = termo1*termo2;
Para executar a instrução de atribuição, o valor de termo2 é temporariamente convertido para float e o valor de termo2 não é alterado. A hierarquia de conversão segue a sequência: double, float, long, int, short.
Se um float é convertido para int a parte fracionária é perdida sem arredondamento, vejamos o exemplo:
float termo1=2.9, termo2=7.8;
int resultado;
resultado = termo1*termo2;
Esse operação teria como resultado 22,62 se resultado fosse do tipo float ou double, mas como é uma variável do tipo int a parte fracionária é perdida e resultado receberá o valor 22 após a instrução.
Em algumas instruções o resultado normal é indesejável e nesse caso os dados devem ser convertidos com o operador cast, que modela o tipo de dado da melhor maneira para a aplicação:
float termo1=5.7, resultado;
int termo2=3, termo3=4;
resultado = termo1 + termo2/termo3;
Depois dessa instução, o valor de resultado é 5,7. Isso é estranho, já que os dados inteiros não exerceram nenhuma influência. Isso ocorreu porque após a divisão termo2/termo3 o resultado deveria ser 0,75 mas como os dois operandos são inteiros a parte fracionária é desprezada e o resultado da divisão é 0.
Para corrigir esse problema, C++ possui o operador de modelamento de dados (cast). Usando o operador cast em um dos operandos inteiros, o resultado seria 4,275:
resultado = termo1 + termo2/(float)termo3;
Quando o operador cast é aplicado em termo3, a divisão passa a considerar todos os dados como float, conforme a hierarquia de conversão, por isso não é necessário modelar os dois operandos da operação.�
Classes de armazenamento
Os dados em C++ podem ter seu armazenamento padrão modificado, e isso terá efeitos na visibilidade (escopo) da variável dentro do arquivo e dentro do programa (se o programa conter mais de um arquivo). Um dado declarado fora de qualquer função é um dado de escopo global, porém se ele for declarado dentro de um bloco de código ele terá escopo local. As declarações de dados pode ser de nível interno ou externo.
As classes possíveis em declarações de nível interno são auto (padrão) static e register. Um dado auto ou static existe enquanto o programa estiver dentro do bloco onde está declarado, mas se for static a cada chamada à função ele retém o último valor e deve ser iniciado com algum valor, ou o compilador presumirá o valor zero. Se um dado é declarado com classe register o compilador tentará armazenar esse dado em um registrador da CPU ou otimizá-lo. Devemos ter cuidado: register é uma solicitação e não uma ordem, pois nem sempre será possível armazenar dado em um registrador.
Em declarações de nível externo, as classes podem ser somente extern ou static: extern refere-se a um dado declarado em outro arquivo, e pode ser declarado apenas uma vez em um dos arquivos; dados static podem ser declarados em mais de um arquivo, já que static limita o escopo no arquivo onde está declarado. Uma função também pode ter classe de armazenamento modificada: funções static são visíveis apenas dentro do arquivo onde está declarada e funções extern são visíveis em todos os arquivos que formam o programa. Funções sem classe de armazenamento são extern por padrão Abaixo um exemplo de declaração de de um dado com declarações de nível externo (para rodar, abra o projeto proj01.prj no Turbo C++):
// Ilustrando o uso de classes de armazenamento static e extern
// Arquivo PROG004.CPP
// Curso de Linguagem de Programação C++ PROG004.CPP - Silvio Sabino
#include<iostream.h>
int a=0;
static int b;
extern void modifica(void); // declaração de função para acessá-la em outro arquivo
void main(void){
	cout << "\nO valor de a é: " << a;
	modifica();
	cout << "\n\nE o de B em PROG004.CPP é: " << b;
}
// Ilustrando o uso de classes de armazenamento static e extern
// Arquivo PROG005.CPP
// Curso de Linguagem de Programação C++ PROG005.CPP - Silvio Sabino
#include<iostream.h>
extern int a;
static int b=2;
void modifica(void){
	a=a+1;
	cout << "\n\nO valor de a mudou para: " << a;
	cout << "\nE o de B em PROG005.CPP é: " << b;
}
�
Matrizes
Qualquer tipo de dado em C e C++ pode ser organizados em arranjos (array) contíguos na memória RAM. Esses arranjos são chamados matrizes e têm grande importância na programação. As matrizes podem ter uma ou mais dimensôes, e quando possuem uma dimensão podem ser denominadas de vetores.
A declaração de uma matriz de 5 inteiros de nome matriz seria:
int matriz[5];
Para uma matriz bidimensional em que cada dimensão possui 5 elementos:
int matriz[5][5];
O nº de elementos de uma matriz pode ser omitido na declaração, mas se a matriz não for iniciada o seu tamanho será presumido como 0 pelo compilador. Para declarar uma matriz iniciando-a a sintaxe é:
int matriz[]={0,1,2,3,4,5,6};
No caso de matrizes de mais de uma dimensão, somente a dimensão mais à direita pode ficar sem o nº de itens:
int matriz[5][]={{0,1,2,3},{4,5,6,7},{8,9,10,11},{12,13,14,15},{16,17,18,19}};
No caso de matrizes de caracteres (em Pascal, o tipo string é padrão, o que não ocorre com C e C++),a inicialização pode ser feita como mostrada acima ou de forma mais direta:
char matriz[]= "essa é uma matriz de caracteres";
No caso de mais de uma dimensão:
char matriz[3][]={"primeiro item","segundo item","terceiro item";};
Nesse caso, o compilador criará todos os itens com o tamanho do maior item.
Poderemos usar as matrizes com todas as possibilidades que elas oferecem quando estudarmos os ponteiros, um assunto de extrema importância em C e C++ que é um dos motivos da escolha delas para implementar sistemas operacionais.
�
Operadores
C++ possui alguns operadores que não são encontrados em outras linguagens de programação, como operadores bit a bit, de atribuição composta, incremento e decremento e operador vírgula. Os tipos de operadores C++ são:
Operadores bit a bit
Tratam os dados como sequências de bit individuais. São & (AND), | (OR), ^ (XOR), ~ (complemento de um). O programa a seguir ilustra os efeitos dos operadores bit a bit:
// Ilustrando os efeitos dos operadores bit a bit
// Curso de Linguagem de Programação C++ PROG006.CPP - Silvio Sabino
#include<iostream.h>
unsigned int zeros=0;
unsigned int uns=255;
unsigned int medio=127;
void main(void){
	cout << "\n\n 0 em binário é 0000000000000000";
	cout << "\n127 em binário é 0000000001111111";
	cout << "\n255 em binário é 0000000011111111\n";
	cout << "\n0 & 255 = " << (zeros & uns) << " 0000000000000000";
	cout << "\n0 | 255 = " << (zeros | uns) << " 0000000011111111";
	cout << "\n0 ^ 255 = " << (zeros ^ uns) << " 0000000011111111";
	cout << "\n~0 = " << (~zeros) << " 1111111111111111";
	cout << "\n0 & 127 = "
<< (zeros & medio) << " 0000000000000000";
	cout << "\n0 | 127 = " << (zeros | medio) << " 0000000001111111";
	cout << "\n0 ^ 127 = " << (zeros ^ medio) << " 0000000001111111";
	cout << "\n~127 = " << (~medio) << " 1111111110000000";
	cout << "\n255 & 127 = " << (uns & medio) << " 0000000001111111";
	cout << "\n255 | 127 = " << (uns | medio) << " 0000000011111111";
	cout << "\n255 ^ 127 = " << (uns ^ medio) << " 0000000010000000";
	cout << "\n~255 = " << (~uns) << " 1111111100000000";
}
Deslocamento
Também conhecidos como rotação de bits. Esses operadores, bem como os operadores bit a bit, são bastante utilizados em programação de sistemas, por manipularem diretamente os bits dos dados. O operador deslocamento à esquerda << move todos os bits uma posição para a esquerda, e o deslocamento à direita >>, move todos os bits para a direita. Nos dois casos, os bits de um extremo é perdido e o do outro extremo torna-se zero. O programa a seguir mostra como funcionam os operadores de deslocamento de bits:
// Ilustrando os efeitos dos operadores bit a bit
// Curso de Linguagem de Programação C++ PROG007.CPP - Silvio Sabino
#include<iostream.h>
unsigned int valor1=7;
unsigned int valor2=64512;
void main (void){
	cout << "\n\n 7 em binário ‚ 0000000000000111";
	cout << "\n64512 em binário ‚ 1111110000000000\n";
	cout << "\n 7<<1 = " << (valor1<<1) << " 0000000000001110";
	cout << "\n 7<<2 = " << (valor1<<2) << " 0000000000011100";
	cout << "\n64512>>1 = " << (valor2>>1) << " 0111111000000000";
	cout << "\n64512>>2 = " << (valor2>>2) << " 0011111100000000";
}
Incremento e decremento
Somar ou subtrair 1 de um número é tão comum em programação que C++ possui operadores especiais para essas ações: ++ (incremento) e – (decremento). Eles só podem ser utilizados por dados variáveis e a sua sintaxe pode ser observada no programa abaixo:
// Ilustrando os efeitos dos operadores bit a bit
// Curso de Linguagem de Programação C++ PROG008.CPP - Silvio Sabino
#include<iostream.h>
#include<conio.h>
int numero=10;
void main(void){
	clrscr();
	cout << "\nnumero incrementado: " << ++numero;
	cout << "\nnumero novamente incrementado: " << numero++;
	cout << "\nnumero decrementado: " << --numero;
	cout << "\nnumero novamente decrementado: " << numero--;
}
Já que numero foi iniciado com valor 10 e foi incrementado 2 vezes e depois decrementado 2 vezes, então a princípio a saída deve ser:
numero incrementado:			11
numero novamente incrementado:	12
numero decrementado:			11
numero novamente decrementado:	10
Mas a saída que ele apresenta é outra. Execute o programa para verificar e veja que o resultado é diferente. Isso acontece porque a posição dos operadores ++ e – influi no resultado, pois altera a ordem de execução da instrução. Quando escrevemos:
cout << "\nnumero incrementado: " << ++numero;
A ordem de execução é: primeiro a variável numero é incrementada e depois a sentença é impressa por cout.
Enquanto que na linha seguinte:
cout << "\nnumero novamente incrementado: " << numero++;
A ordem é: primeiro a sentença é impressa por cout e depois a variável numero é incrementada
O mesmo ocorre com decremento.
Aritméticos
Os operadores para operações aritméticas em C++ são: + (adição), - (subtração), * (multiplicação), / (divisão) e % (módulo). O operador módulo retorna o resto de uma divisão entre dois inteiros.
Atribuição simples e compostos
Diferente de outras linguagens, C++ possui um operador de atribuição ao invés de uma instrução de atribuição. Isso torna-se claro na instrução abaixo, que não seria possível em outras linguagens:
valor1 = valor2 = valor3 = 2;
Ou seja: valor3 recebe o valor 2 e a operação retorna o valor contido em valor3, que é atribuído à variável valor2, e a peração retorna o valor contido em valor2 e finalmente valor1 recebe 2.
C++ possui ainda um conjunto de operadores de atribuição compostos que permitem que o código seja escrito de forma mais concisa sem perder a clareza. As instruções abaixo são equivalentes:
valor = valor + 5;
valor + = 5;
Outras operações que podem utilizar esses operadores são as demais perações aritméticas, deslocamento de bits e bit a bit, gerando os seguintes operadores: +=, -=, *=, /=, %=, <<=, >>=, &=, ^=, |=.
Relacionais e lógicos
Os operadores relacionais C++ sempre estabelecem uma relação entre os valores dos operandos. Eles retornam 0 se o teste for falso e 1 se for verdadeiro. Os operadores relacionais C e C++ são: == (igual, note que ele é diferente do operador = de atribuição), != (diferente), > (maior), < (menor), >= (maior ou igual), <= (menor ou igual).
Os operadores lógicos C e C++ retornam resultados de acordo com a relação lógica de seus argumentos: && (AND), || (OR), ! (NOT). O operador && retornará 1 quando os dois argumentos forem verdadeiros, || retornará 1 quando pelo menos 1 argumento for verdadeiro e ! inverte o valor que seria retornado. O programa a seguir mostra os resultados de teste relacionais e lógicos de acordo com a entrada do usuário:
// Ilustrando os resultados dos operadores relacionais e lógicos
// Curso de Linguagem de Programação C++ PROG009.CPP - Silvio Sabino
#include<iostream.h>
void main(void){
	float num1, num2;
	cout << "\nInforme o primeiro valor real: ";
	cin >> num1;
	cout << "\nInforme o segundo valor real: ";
	cin >> num2;
	cout << "\n\nResultado de "<<num1<<" == "<<num2<<" -> " <<(num1==num2);
	cout << "\nResultado de "<<num1<<" != "<<num2<<" -> " <<(num1!=num2);
	cout << "\nResultado de "<<num1<<" > "<<num2<<" -> " <<(num1>num2);
	cout << "\nResultado de "<<num1<<" < "<<num2<<" -> " <<(num1<num2);
	cout << "\nResultado de "<<num1<<" >= "<<num2<<" -> " <<(num1>=num2);
	cout << "\nResultado de "<<num1<<" <= "<<num2<<" -> " <<(num1<=num2);
	cout << "\nResultado de "<<num1<<" && "<<num2<<" -> " <<(num1&&num2);
	cout << "\nResultado de "<<num1<<" || "<<num2<<" -> " <<(num1||num2);
}
Operador condicional ternário
Esse operador torna o código compacto por envolver um decisão com pouco código. Sua sintaxe é:
condição ? expressão_verdadeira : expressão_falsa ;
A condição genérica na instrução acima é um teste, que pode envolver operadores condicionais e lógicos:
// Ilustrando os resultados dos operadores relacionais e lógicos
// Curso de Linguagem de Programação C++ PROG010.CPP - Silvio Sabino
#include<iostream.h>
int a, b, c;
void main(void){
cout << "\n\nInforme o primeiro valor: ";
cin >>a;
cout << "Informe o segundo valor: ";
cin >>b;
cout << "Informe o terceiro valor: ";
cin >>c;
cout << "o "<<((a>=b && a>=c)?"1o.":(b>=c)?"2o.":"3o.")<<"no. ‚ maior";
}
Operador vírgula
O operador vírgula permite que duas expressões coexistam na mesma linha onde normalmente somente uma seria premitida. Seu uso será evidenciado quando tratarmos de estruturas de controle de fluxo.
Resolução de escopo
C++ permite que uma variável local possua o mesmo nome de uma global, bastando que seja utilizado o operador resolução de escopo ::. No trecho abaixo as há duas variáveis teste:
int teste;
...
void funcao(int teste){
	::teste=teste;
}
Dentro da função funcao, a variável global recebeu o valor da variável local por meio do operador ::.
Assim como nas outras linguagens, os operadores C++ obedecem a níveis de precedência que determinam
a ordem que o compilador avaliará os operadores. Efeitos colaterais pode surgir quando os operadores são colocados de forma confusa. As instruções abaixo podem causar efeitos colaterais:
valor = 2; resultado = (valor = 4) + valor;
Existem duas formas de avaliar a expressão: valor recebe 4 e em seguida resultado recebe 8 (4+4); ou valor é usado como 2 e logo depois recebe 4, e resultado recebe 6.
A tabela abaixo relaciona os operadores C++ por ordem de precedência, sendo que alguns ainda não foram descritos. Operadores da mesma categoria tem a mesma precedência:
		Categoria
		Descrição
		Operador
		Precedência mais alta
		Chamada de função
		()
		
		Índice de matriz
		[]
		
		Referência indireta de estruturas
		->
		
		Resolução de escopo
		::
		
		Referência direta de estrutura
		.
		Unários
		NOT
		!
		
		Complemento de 1
		~
		
		Sinal positivo
		+
		
		Sinal Negativo
		-
		
		Incremento
		++
		
		Decremento
		--
		
		Endereço
		&
		
		Referência indireta
		*
		
		Modelamento (cast)
		(tipo)
		
		Tamanho do operando
		sizeof
		
		Alocação dinâmica
		new
		
		Dealocação dinâmica
		delete
		Multiplicativos
		Multiplicação
		*
		
		Divisão
		/
		
		Módulo
		%
		Acesso a membros
		Referência indireta membro de estrutura
		.*
		
		Referência indireta membro de estrutura
		->*
		Aditivos
		Adição
		+
		
		Subtração
		-
		Deslocamento
		Deslocamento à esquerda
		<<
		
		Menor que
		<<
		Relacionais
		Menor ou igual a
		<=
		
		Maior que
		>
		
		Menor ou igual a
		>=
		Igualdade
		Igual
		==
		
		Diferente (não igual)
		!=
		
		AND bit a bit
		&
		
		XOR bit a bit
		^
		
		OR bit a bit
		|
		
		AND lógico
		&&
		
		OR lógico
		||
		
		Condicional ternário
		?:
		Atribuição
		Atribuição
		=
		
		Atribuições compostas
		*=, /=, %=, +=, -=, &=, ^=, |=, <<=, >>=
		
		Vírgula
		,
�
Controle de fluxo
Para que possamos escrever programas C++ mais elaborados, é necessário dominar as estruturas de controle de execução de instruções, que são, basicamente, as instruções condicionais e laços.
Quase todos os programas que escrevemos até o momento seguiram sempre uma sequência definida e o programador não interferiu em nenhum momento para que o programa tomasse decisões. A exceção foi o uso do operador condicional ternário.
Quando é feito o controle de fluxo em um programa, algumas instruções podem não ser executadas em nenhum momento dependendo dos critérios adotados para a decisão.
if
Esse instrução executa condicionalmente um bloco de código. Um bloco de código com apenas uma instrução não precisa ser delimitado com chaves { }, mas deve ser delimitado se houver mais de uma. A sintaxe genérica da instrução if é:
if(expressão de teste)
	ação;
Caso exista mais de uma instrução devem ser usadas as chaves:
if(expressão de teste){
	instrução1;
	instrução2;
	...
}
O programa abaixo exemplifica o uso da instrução if:
//Ilustrando o uso da instrução if
// Curso de Linguagem de Programação C++ PROG011.CPP - Silvio Sabino
#include<iostream.h>
void main(void){
	int valor_teste;
	cout << "\nDigite um valor inteiro: ";
	cin >> valor_teste;
	if(valor_teste==2){
		cout << "\nFoi digitado o valor 2.";
		return;
	}
	cout << "\nFoi digitado um valor diferente de 2.";
}
Nesse exemplo, se o usuário digitar o valor 2, o teste valor_teste==2 retorna 1 e a instrução if direciona o fluxo para dentro do bloco, aparecendo a mensagem “Foi digitado o valor 2.” e o programa retorna para o processo anterior com a instrução return. Caso contrário o programa segue com a instrução após o bloco.
if-else
Com essa instrução o programa pode tomar duas direções baseado em um teste. A sintaxe geral seria:
if(expressão de teste){
	instrução1;
	instrução2;
	...
}
else{
	instrução1;
	instrução2;
	...
}
As instruções dentro do bloco else somente serão executadas quando o teste for falso (retornar 0).
switch
Quando é desejável testar uma variável em relação a vários valores, é improdutivo montarmos sequências de instruções if. Nesses casos é aconselhável utilizar a instrução switch. A sintaxe geral é:
switch (expressão){
	case constante_1:
		instruções;
		break;
	case constante_2:
		instruções;
		break;
	...
	case constante_n:
		instruções;
		break;
	default: instruções;
}
Devemos observar as peculiaridades da instrução switch. Quando o programa encontra a constante que corresponde ao valor da expressão, ele executa as instruções abaixo do case até que seja encontrada uma instrução break ou outra instrução de controle que provoque um devio na odem normal do programa.
for
É uma das estruturas de laço mais potentes em muitas linguagens de programação, mas em C e C++ o laço for ultrapassa os limites normais de flexibilidade. Sua sintaxe geral é:
for(inicialização;expressão de teste;incremento){
	instrução1;
	instrução2;
	...
}
O laço for deve ser usado preferencialmente quando o número de iterações é conhecido. O exemplo abaixo mostra o uso do laço for e da instrução switch:
//Ilustrando o uso do laço for e da instrução switch
// Curso de Linguagem de Programação C++ PROG012.CPP - Silvio Sabino
#include<iostream.h>
void main(void){
	// corpo do laço for, atenção às declarações
	// de variáveis dentro da inicialização.
	// O programa executará 5 vezes as instruções dentro do bloco
	for(register int i = 0; i < 5;i ++){
		int valor;
		cout << "\nDigite um valor inteiro: ";
		cin >> valor;
		// a instrução switch testará o valor de "valor" e
		// direcionará o programa para o case certo
		switch(valor){
			case 1: cout << "\n\nVocê digitou o valor 1";
							break;
			case 2: cout << "\n\nVocê digitou o valor 2";
							break;
			case 3: cout << "\n\nVocê digitou o valor 3";
							break;
			default: cout << "\n\nVocê digitou um valor diferente de 1,2 ou 3";
		}
	}
}
while
Quando não podemos prever o número de iterações necessárias é recomendado o uso do laço while:
while(expressão de teste){
	instrução1;
	instrução2;
	...
}
Vamos reescrever o exemplo anterior utilizando o laço while:
// Ilustrando o uso do laço while e da instrução switch
// Curso de Linguagem de Programação C++ PROG013.CPP - Silvio Sabino
#include<iostream.h>
void main(void){
	// iniciando a variável com um valor diferente de 0 para
	// evitar efeito colateral no laço while
	int valor=1;
	// se o valor de "valor" for 0, o teste retorna 0 e o laço termina
	while(valor){
		cout << "\nDigite um valor inteiro (0 para sair): ";
		cin >> valor;
		switch(valor){
			case 1: cout << "\nVocê digitou o valor 1";
							break;
			case 2: cout << "\nVocê digitou o valor 2";
							break;
			case 3: cout << "\nVocê digitou o valor 3";
							break;
			default: cout << "\nVocê digitou um valor diferente de 1,2 ou 3";
		}
	}
}
do-while
A principal direfença entre
esse instruçõ e while é que as ações dentro do bloco sempre serão executadas pelo menos uma vez:
do{
	instrução1;
	instrução2;
	...
}while(expressão de teste);
break e continue
Dentro de laços, a instrução break provoca a saída imediata do laço, e a instrução continue faz o programa saltar imediatamente para a avaliação da expressão de teste. O uso comum de break é na instrução switch, e continue é raramente usado.
return
Provoca a saída imediata de uma função para o processo anterior. Se a mesma for de tipo diferente de void essa instrução deve vir acompanhada de um valor de retorno, caso contrário o compilador emitirá um aviso que não impede a execução do programa. Se a função for main() o programa terminará.
exit( ) e atexit( )
A função exit( ) provoca a saída imediata do programa e pede um argumento inteiro que será o código de erro para o sistema operacional, e atexit( ) faz com que uma função seja chamada imediatamente antes de terminar o programa. Essa função pede um ponteiro de função com argumento.
goto
É uma instrução que desvia incondicionalmente o programa para um rótulo. Sua sintaxe geral é:
goto rotulo;
...
rotulo:
instrução;
Seu uso é condenável por estar fora da filosofia da programação estruturada, mas foi mantido na transição de C para C++ porque em algumas situações seu uso é vantajoso. Exemplo genérico:
...
for(...){
	for(...){
		for(...){
			for(...){
				...
				if(...)goto sair;
			}
		}
	}
}
sair:
...
Nesse esquema de laços profundamente aninhados, não importam os testes dos laços externos ao for mais interno, porque goto desvia incondicionalmente o fluxo para o rótulo especificado. A única restrição é que o rótulo deve estar dentro da mesma função da instrução goto.
Laços infinitos
Se a expressão de teste de um laço for vazia ou se as variáveis envolvidas não sofrerem modificação dentro do laço, deve existir alguma instrução para que o programa saia do laço por meio de break, return, goto ou pelas função exit( ), caso contrário o laço nunca terminará.
Os laços infinitos podem ser usados quando o programa ou o laço termina mediante um evento produzido pelo usuário ou alguma entrada de valor específica. O exemplo anterior pode ser reescrito novamente utilizando-se um laço for(poderia ser while ou do-while, mas a expressão de teste não seria vazia) infinito:
// Ilustrando o uso do laço infinito
// Curso de Linguagem de Programação C++ PROG014.CPP - Silvio Sabino
#include<iostream.h>
void main(void){
	// utlizando um laço for infinito
	// nota-se que os sinais de ponto-e-vírgula são mantidos
	for(;;){
		int valor;
		cout << "\nDigite um valor inteiro (0 para sair): ";
		cin >> valor;
		switch(valor){
			case 0: return;
			case 1: cout << "\nVocê digitou o valor 1";
							break;
			case 2: cout << "\nVocê digitou o valor 2";
							break;
			case 3: cout << "\nVocê digitou o valor 3";
							break;
			default: cout << "\nVocê digitou um valor diferente de 1,2 ou 3";
		}
	}
}�
Ponteiros
Ponteiros são variáveis dinâmicas que guardam endereços de outra variáveis. A declaração de ponteiros é feita com o operador de referência indireta *:
tipo *identificador;
Onde tipo é o tipo apontado pelo ponteiro. Para atribuição, podemos utilizar o operador endereço &:
tipo nome;
tipo *apontador = &nome;
O ponteiro apontador armazenará o endereço da variável nome, ou em outras palavras, apontará para ela.
Ponteiros podem apontar para ponteiros, aumentando o nível de referência indireta, que é limitado apenas pela necessidade. Os ponteiros podem ser constantes ou variáveis. Ponteiros constantes são as matrizes ou ponteiros que tenham classe de armazenamento const. O nome da matriz representa o endereço do 1º item, ou seja, se array[50] é uma matriz, as expressões &array[0] ou array são equivalentes. Para declarar um ponteiro de nível(ordem) maior, basta aumentarmos o nº de operadores de referência indireta:
int **p, *****p1; //p é de segunda ordem e p1 é de quinta ordem
Se o operador referência indireta for utilizado em instruções durante o programa, ele permitirá o acesso à variável apontada pelo ponteiro. O programa a seguir mostra como isso ocorre:
// Funcionamento de ponteiros
// Curso de Linguagem de Programação C++ PROG015.CPP - Silvio Sabino
#include<iostream.h>
void main(void){
	int valor, *ponteiro = &valor;
	cout << "\nDigite um valor inteiro: ";
	cin >> valor;
	cout << "\nO valor digitado foi: "<< *ponteiro;
	*ponteiro=10;
	cout << "\nO valor foi modificado para: " << valor;
}
Aritmética
Ponteiros podem ser incrementados, decrementados, adicionados ou subtraídos de constantes, e a unidade válida é sempre o tamanho do tipo de dado apontado: depois e incrementar um ponteiro de nome pointer que aponta para o tipo float com a instrução pointer++, o seu valor será o endereço sizeof(float) acima do anterior. E depois de pointer = pointer+3, o novo valor será 3*sizeof(float) acima do anterior.
Para obter o endereço do elemento n de um ponteiro de nome array, que aponta para uma matriz, podemos utilizar notação de matriz ou de ponteiro se o ponteiro for variável: &array[n] ou array+n. E para acessar o valor desse elemento podemos escrever: array[n] ou *(array+n). Em qualquer caso, a notação de ponteiro executa mais rapidamente do que a de matriz.
Modificadores de ponteiros
A memória do processador 8088 é segmentada, e cada segmento tem 64 kbytes (65535 bytes). Todo endereçamento é feito com dois números denominados segmento e deslocamento (offset). Existem 4 segmentos em um programa “.EXE”: código, dados, pilha e extra. Se nada for informado ao compilador, ele tentará sempre alocar espaço dentro do segmento de dados, mas podemos modificar ponteiros para que sejam armazenados em outros locais com o uso de modificadores:
near: força o ponteiro a apontar somente para o deslocamento. Ocupam 2 bytes na memória;
far: força o ponteiro a contar sempre o valor do segmento e do deslocamento. Além e tornar o acesso mais lento, ponteiros far ocupam 4 bytes;
huge: semelhante ao ponteiro far, mas quando é incrementado, o segmento pode ser alterado. Isso nunca ocorre com um ponteiro far.
Para apontar para qualquer tipo de dado, um ponteiro pode ser declarado como void * e ser moldado para qualquer tipo de acordo com a necessidade. Um ponteiro void simplesmente aponta para uma endereço de memória sem estar associado a qualquer tipo de dado. Abaixo um programa para exemplificar:
// Funcionamento de ponteiros void
// Curso de Linguagem de Programação C++ PROG016.CPP - Silvio Sabino
#include<iostream.h>
int inteiro;
float flutuante;
void *pointer=&inteiro;
void main(void){
	*(int *)pointer = 2;
	pointer = &flutuante;
	*(float *)pointer = 3.0;
	cout << "\nValor int: " << inteiro << "\nValor float: " << flutuante;
}
Strings
C++ não possui cadeias de caracteres como tipo de dado padrão. Todas as cadeias de caracteres são tratadas como ponteiros para o tipo char. O programador deve ter muito cuidado com strings, porque um acesso fora da área reservada ou alocada não será avisado pelo compilador e pode levar à catástrofe: a área invadida pode pertencer a outros dados, ao programa ou ao sistema operacional, no pior caso.
Strings em C++ são sempre terminadas com o caractere nulo (NULL), portanto sempre devemos alocar espaço para um elemento além do tamanho da string.
Alocação dinâmica de memória
Quando os programas
tornam-se mais complexos, é comum que o programador não possa prever quanta memória será necessária para o programa, devendo alocar memória dinamicamente. Os operadores new e delete alocam e liberam memória, respectivamente. A sintaxe geral desses operadores é:
tipo *ponteiro = new tipo[num_itens];
delete(ponteiro);
Quando o operador new é invocado pelo programa, este solicita ao sistema operacional um bloco de tamanho igual a núm_itens*sizeof(tipo). Se não houver memória disponível o ponteiro recebe o valor 0(NULL). Devemos testar se a alocação foi feita com sucesso, porque se tentarmos usar um ponteiro que aponta para NULL ou com valor desconhecido podemos causar uma catástrofe: os outros dados, o código do programa ou de outros programas pode ser corrompido e o sistema pode cair, travando a máquina. O programa a seguir mostra o uso dos operadores new e delete:
// Operadores new e delete
// Curso de Linguagem de Programação C++ PROG017.CPP - Silvio Sabino
#include<iostream.h>
void main(void){
	int *valor, itens;
	cout << "\nDigite o n£mero de itens: ";
	cin >>itens;
	if(!(valor=new int[itens]))
		cout << "\nMemória insuficiente!";
	else{
		cout << "\nAlocação dinâmica efetuda com suceso!";
		delete(valor);
	}
}
Referência
É possível simplificar a notacão de ponteiros usando o tipo referência. Assim, nas chamadas de funções podemos utilizar os nomes das variáveis e passar o endereço para a função. O cabeçalho abaixo possui um argumento que é passado por referência:
int funcao(char *a, int &ref){...
Quando o programa chamar essa função, a variável referência ref equivalerá ao argumento passado para a função, porque terão o mesmo endereço. O uso do tipo referência C++ é indispensável quando não podem ser utilizados ponteiros e tampouco é possível o uso de variáveis comuns. Em C, a única forma de alterar o valor do parâmetro original era por meio de ponteiros.
Membros de ponteiros de estruturas
Para referenciarmos membros de ponteiros que apontam para estruturas de dados, a referência indireta é realizada com os operadores -> e ->*. Por exemplo: seja *pont um ponteiro para uma struct casa, que possui uma instância denominada sala que e um ponteiro do tipo comodo.
struct casa *pont = new casa;
pont->casa = new comodo;
pont->*casa = 20;
A instância casa é referenciada pelo operador-> porque a estrutura externa (pont) é um ponteiro, e o conteúdo apontado por casa é acessado com o operador ->*.
�
Funções
Conforme o conceitos da programação estruturada, todas as ações que são usadas rotineiramente devem ser modularizadas para economizar tempo e facilitar o entendimento. Cada módulo ou sub-rotina em C++ é um função, como também foi explicado no início. A sintaxe geral de uma função C++ é:
tipo_de_retorno identificador(tipo_1 argum_1, tipo_2 argum_2, ..., tipo_n argum_n){
	instrução1;
	instrução2;
	...
}
O tipo de retorno é o tipo da função, ou seja, se ela retorna um tipo int dizemos que ela é do tipo int. Para retornar um valor, basta que uma expressão constante ou variável seja argumento de return.
Argumentos
Uma função pode ter um n° de argumentos limitado apenas pela necessidade e capacidade da máquina. Quando um argumento é passado para uma função, ele pode ser passado de duas formas:
Passagem por valor: quando passamos o valor dos dados. Os valores das variáveis originais da função chamadora não são alterados porque apenas uma cópia de seus valores é armazenada na pilha para serem utilizadas na função chamada. Funções chamadas por valor só podem retornar um valor;
Passagem por referência: nesse caso, são utilizados tipos referência e os dados originais podem ser alterados pela função. Por isso podemos dizer que funções chamadas por referência podem retornar mais de um valor (o normal com return e os outros que foram modificados). Em qualquer caso, a chamada por referência é mais rápida, consumindo menos espaço na pilha e menos instruções.
Em C++ os argumentos podem possuir um valor padrão, definido no cabeçalho da função:
int minha_funcao(int a, char n, double d=0.0, int c=0){
	instrução1;
	instrução2;
	...
}
Argumentos com valores padrões só podem ser os últimos da função. Portanto o cabeçalho:
int minha_funcao(int a, char n, double d=0.0, int c...
É inválido porque após um argumento iniciado com valor padrão segiu-se um argumento normal.
A função main() pode aceitar dois argumentos:
void main(int argc, char argv[]){...}
O argumento argc é o n° de argumentos na linha de comando e argv[] é uma matriz de ponteiros para char contendo os argumentos da linha de comando (o primeiro é o nome completo do programa).
Podem existir funções com nº variável de argumentos utilizando as elipses (...):
void funcao(int arg1, int arg2, ...){...}
Ponteiros de função
Em alguns casos, para que o código torne-se funcional, é aconselhável referenciar uma função indiretamente por um ponteiro. Apontar para uma função é conter o endereço do início do seu código, representado pelo nome da função. O programa abaixo mostra como funciona a sintaxe de um ponteiro de função:
// Ponteiros de função
// Curso de Linguagem de Programação C++ PROG018.CPP - Silvio Sabino
#include<iostream.h>
// declarando um ponteiro que aponta para uma função do tipo void
// sem nenhum argumento
void (*ponteiro)(void);
void funcao_1(void){
	cout << "\nExecutando a função 1!";
	return;
}
void funcao_2(void){
	cout << "\nExecutando a função 2!";
	return;
}
void main(void){
	int resposta;
	do{
		cout << "\nVocê deseja executar qual função (1 ou 2)?";
		cin >>resposta;
	}while(resposta!=1&&resposta!=2);
	ponteiro = resposta==1?funcao_1:funcao_2;
	ponteiro();
	return;
}
O uso de ponteiros de função é uma das portas para a programação avançada orientada por eventos, onde estruturas de dados genéricas são criadas e os objetos são diferenciados pelas funções apontadas.
Modificadores de acesso
C++ pode interagir com as linguagens Pascal e Assembly. Para que uma função possa ser utilizada por um programa escrito em Pascal, ela deve ser modificada com a palavra reservada pascal. Assim a ordem de empilhamento dos argumentos seguirá o padrão da linguagem Pascal: do primeiro para o último (em C++ é o inverso). Diversamente, para garantir que a ordem de empilhamento dos argumento siga o padrão C++ deve-se utilizar cdecl.
Assim como os dados referenciados por ponteiros, as funções também podem estar localizadas em segmentos de código diferentes. Com o uso dos modificadores near e far o compilador pode forçar uma chamada somente utilizando deslocamento (near) ou segmento e deslocamento (far). Chamadas distantes (far) tornam todo o processo mais lento.
inline
Algumas vezes é vantajogo expandir em linha uma função pequena. Isso acontece porque existe um código mínimo para chamar a função envolvendo pilha, argumentos e endereçamento que pode ser de tamanho ou tempo de execução maior do que a colocação do código da função diretamente no local. Para que o programador possa sugerir a expansão em linha, usamos a palavra reservada inline. A limitação é que não podem haver laços na função “candidata” para a expansão.
Recursividade
Muitos problemas possuem solução recursiva ou recorrente, ou seja, a solução chama a si própria até que uma condição básica seja satisfeita e ela começa a retornar. O fatorial de um número é um exemplo clássico de aplicação de recursividade. Observe a função fatorial recursiva:
long fatorial(int n){
	return(n<2?1:n*fatorial(n-1));

Teste o Premium para desbloquear

Aproveite todos os benefícios por 3 dias sem pagar! 😉
Já tem cadastro?

Outros materiais