Docsity
Docsity

Prepare-se para as provas
Prepare-se para as provas

Estude fácil! Tem muito documento disponível na Docsity


Ganhe pontos para baixar
Ganhe pontos para baixar

Ganhe pontos ajudando outros esrudantes ou compre um plano Premium


Guias e Dicas
Guias e Dicas

C / C++ e Orientação a Objetos em Ambiente , Notas de estudo de Engenharia Informática

Tutorial C/C++ e orientação a objetos (Multiplataforma)

Tipologia: Notas de estudo

Antes de 2010
Em oferta
30 Pontos
Discount

Oferta por tempo limitado


Compartilhado em 02/08/2006

hugo-makoto-6
hugo-makoto-6 🇧🇷

4.7

(78)

242 documentos

1 / 210

Documentos relacionados


Pré-visualização parcial do texto

Baixe C / C++ e Orientação a Objetos em Ambiente e outras Notas de estudo em PDF para Engenharia Informática, somente na Docsity! C / C++ e Orientação a Objetos em Ambiente Multiplataforma Por: Sergio Barbosa Villas-Boas, Ph.D. Professor Adjunto do DEL - Departamento de Eletrônica e Computação da UFRJ. (www.del.ufrj.br) Resumo do Currículo: www.crie.coppe.ufrj.br/mbkm/2000MBA em Inteligência Empresarial e Gestão do Conhecimento (MBKM) www.chiba-u.ac.jp1998Ph.D. em Engenharia de Controle por Chiba University - Japão www.coep.ufrj.br1991M.Sc. em Engenharia Elétrica pela COPPE - PEE - Controle www.del.ufrj.br1987Engenheiro Eletrônico pelo DEL, UFRJ www.cefet-rj.br1981Técnico Eletrônico pelo CEFET-RJ Email do Autor: villas@kmail.com.br URL do Autor: www.del.ufrj.br/~villas URL do Livro: www.del.ufrj.br/~villas/livro_c++.html Versão do Livro: 5.1, de 17 de Agosto de 2001 “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 2 Índice Índice ........................................................................................................................................................2 Capítulo 1) Introdução............................................................................................................................17 1.1 Prefácio...................................................................................................................................17 1.2 Histórico do livro....................................................................................................................19 1.3 Escolha de uma tecnologia: uma decisão estratégica .............................................................20 1.3.1 Características do produto “software” 21 1.3.2 Incorporação de novidades 22 1.4 Mercadoria e produto diferenciado ........................................................................................24 1.4.1 Mercadoria escassa 24 1.5 Sociedade do conhecimento ...................................................................................................25 1.5.1 Mudança do paradigma de negócios 26 1.5.2 “Mercadorização” 26 1.5.3 Remuneração × agregação de valor na cadeia produtiva 27 1.6 Porque C/C++ ? ......................................................................................................................27 1.6.1 “Tribos” de tecnologia 27 1.6.2 A escolha tecnológica é uma escolha estratégica 28 1.7 Breve história do C/C++.........................................................................................................30 1.8 Qualidades da Linguagem C/C++ ..........................................................................................31 1.9 Classificação de interfaces de programas...............................................................................32 1.10 Programando para console .....................................................................................................32 1.11 Linguagens de programação de computador..........................................................................33 1.11.1 Alto nível × baixo nível 33 Capítulo 2) Conheça o Seu Compilador.................................................................................................35 2.1 Visual C++ 6.0 .......................................................................................................................35 2.1.1 Reconhecendo o Compilador 35 2.1.2 “Hello world” para DOS 41 2.1.2.1 Adicionando argumentos para a linha de comando....................................................44 2.1.3 Usando o Help 45 2.1.4 Projetos (programas com múltiplos fontes) 46 2.1.5 Bibliotecas 46 “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 5 2.4.8.3 Construindo um rpm...................................................................................................67 2.4.8.3.1 Introdução.............................................................................................................67 2.4.8.3.2 O header ...............................................................................................................68 2.4.8.3.3 Preparação (prep)..................................................................................................69 Capítulo 3) Princípios de C/C++............................................................................................................70 3.1 O primeiro programa ..............................................................................................................70 3.2 Formato livre ..........................................................................................................................70 3.3 Chamada de função ................................................................................................................70 3.4 Declaração e definição de funções .........................................................................................71 3.5 Comentários............................................................................................................................71 3.6 Identificador ...........................................................................................................................72 3.7 Constantes literais...................................................................................................................72 3.8 Escopo ....................................................................................................................................72 3.9 Tipos de dados padrão (Standard Data Types) ......................................................................73 3.10 Palavras reservadas do C++ (keywords) ................................................................................74 3.11 Letras usadas em pontuação ...................................................................................................74 3.12 Letras usadas em operadores ..................................................................................................74 Surgiram oportunidades profissionais ? lembre-se do autor ! http://www.del.ufrj.br/~villas O primeiro patrocinador é o autor, cujos dados de contato estão divulgados no texto. Espero ser lembrado pelos leitores em consultorias, projetos, cursos ou empreendimentos que surjam, no ambiente profissional sempre em grande mutação. Como membro da comunidade acadêmica, sou entusiasta defensor de uma parceria tipo “ganha-ganha” entre universidade e empresas privadas ou públicas. Acredito que implantar com sucesso esse tipo de parceria é fator essencial de desenvolvimento econômico e social. Qualquer país precisa muito disso. No caso do Brasil, a necessidade de que a inteligência das universidades seja traduzida em desenvolvimento econômico e bem estar social é evidente e urgente. Veja slides desse livro na web em http://del.ufrj.br/~villas/slides.html “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 6 Capítulo 4) Estrutura do Compilador .....................................................................................................75 4.1 Entendendo o Compilador......................................................................................................75 4.2 Protótipos (prototypes) ...........................................................................................................76 4.3 Projetos em C/C++ .................................................................................................................77 4.4 Header Files (*.h)...................................................................................................................79 4.5 Biblioteca (library).................................................................................................................79 4.5.1 Utilizando Bibliotecas prontas 80 4.5.2 Fazendo bibliotecas 80 4.6 Regras do compilador.............................................................................................................82 Capítulo 5) Fundamentos de C /C++......................................................................................................84 5.1 Chamada de função por referência e por valor.......................................................................84 5.2 Tipos de dados definidos pelo programador ..........................................................................85 5.3 Maquiagem de tipos (type casting) ........................................................................................85 5.4 Operações matemáticas ..........................................................................................................86 5.5 Controle de fluxo do programa ..............................................................................................86 5.6 Execução condicional.............................................................................................................87 5.7 Laços (loop) de programação .................................................................................................87 Balico – o mercado de trabalho na web http://www.balico.com.br O Balico é um sistema na web para cadastrar profissionais a procura de emprego, e empresas com ofertas de emprego. O sistema permite o cadastro imediato e gratuito tanto de empresas quanto de profissionais. Formulários específicos dão perfil para as empresas e para os profissionais, de forma que as buscas por oportunidades são eficientes e focadas. Se você está procurando talentos, o Balico é o melhor local para veicular o seu anúncio. “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 7 5.7.1 Laço tipo “do-while” 87 5.7.2 while 88 5.7.3 for 88 5.7.4 Alterando o controle dos laços com break e continue 89 5.7.5 Exercício 89 5.8 switch-case .............................................................................................................................90 5.9 arrays ......................................................................................................................................90 5.9.1 Arrays multidimensionais 92 5.10 Parâmetros da função main ....................................................................................................92 5.11 Compilação condicional .........................................................................................................93 5.12 Pré processador e tokens (símbolos) usados pelo pré-processador ........................................93 5.13 #define ....................................................................................................................................94 5.14 operador # ..............................................................................................................................94 5.15 operador ## ............................................................................................................................94 5.16 Número variável de parâmetros..............................................................................................95 Capítulo 6) Técnicas para melhoria de rendimento em programação....................................................96 6.1 Reutilização de código ...........................................................................................................96 Vogsys http://www.vogsys.com.br/ A Vogsys Consultoria e Desenvolvimento de Sistemas, é uma empresa especializada no fornecimento de soluções integradas para o segmento de mídia, possui uma expressiva participação no mercado de publicação impressa e on-line. “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 10 8.4.3 Definindo o número de algarismos significativos 130 8.4.4 Preenchendo os espaços vazios com o método fill 131 8.4.5 Manipuladores padrão 131 8.4.6 Manipuladores do usuário 132 8.4.7 Saída com stream em buffer 133 8.5 Acesso a disco (Arquivos de texto para leitura/escrita) .......................................................134 8.5.1 Escrevendo um arquivo de texto usando a biblioteca padrão de C++ 134 8.5.2 Escrevendo um arquivo de texto usando a biblioteca padrão de C 134 8.5.3 Lendo um arquivo de texto usando a biblioteca padrão de C++ 135 8.5.4 Dica para leitura de arquivo de texto. 135 8.5.5 Lendo um arquivo de texto usando a biblioteca padrão de C 136 8.6 Acesso a disco (Arquivos binários para leitura/escrita) .......................................................136 8.6.1 Escrevendo um arquivo binário usando a biblioteca padrão de C++ 136 8.6.2 Escrevendo um arquivo binário usando a biblioteca padrão de C. 137 8.6.3 Lendo um arquivo binário usando a biblioteca padrão de C++ 138 8.6.4 Lendo um arquivo binário usando a biblioteca padrão de C 138 Capítulo 9) Programação genérica (template)......................................................................................140 VBMath – biblioteca gratuita multiplataforma para matemática http://www.vbmcgi.org/vbmath Para quem usa C++, a VBMath oferece classes para matemática matricial. Desenvolvida em programação genérica (template), o usuário pode facilmente criar classes matriciais codificadas com float, double ou long double, por exemplo. As funções básicas de operação matemática matricial estão implementadas (+, -, *, /, inverse, etc). Essa biblioteca é recomendada para implementação de contas matriciais de pequena dimensão, ou quando o requerimento de desempenho de execução não é severo. Nesse caso, aproveita-se a vantagem de fazer o programa de forma rápida e facilmente compreensível. Também está implementada uma classe (genérica) VBParser para calcular em tempo de execução o resultado de uma fórmula matemática. “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 11 9.1 Uma lista encadeada simples com template .........................................................................141 9.2 VBMath - uma biblioteca de matemática matricial usando classe template ........................146 Capítulo 10) Tratamento de exceção (exception handling)..................................................................152 Capítulo 11) RTTI – Identificação em tempo de execução..................................................................154 11.1 Introdução.............................................................................................................................154 11.2 typeid ....................................................................................................................................154 Capítulo 12) namespace .......................................................................................................................156 12.1 Introdução.............................................................................................................................156 12.2 Namespace aberto.................................................................................................................157 12.3 Biblioteca padrão de C++ usando namespace......................................................................158 12.4 Adaptando uma biblioteca existente para uso de namespace std .........................................159 Capítulo 13) STL - Standard Template Library ...................................................................................161 13.1 Introdução.............................................................................................................................161 13.1.1 Classes contenedoras 161 13.1.2 Classes iteradoras 162 13.1.3 Algoritmos 162 13.2 Preâmbulo.............................................................................................................................162 Confraria de Mercado – restaurante & palestras: encontre-se aqui http://www.confrariademercado.com.br A Confraria de Mercado é o seu ponto de encontro no Rio de Janeiro, no bairro de Botafogo (em frente a um estacionamento). É um restaurante que com comida muito boa, no estilo “simple chic”. Mas o grande diferencial é o fato de ter infra-estrutura para apresentação de palestras, com projetor (data- show) sofisticado, ligado a um computador moderno com Internet, a um vídeo cassete e ao sinal de TV a cabo. A agenda de palestras e eventos (sempre gratuitos) pode ser conferida no site, assim como mapa para chegar lá, informações de contato, etc. Para quem se cadastrar, a confraria envia propaganda dos eventos por email. Quem precisar de um local para almoço de negócios, pode reservar o local. Marque sua comemoração de formatura na Confraria de Mercado ! “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 12 13.2.1 Classes e funções auxiliares 164 13.2.1.1 Par (pair)...............................................................................................................164 13.2.2 Operadores de comparação 164 13.2.3 Classes de comparação 165 13.2.4 Classes aritméticas e lógicas 167 13.2.5 Complexidade de um algoritmo 167 13.2.5.1 Algumas regras.....................................................................................................168 13.3 Iterador (iterator) ..................................................................................................................168 13.3.1 Iteradores padrão para inserção em contenedores 169 13.4 Contenedor (container).........................................................................................................170 13.4.1 Vector 170 13.4.2 List 171 13.4.3 Pilha (Stack) 172 13.4.4 Fila (Queue) 173 13.4.5 Fila com prioridade (priority queue) 174 13.4.6 Contenedores associativos ordenados 175 13.4.6.1 Set .........................................................................................................................176 Kmail – email com inteligência. Venha para K você também. http://www.kmail.com.br Kmail é a marca que representa tecnologia de email inteligente. Filtros de email, logs especializados de email e segurança de email são alguns dos serviços que se sabe prestar. Na página da Internet, oferece-se serviço inteligente e gratuito de redirecionamento de email. O cadastro é feito imediatamente, e o redirecionamento é feito para até 5 locais, com filtros independentes. “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 15 16.5 Passagem por valor de objetos com alocação de memória...................................................198 16.6 Sobrecarga de insersor e extrator quando se usa namespace ...............................................199 16.7 Inicializando um array estático, membro de uma classe ......................................................200 16.8 SingleTon .............................................................................................................................200 16.9 Slicing in C++ ......................................................................................................................201 16.10 Dicas de uso de parâmetro implícito ................................................................................202 Capítulo 17) Incompatibilidades entre compiladores C++...................................................................204 17.1 Visual C++ 6.0 SP5..............................................................................................................204 17.1.1 for não isola escopo 204 17.1.2 Comportamento do ifstream quando o arquivo não existe 204 17.1.3 ios::nocreate não existe quando fstream é usado com namespace std 205 17.1.4 Compilador proíbe inicialização de variáveis membro estáticas diretamente 205 17.1.5 “Namespace lookup” não funciona em funções com argumento 205 17.1.6 Encadeamento de “using” não funciona 205 17.1.7 Erro em instanciamento explícito de funções com template 205 17.2 Borland C++ Builder (versão 5.0, build 12.34)....................................................................206 17.2.1 Inabilidade de distinguir namespace global de local 206 TELECOM - Curso de Especialização em Sistemas de Telecomunicações http://www.lps.ufrj.br/telecom.html O TELECOM é um curso de pós graduação latu sensu ministrado pelo DEL que oferece a profissionais de nível superior interessados nas modernas técnicas de telecomunicações conhecimentos teóricos e práticos em sistemas de telecomunicações, processamento digital de voz e imagem, sistemas de transmissão e recepção, telefonia móvel e redes de computadores. “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 16 17.2.2 Erro na dedução de funções com template a partir de argumentos const 206 17.2.3 Erro na conversão de “const char *” para “std::string” 206 17.3 Gnu C++ (versão 2.91.66)....................................................................................................206 17.3.1 Valor do elemento em vector<double> de STL 206 Capítulo 18) Glossário..........................................................................................................................208 Capítulo 19) Bibliografia......................................................................................................................209 Capítulo 20) Índice remissivo ..............................................................................................................210 Marlin http://www.marlin.com.br/ Empresa que atua na área de acesso a Internet, hospedagem, comércio eletrônico, smart cards, etc. Desenvolve soluções baseadas em XML. A empresa é parceira certificada Microsoft. Capítulo 1) Introdução 1.1 Prefácio A linguagem C/C++ é um assunto relativamente tradicional no dinâmico mercado de tecnologia de informação, sempre cheio de novidades. Existe um acervo bibliográfico substancial sobre esse assunto. Portanto surge a pergunta: ainda há espaço para um novo livro ensinando C/C++ ? Acredito firmemente que sim, pelos motivos que exponho a seguir. 1. C/C++ deve ser ensinado como multiplataforma. Ainda há relativamente poucos livros que enfatizam o aspecto multiplataforma dessa linguagem. Muitos livros se propõe a ensinar C/C++ a partir de um compilador específico. Mas eu considero isso um erro. A ênfase no ensino de C/C++ deve ser em cima dos conceitos, e não no compilador ou no sistema operacional. No capítulo “Conheça o Seu Compilador” (página 35), há um conjunto de explicações sobre operacionalidade dos principais compiladores para Windows e unix. Além disso, há um capítulo sobre “Diferenças entre compiladores” (pagina 202), onde são listadas pequenas (porém importantes) diferenças de comportamento entre os compiladores. 2. Talvez seja um erro abandonar C++ pela linguagem java. A linguagem C++ implementa os conceitos de orientação a objetos, que são de grande valor em projetos de tecnologia de informação. Outras linguagens também o fazem. A linguagem java também implementa muito bem os conceitos de orientação a objetos, e claramente concorre com C++ como alternativa tecnológica para implementação de projetos de sistemas. Há um debate quente sobre C++ versus java. Várias universidades acreditam que não é mais necessário ensinar C/C++, porque supostamente java a substituiria com vantagem de ser mais segura, elegante, robusta, portável, etc. Eu sustento que embora a linguagem java tenha várias qualidades, é um erro parar de ensinar C/C++. Portanto, o mercado precisa seguir melhorando sempre o material tutorial para C/C++, inclusive porque há novidades acrescentadas a linguagem há relativamente pouco tempo, (e.g. namespace, RTTI, programação genérica com template, STL), e que precisam ser ensinadas com material didático sempre melhorado. 3. Deve-se ensinar regras práticas para reutilização de código, e o trabalho em equipe. Ainda há relativamente poucos livros de C/C++ que enfatizam a reutilização de código e o trabalho em equipe. A linguagem C/C++ possui grande tradição. Na prática isso significa que existem várias bibliotecas e componentes disponíveis para apoiar o desenvolvimento de projetos, sendo que boa parte desses componentes é gratuita. Mas para ser capaz de usar esse tipo de componente é preciso conhecimento. O foco é apoiar a formação de profissionais que saibam participar na prática de um esforço coletivo de desenvolvimento de um sistema. O programador deve saber usar um componente de software feito por outra pessoa, e explorar essa habilidade no sentido de maximizar seu desempenho profissional. Analogamente, é preciso saber fazer um componente de software, que possa ser usado em diversos projetos diferentes, inclusive por outras pessoas. No capítulo “Boa programação × má programação” (página 189), enfatiza-se os aspectos que um programa deve ter para atingir as necessidades práticas de empresas e organizações. Nesse capítulo, o objetivo de se obter reutilização de código, trabalho em equipe, bem como métodos práticos para minimizar a possibilidade de bugs é traduzido em regras escritas. “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 20 b. Acrescentou-se capítulo de boa programação vs. má programação c. Acrescentou-se capítulo sobre STL d. Acrescentou-se tutorial para DLL em Visual C. e. No capítulo “Conheça o Seu Compilador”, acrescentou-se referência para o compilador Borland Builder 5.0. f. Acrescentou-se índice remissivo. Nas próximas versões, esse índice deve melhorar. g. Acrescentou-se uma seção inicial de introdução dando ao leitor uma justificativa para existência desse livro, face ao ambiente do mercado de tecnologia de informação. h. Revisão geral. 8. Em Agosto de 2001, versão 5.0 a. Incluiu-se um índice. b. Retirados trechos de código em português do livro. Dessa forma, ilustra-se que é boa programação escrever o código em si em inglês. c. Incluiu-se informação sobre uso da ferramenta libtool, para criação de bibliotecas de ligação dinâmica em unix (embora ainda seja preciso melhorar essa informação). d. Incluiu-se informação sobre desenvolvimento de pacores RPM para linux. e. Melhorou-se o capítulo sobre tratamento de exceção. f. Melhorou-se o capítulo sobre namespace g. Acrescentou-se informação sobre construtor de cópia, e criação de objetos com memória alocada. h. Acrescentou-se um capítulo sobre dicas de programação. i. Acrescentou-se mensagem do patrocinador 1.3 Escolha de uma tecnologia: uma decisão estratégica O mundo que vivemos é complexo e possui quantidade extremamente grande de informações. O ambiente profissional no ramo de tecnologia de informação muda rapidamente. Muitas tecnologias nasceram e ficaram obsoletas rapidamente. Os profissionais de tecnologia de informação convive com um problema básico: que estratégia devem ter para manter-se atualizado nos conhecimentos valorizados no mercado ? Heis alguns itens a considerar na hora de definir essa estratégia: • Conhecer o mais possível o teor das opções tecnológicas disponíveis no mercado. • Estimar em que setores desse mercado se pretende atuar. • Conhecer o comportamento humano, e juntando-se o conhecimento técnico que se tem, tentar antecipar tendências do mercado. • Observar historicamente quais tipos de conhecimentos tornaram-se obsoletos, e quais foram relativamente bem aproveitados, apesar da mudança do ambiente. “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 21 1.3.1 Características do produto “software” O software é um produto com características especiais, diferentes de quase todos os outros produtos. Nessa seção, comenta-se sobre essas diferenças. Um produto tangível (televisão, computador, etc.) precisa que cada unidade seja produzida para que seja vendida. De forma semelhante, serviço tangível (limpeza, preparação de comida, segurança, etc.) precisa ser feito a cada vez que é vendido. Já um software é um produto que na prática custa apenas para ser desenvolvido. O custo de produção ou cópia é tão pequeno que pode ser considerado nulo. Uma vez desenvolvido, a firma poderia em princípio copiar e vender o software indefinidamente, com excelente lucro. Mas nem tudo são flores para uma firma de software. A concorrência é muito grande, e não se sabe a princípio se um software vai ter boa aceitação no mercado. Portanto, o negócio de desenvolver software é um tanto arriscado. Além disso, o ambiente tecnológico muda rapidamente. Para desenvolver um software, é preciso investir em salários de profissionais caros, e gastar tempo. Quando o produto fica pronto, é preciso convencer o mercado a aceita-lo, sendo que há inúmeras informações sobre software, que podem confundir o cliente final. Uma outra diferença fundamental entre o software e os demais produtos é o fato de que há vantagens para o consumidor final em haver padronização do software usado. A existência de pluralidade de padrões geralmente causa confusão, pois não é viável na prática conhecer todas as tecnologias em profundidade. Concretamente: o mundo seria muito confuso se cada indivíduo ou empresa usassem um computador diferente, com um sistema operacional diferente, com editor de texto diferente, etc. A padronização do software faz facilitar a árdua tarefa de se aprender uma nova e complexa forma de se trabalhar, e mesmo de se pensar. A existência de pessoas próximas com as quais pode-se tirar dúvidas a respeito do uso do software facilita muito a efetiva assimilação do seu uso. Se um consumidor escolher uma televisão da marca x, a probabilidade de que a próxima televisão seja da mesma marca é relativamente pequena. Há várias marcas disponíveis, e muitas delas são muito boas. O produto “televisão” é uma mercadoria. Mas se um consumidor escolhe um software para resolver um problema, se o software é satisfatório, a tendência é o consumidor recomendar sempre o mesmo software para resolver o tal problema. É fácil entender o motivo desse comportamento. A complexidade do uso do software pode ser grande, e portanto há um esforço em se aprender a usa-lo bem. Esse esforço pode ser bastante grande. O consumidor tende a recomendar o software que já usou para não jogar fora o investimento que já fez em aprender a usar o software. Outra forma de entender a diferença fundamental entre software e a maioria dos outros produtos é a seguinte. Seria possível um futuro em que produtos como televisão, gasolina, energia, roupas, etc. fossem oferecidos gratuitamente ? É muito difícil imaginar que isso pudesse acontecer. No entanto, é perfeitamente possível que exista software gratuito. Se o criador de um software não ganha dinheiro diretamente distribuindo um software gratuito, que interesse haveria em faze-lo ? Muito simples: sendo gratuito, o consumidor torna-se mais interessado em experimentar o software. Assim, facilita-se a criação de uma base de usuários do software, e portanto o produto fica mais confiável e também mais valioso. Com a base de usuários consolidada, é muito possível pensar em formas indiretas de se ganhar dinheiro. Um exemplo disso é o linux. A inércia é um termo importado do estudo de física. Sabe-se que é difícil mudar a velocidade de um corpo que possui grande massa. Para tal corpo mudar de velocidade, é preciso que se gaste muita energia. Em outras palavras: o tal corpo possui grande inércia. O comportamento humano é inercial em relação ao relacionamento com a tecnologia. Para efetivamente usar um produto tecnológico – tal como um software – é preciso que se invista energia (tempo, paciência, etc.) no estudo desse produto. Uma vez vencida a inércia e adquirido conhecimento sobre o uso de uma tecnologia, torna-se um tanto “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 22 difícil convencer um consumidor a adotar uma solução alternativa, especialmente se não houver uma vantagem palpável. Uma das formas de se interpretar o “frenesi de Internet” que ocorreu no final do milênio é justamente o reconhecimento de que seria preciso explorar rapidamente o mercado ainda virgem de pessoas que precisam de serviços de Internet. Após passada a fase na qual muitos se acostumariam com os serviços, seria cada vez mais difícil para novos entrantes no mercado, pois haveria inércia para se mudar de serviço. Atualmente vivemos uma batalha entre grandes desenvolvedores de software pago e alternativas gratuitas (por exemplo linux). As grandes firmas do setor de software procuram fazer ver ao cliente que embora seus produtos sejam pagos, o TCO (Total Cost of Ownership ou custo total de propriedade) é mais baixo que a alternativa. Supostamente, segundo o ponto de vista das grandes empresas, seria mais barato comprar produtos dela e valer-se da base instalada de usuários, suporte, etc. A alternativa de instalar um produto gratuito para a qual há muito menos disponibilidade de assistência seria mais cara, pois seria necessário pagar caro por consultoria. Além disso, os bugs que supostamente seriam mais numerosos causariam despesas para o cliente. 1.3.2 Incorporação de novidades É muito comum no mercado de software (na realidade para vários produtos de tecnologia de informação) uma situação tipo “competição Darwiniana”. Isto é, para um problema dado surgem diversas alternativas para soluciona-lo. No início, todas as alternativas são incompletas e insatisfatórias. Com o tempo, vão surgindo evoluções na qualidade do software, e cada vez menos alternativas se sustentam. Geralmente apenas uma alternativa é efetivamente usada, ou no máximo muito poucas. A competição Darwiniana descreve a competição para a definição do hardware básico (arquitetura do computador, CPU, etc.), para sistema operacional para esse hardware, para editor de texto e demais aplicativos de escritório, para comunicação pessoal com cliente de email ou outras, para navegador de Internet, etc. Uma empresa que tem um produto de software deve ter uma estratégia para fazer o seu produto ser aceito no mercado. Isso deve ser feito rapidamente, pois do contrário a maioria do mercado tenderá a convergir para uma alternativa concorrente, e depois haverá inércia para deixar de usar o que já se sabe. Há estudos que mostram como uma novidade costuma ser incorporada por um grupo social. Pode-se classificar (de forma simplificada) os usuários em 4 grupos, com suas porcentagens: 1. A - Desbravadores (10%) 2. B - Primeira maioria (40%) 3. C - Maioria atrasada (40%) 4. D - Retardatários (10%) “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 25 evidentemente uma pergunta complexa, mas a resposta certamente estará na capacidade de o profissional reciclar-se mais rápido que a média, mantendo-se sempre como um produto diferenciado. Na hora de escolher uma linguagem de programação para estudar, procure pensar a longo prazo e avaliar em quais mercados pretende atuar. 1.5 Sociedade do conhecimento A humanidade está vivendo a “sociedade do conhecimento”. O conhecimento tornou-se o mais valorizado ativo das empresas. Obter, assimilar, classificar, recuperar, acessar, interpretar, gerenciar e manipular conhecimentos são algumas das habilidades valorizadas nesse ambiente. Dentre os conhecimentos que se deve ter não incluem-se apenas os conhecimentos técnicos. Igualmente importante é ter conhecimentos sociais (relacionamentos), conhecimentos de mercado, conhecimento de como e onde se produz e se acessa (ou se compra) conhecimentos de boa qualidade, saber distinguir um conhecimento de boa qualidade de um conhecimento de qualidade desconfiável, saber para que servem os conhecimentos técnicos que se dispões, etc. Alguns conceitos fundamentais: • Dados: é um valor derivado da observação de objeto ou referência. Exemplo: 15 graus celcius. Para serem registrados, guardados e disponibilizados os dados devem estar ligados a um quadro referencial. No caso o quadro referencial é a escala de temperatura. • Informação: é uma coleção de dados relacionados que, dentro de um determinado contexto, podem transmitir algum significado a que os consulta. Exemplo: guia telefônico, tabela de temperaturas. Para quem não sabe o que é um telefone, o guia telefônico não contém informação alguma. • Comunicação: é a transferência de informações de um agente de processamento dessa informação para outro. • Conhecimento: É a familiaridade, a consciência ou entendimento conseguido seja através da experiência ou do estudo. O conhecimento pode ser classificado nas formas abaixo: o Tácito - é algo pessoal, formado dentro de um contexto social e individual. Não é propriedade de uma organização ou de uma coletividade. Em geral é difícil de ser transmitido. Por exemplo: um craque de futebol sabe dar uma bicicleta e marcar um gol. Por mais que se veja e reveja o craque fazendo isso, é difícil fazer o mesmo. o Explícito - envolve conhecimento dos fatos. É adquirido principalmente pela informação, quase sempre pela educação formal. Está documentado em livros, manuais, bases de dados, etc. Por exemplo: o conhecimento da sintaxe e da programação de C/C++ é um conhecimento explícito. Já a boa programação é em parte explícito, mas envolve uma certa dose de conhecimento tácito. A capacidade de trocar informações com um grupo (tribo) do mesmo segmento de tecnologia é um complemento fundamental para o profissional, e envolve muito conhecimento tácito. • Sabedoria: É a qualidade de possuir grande conhecimento, geralmente de mais de uma área do saber. A associação de compreensão de diversos conhecimentos faz surgir uma “compreensão geral”, ou “compreensão da grande figura”, que é exatamente o aspecto que configura a sabedoria. Uma das vertentes da sabedoria é conseguir ver o mundo pelo ponto de vista de outras pessoas. “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 26 1.5.1 Mudança do paradigma de negócios Pode-se chamar de “sociedade do conhecimento” a sociedade que em grande parte adotou para si os “paradigmas economia do conhecimento”, mais atuais, que se opões aos “paradigmas da economia do conhecimento”. Um quadro comparativo desses paradigmas é mostrado abaixo. Paradigmas da Economia Industrial Paradigmas da Economia do Conhecimento Fordismo, economia de escala, padronização Escala flexível, customização, pequenos estoques, just in time. Grandes tempos de resposta Tempo real Valorização de ativos tangíveis Valorização de ativos intangíveis Atuação local, regional Atuação global Intensivo em energia (petróleo) e materiais Intensivo em informação e conhecimento Ramos matrizes: petrolíferas, petroquímicas, automóveis, aeroespacial Ramos matrizes: eletrônico, informática, telecom., robótica, genética Qualidade do produto Qualidade do processo (além do produto) Grandes organizações verticais Sub-contratação (tercerização), downsizing, redes de relacionamento entre empresas Rigidez da hierarquia administrativa, separada da produção Flexibilidade e integração de empresa com clientes, colaboradores e fornecedores Taylorismo. Decomposição do processo de trabalho Trabalhador polivalente Empregado como gerador de custo Empregado como geradores de receita (capital intelectual) Pleno emprego Empregabilidade Pouco ou nenhum aprendizado no trabalho Aprendizado contínuo Qualificação formal Competência (capacidade efetiva de resolver problemas) 1.5.2 “Mercadorização” Tradicionalmente, se um segmento do mercado estiver na situação de escassez e com ganhos relativamente altos, esse segmento torna-se atrativo para negociantes. Desde que exista informação disponível sobre o ambiente de negócios, a tendência é de o segmento atrair novos entrantes, que farão aumentar a oferta de produtos, até que o preço se estabilize num patamar razoável (com taxas de lucro relativamente pequenas), quando então diz-se que o segmento de mercado está maduro. No ambiente atual, a Internet ajudou a tornar as informações mais abundantes e baratas. Portanto como nunca há reportagens informando qualquer segmento de mercado que esteja “dando dinheiro”. Além disso, a facilidade de comunicação tornou o conhecimento rapidamente transferível de um local “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 27 a outro. Com isso, serviços de conhecimento passaram a ser globalizados. Por exemplo: pode-se desenvolver software num país para um cliente em outro país. O efeito final desses fatores é a chamada “mercadorização” do ambiente de negócios. Isto é, tudo transforma-se numa mercadoria, e rapidamente. A concorrência em todos os setores parece ser incrivelmente grande, e o consumidor exige preço e qualidade como nunca, sabendo que há inúmeras opções caso não se sinta satisfeito. Isso é bom para quem compra, mas torna-se difícil a vida de quem quer vender. E todos nós temos que vender alguma coisa, nem que seja a nossa capacidade profissional no mercado. 1.5.3 Remuneração × agregação de valor na cadeia produtiva O processo de produção de um produto (ou serviço) é geralmente composto de várias etapas, ou elos. Pode-se dizer que há uma “cadeia produtiva” que faz surgir o produto. Com a comercialização do produto final, faz-se caixa (ganha-se dinheiro), com o qual se remunera direta ou indiretamente toda a cadeia produtiva. Uma das características da sociedade do conhecimento é que as melhores remunerações da cadeia de valor acabam sendo dos elos que agregam alto valor de conhecimento. Por exemplo: na produção de um carro, o ato de montar as peças não agrega tanto valor de conhecimento quando o projeto de um carro novo. E a remuneração do projetista é maior do que a do montador. Na escala mercadoria- produto_diferenciado, o projetista de carro está mais para produto diferenciado, enquanto o montador está mais para mercadoria, Mas gradativamente mesmo o projetista torna-se também uma mercadoria, e passa a ter menores remunerações. Apenas um projetista que saiba fazer algo difícil (entenda-se: que poucos sabem fazer) e útil (entenda-se: valorizado no mercado) consegue obter boa remuneração. 1.6 Porque C/C++ ? De tudo o que foi dito (até agora) nesse capítulo de introdução, o que se pode concluir sobre a escolhe de uma linguagem de programação para um estudo profundo ? 1.6.1 “Tribos” de tecnologia O uso de uma tecnologia - tal como uma linguagem de computador - geralmente cria uma “tribo” de usuários que gostam dessa tecnologia. Os membros da “tribo” costumam achar que a “sua” linguagem é a melhor, por isso é que torna-se difícil julgar de forma isenta qual seria a linguagem melhor. A mentalidade de tribo é de certa forma semelhante a mentalidade que une os torcedores de um time de futebol, ou os crentes de uma religião. Por exemplo: quem está habituado a usar unix (e.g. linux) como servidor, geralmente não tolera usar Windows. Vice versa também acontece. Uma empresa com cultura Windows bem consolidada muitas vezes reluta em usar servidores unix, ainda que gratuitos. Para quem conhece bem uma certa linguagem de computador, e essa linguagem atende às suas necessidades, a tal linguagem é em princípio a melhor opção. Mas a experiência mostra que o ambiente de trabalho com tecnologia de informação muda constantemente, e muito rapidamente. Uma linguagem de computador não se “deteriora”, no mesmo sentido que uma máquina velha o faz. Mas considerando-se a constante mudança do ambiente, se uma linguagem de computador deixa de ter suporte às novidades que o mercado exige, então essa linguagem de certa forma está se deteriorando. Há inúmeros exemplos de linguagens de programação muito boas que entraram em desuso, pois não houve uma “manutenção”. O dBase ou o Clipper para sistema operacional DOS, são um bom exemplo. São duas linguagens que foram muito importantes no seu tempo. Mas o ambiente passou a “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 30 na linguagem C/C++ levará o programador a uma versatilidade enorme. Esse conhecimento pode ser usado para programar inúmeros ambientes, incluindo Windows, Unix (Linux, FreeBSD, etc.), computador de grande porte, implementação de interatividade em páginas Internet, diários portáteis tipo Palm Pilop ou Windows CE, dispositivos programáveis como DSPs, microcontroladores, etc. Se surgir no futuro algum tipo novo de processador ou computador que apresente alguma vantagem sobre o que existe hoje, com certeza uma das primeiras coisas que se fará para esse novo processador é o compilador mais fácil de se fazer - da linguagem C/C++. 1.7 Breve história do C/C++ A linguagem de programação C / C++ está em constante evolução, e isso é bom. Tudo começou com a linguagem BCPL, por Martin Richards, que rodava no computador DEC PDP-7, com sistema operacional unix (versão da época). Em 1970, Ken Thompson fez algumas melhorias na linguagem BCPL e chamou a nova linguagem de “B”. Em 1972, Dennis Ritchie e Ken Thompson fizeram várias melhorias na linguagem B e para dar um novo nome a linguagem, chamaram-na de “C” (como sucessor de “B”). A linguagem C não foi um sucesso imediato após a sua criação, ficando restrita a alguns laboratórios. Em 1978 (um ano histórico para os programadores C), é lançado um livro famoso por Brian Kernigham e Dennis Ritchie. Esse livro serviu de tutorial para muita gente e mudou a história da programação em C. De fato, essa primeira versão da linguagem C é até hoje conhecida como “C Kernigham e Ritchie” ou simplesmente “C K&R”. Em 1981, a IBM lança o IBM PC, iniciando uma família de computadores de muito sucesso. A linguagem C estava no lugar certo e na hora certa para casar-se com o fenômeno dos computadores pessoais. Logo foram surgindo inúmeros compiladores para PC e a linguagem C estava livre do seu confinamento inicial no sistema operacional unix. Conforme a tecnologia de software foi se desenvolvendo, o mercado exigiu que se introduzisse mudanças na linguagem C. Talvez nós devêssemos nos referir as várias versões de C como “C 1.0”, “C 2.0”, etc., mas o mercado geralmente não usa essa nomenclatura. O fato é que modificações importantes foram pouco a pouco sendo introduzidas na linguagem. Uma modificação importante foi a padronização feita pelo American National Standards Institute (ANSI), em 1983, que criou uma linguagem conhecida como “C ANSI”. Entre outras modificações, o C ANSI mudou a forma de se definir um protótipo de função, para que se possa conferir esse protótipo na hora da compilação e acusar erros no caso de se chamar uma função com parâmetros errados. No quadro abaixo é mostrado um exemplo de como se escrevia uma função (fun1) em C K&R e como passou a se escrever em C ANSI. Se segunda função (fun2) chama a primeira com parâmetros errados, o C K&R não tem como saber do erro na hora da compilação, mas o C ANSI acusa o erro e com isso ajuda o programador a depurar o seu código. C K&R C ANSI void fun1 (i, k) int i, k; { ... } void fun1 (int i, int k) { ... } “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 31 void fun2 () { int a1, a2; float b1, b2; /* variáveis locais */ fun1(a1,a2); /* OK em ambas as versões de C */ fun1(b1,b2); /* é um erro, pois os parâmetros estão errados. Mas somente surgirá um erro de compilação no C ANSI, no C K&R não há esse tipo de checagem */ } No C K&R, como não havia como checar se uma função foi chamada com os argumentos certos, não se proibia o uso de identificadores que não previamente declarados. No exemplo acima significa que podia-se chamar a função fun1 a qualquer momento, sem necessidade de declarar o identificador da função. Com o C ANSI, passou a se recomendar (como técnica de boa programação) que toda função fosse declarada antes de ser usada, para que o compilador pudesse checar a chamada da função. A partir do C++ essa recomendação tornou-se uma obrigação, isto é, o compilador simplesmente não aceita compilar um identificador que não tenha sido previamente declarado2. ano 1990 1980 1970 C com classes (1980) ANSI C 1983; C++ (1983/84) C (K&R) (1972) livro do K&R, “The C programming language” (1978) livro do Stst, “The annotaded C++ reference manual” (1995) livro do Stst, “The C++ programming language” (1986) livro do Stst, “C++ reference manual” (1990) Figura 2: Alguns fatos relevantes na evolução da linguagem C / C++ 1.8 Qualidades da Linguagem C/C++ Há ainda outras qualidades interessantes na linguagem C/C++, listadas abaixo. 1. Não há um “dono” desta linguagem. Há vários sistemas operacionais e compiladores 100% gratuitos que usam o padrão C/C++ (o exemplo mais visível é o Linux). Isso significa na prática que essa linguagem tem inúmeros patrocinadores, famosos e anônimos. Isso mantém o suporte sempre muito atualizado e amplamente disponível na Internet. 2. Escolher C/C++ é uma opção estratégica muito interessante para uma empresa ou consultor, pois sendo um padrão amplamente difundido e com opções gratuitas. Portanto pode-se reproduzir infinitamente (sem custo adicional e sem fazer pirataria) qualquer solução que se aprenda ou se desenvolva a partir dessa linguagem. Há inúmeras opções tecnológicas de 2 Para quem está no começo da aprendizagem, pode ser um tanto difícil compreender agora a diferença entre o C K&R e o C ANSI. O importante é lembrar que o C K&R é mais antigo e mais sem proteção. O C ANSI é mais moderno e dá algumas dicas a mais para facilitar encontrar erros de programação. O C++ é mais moderno ainda, e melhor que C. “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 32 programas (com fonte incluído) disponíveis na Internet. Os links de algumas delas estão listadas na página web desse livro. 3. É verdade que a curva de aprendizado de C/C++ tende a ser mais lenta (especialmente no início) que a de outras linguagens. Mas isso pode ser compensado com um bom material didático. Esse livro, que é gratuito e distribuído na Internet, é uma contribuição no sentido de se aumentar a oferta de material didático para o estudo de C/C++. 4. Conforme será explicado em detalhes em outro trecho do livro, é possível “encapsular” complexidades de programação de forma a tornar o uso de C/C++ perfeitamente digeríveis mesmo para um programador inexperiente. Isso pode ser feito a partir do uso de bibliotecas (que existem em enorme quantidade a disposição na Internet, e que podem ser desenvolvidas/adaptadas para necessidades específicas). 5. Pode-se usar C/C++ com técnicas apropriadas para trabalho em equipe. Dessa forma, um gerente de projeto de software pode alocar tarefas para diversos programadores, que trabalham em paralelo. Com essas técnicas pode-se obter resultados excelentes no tempo de desenvolvimento de um software. 1.9 Classificação de interfaces de programas Na informática há hardware e software. O hardware é fisicamente tangível, ao contrário do software. A palavra software significa um programa de computador ou um sistema, que é um conjunto de programas de computador. Há basicamente 3 tipos de interface para programas, como mostrado abaixo em ordem de complexidade (1 = menos complexo, 3 = mais complexo). 1. Console (ou linha de comando), tela de texto tipo scroll (rolar). Exemplo: xcopy, grep. 2. Console (ou linha de comando), tela de texto cheia. Exemplo: Lotus 1-2-3, WordStar (para DOS). 3. GUI (graphics user interface), também chamado de “interface Windows”. Exemplo: sistema operacional Windows e qualquer aplicação para Windows ou o ambiente xWindows do unix. Uma interface mais complexa agrada mais ao usuário, porém complica a vida do programador. Quando o objetivo é estudar conceitos de programação, a interface é algo que a princípio não está no foco. Portanto, a interface mais adequada para estudo é a interface tipo 1 – console do tipo scroll. Em Windows, é necessário que se abra uma janela de DOS para se ter acesso ao console e poder usar programas com linha de comando (como se fazia na época que não havia Windows). Em unix, há o xWindows, que é um dos tipos de interface gráfica, e também o console de unix. 1.10 Programando para console Ultimamente, há particular interesse por aplicativos gráficos, com uso intensivo de GUI e multimedia. Há também muito interesse em programação para Internet. Para quem está em fase de aprendizado, é importante que se tenha uma base sólida de programação em console antes de se pretender programar em ambientes mais complexos. Programar para console é a abordagem que historicamente surgiu primeiro que a programação GUI. Programas para console NÃO estão caindo em desuso, apesar da popularidade dos ambientes gráficos. Um exemplo importante de como a programação para console é muito presente na modernidade do “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 35 Capítulo 2) Conheça o Seu Compilador Esse capítulo explica como conhecer o compilador que se vai usar. Cada seção fala de um compilador diferente. Portanto use esse capítulo assim: verifique dentre os compiladores abordados qual é o que você vai usar e leia essa seção. As demais seções podem ser ignoradas (a princípio), pois falam de outros compiladores. Para um compilador qualquer, é importante que se adquira as seguintes habilidades: 1. Fazer um programa tipo “hello world” para console. 2. Adicionar argumentos na linha de comando. 3. Usar o help do programa. 4. Usar “projetos” (fazer programas com múltiplos fontes). 5. Usar bibliotecas (libraries), isto é, o Incluir no projeto uma biblioteca num projeto. o Fazer uma biblioteca para uma terceira pessoa. o Examinar (listar) o conteúdo de uma biblioteca qualquer. 6. Usar ferramenta de debug. 7. Definir um identificador para permitir compilação condicional. 8. Escrever um código para detectar vazamento de memória 2.1 Visual C++ 6.0 2.1.1 Reconhecendo o Compilador O VisualC trabalha com o conceito de “workspace”. A idéia é que várias pessoas podem trabalhar com o mesmo compilador e o que uma pessoa faz não afeta o ambiente de trabalho de outra pessoa. A primeira coisa a fazer com esse compilador é criar um workspace para iniciar o trabalho. Para isso, vá no menu File - New. Na caixa de diálogo “New” que aparecer, selecione o tab “workspaces”. Digite um nome para o workspace no campo “Workspace name” (selecione também o local para o workspace). Um bom nome para o workspace é o seu nome pessoal (o nome pelo qual é conhecido, possivelmente o sobrenome; no meu caso uso “villas”; nesse exemplo, usei “villas_new”). Cria-se assim o arquivo “villas_new.dsw” “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 36 Ao entrar no VisualC uma próxima vez, abra o seu workspace e trabalhe dentro dele. Uma forma fácil de fazer isso é usar o comando pelo menu File - Recent Workspaces. “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 37 Um workspace pode conter diversos projetos. Cada projeto é uma aplicação, biblioteca, componente, etc., que se pretende desenvolver. Mantenha o “painel workspace” a mostra (use o botão “workspace” na barra de ferramentas para comutar (toggle) entre ver e não ver o painel workspace, que fica do lado esquerdo da tela). “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 40 Dentro de um mesmo workspace, podem existir vários projetos. Dentre os projetos existentes, pode haver mais de um carregado (loaded). Dentre os projetos carregados, somente um está “active” (no foco). O único projeto ativo aparece com letras em negrito (bold), e é esse projeto que está sendo compilado e “debugado”. “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 41 único projeto ativo (está em negrito) projetos carregados mas mas não ativos projetos não carregados 2.1.2 “Hello world” para DOS Crie um projeto com nome “hello console” do tipo “win32 console application”. No step 1 do application wizard, escolha “An empty project” (um projeto vazio, apesar da opção “Typical hello world application”). Clique “Finish”. O seu projeto precisa de pelo menos um arquivo de código fonte. Crie-o com File - New - (no tab Files) <C++ source file> - no campo File name, escreva o nome do arquivo, digamos, “fonte1” (na verdade fonte1.cpp, mas a extensão .cpp é automática) - deixe ativo o flag “Add to project”, para que o seu arquivo fonte1.cpp seja automaticamente incluído no projeto em questão - <OK>. “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 42 Confirme que a janela da direita está editando o arquivo fonte1.cpp olhando a barra de título do VisualC++, com “[fonte1.cpp]” do lado direito. Escreva o texto abaixo no arquivo que criado. // fonte1.cpp #include <iostream.h> void main() { cout << "Hello, world\n"; } “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 45 O programa abaixo lista os argumentos. #include <iostream.h> void main(int argc, char**argv) { cout << "Hello, world\n"; int i; for (i=0; i<argc; i++) cout << "Arg[" << i << "]:" << argv[i] << endl; } Resultado: Hello, world Arg[0]:C:\USERS\villas_C\visual_c\villas_new\hello console\Debug\hello console.exe Arg[1]:argumentos Arg[2]:do Arg[3]:programa 2.1.3 Usando o Help Aprender a usar bem o help é uma habilidade estratégica, pois é um conhecimento que permite ao programador usar o seu tempo para pesquisa pessoal no sentido de se aprimorar no uso da linguagem. Aprender a usar o help é “aprender a aprender”. Como é fundamental usar o help do programa, isso torna-se mais um motivo para que nessa apostila se use o idioma inglês misturado com português. Para se encontrar algo no help, é preciso se ter em mente as palavras chave em inglês. O help do Visual C++ 6.0 é muito grande, ocupando 2 CDs. Para não ocupar lugar demais no disco rígido do computador, a ferramenta de help vai copiando para o disco os pedaços do help a medida que vão sendo solicitados. Por isso, é sempre bom trabalhar com o Visual C++ tendo-se a mão os seus 2 CDs de help. Uma forma direta de se usar o help é comandar Help - Search - e digitar o que se quer. Nessa apostila, em vários lugares recomenda-se que mais informação seja pesquisada no help , tópico “tal”, sendo que “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 46 “tal” é uma palavra chave ou expressão chave faz o Visual C++ apontar para a parte correspondente do help. 2.1.4 Projetos (programas com múltiplos fontes) Num “Workspace” do Visual C++, há diversos projetos. Cada projeto desses pode ter um ou mais arquivos fonte. Para compilar um programa que possui mais de um arquivo fonte, basta colocar todos os arquivos fonte que compões o programa debaixo do mesmo folder “Source Files”. Não é necessário acrescentar manualmente os arquivos header no folder “Header Files”. O Visual C++ faz isso automaticamente ao compilar os arquivos *.cpp. Além de arquivos *.cpp, pode-se também acrescentar no folder “Source Files” arquivos *.obj e *.lib, desde que compilados pelo Visual C++. 2.1.5 Bibliotecas 2.1.5.1 Fazer uma biblioteca Para criar uma biblioteca estática (*.lib) com o Visual C++, comande File - New, e no tab “Projects” escolha “win 32 Static Library”. No exemplo da figura abaixo, foi escolhido o nome “myLib” para a biblioteca. “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 47 Acrescente arquivos fonte na biblioteca, como se o projeto fosse gerar um executável. Compile a biblioteca da mesma forma como se compila um executável (F7). Também da mesma forma como num programa executável, escolha a versão (debug, release) da biblioteca (veja página 42). “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 50 2.1.7.2 Class View A funcionalidade “Class View” do Visual C++ é um interessante diferencial desse produto. A idéia é “enxergar” um projeto de um programa C++ a partir da descrição de suas classes, mais que pela descrição de seus arquivos (o que corresponde a “File View”). Há inúmeras funcionalidades de navegação no código C++ a partir da funcionalidade do Class View. Por exemplo: clicando-se num método de uma classe, automaticamente o editor é aberto e o cursor posicionado na classe em questão. “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 51 classes métodos de uma classe 2.1.7.3 Usando bibliotecas de ligação dinâmica (DLL) Uma biblioteca de ligação dinâmica (“Dynamic Link Library - DLL”) é uma biblioteca que será ligada ao programa executável em tempo de execução. Para fazer uma dll, a primeira coisa a fazer é um projeto novo, em que se escolhe “Wind32 Dynamic-Link Library”, como mostrado na figura. A dll deve ter um nome (no caso “mydll”, e pertencer a algum workspace). No wizard, escolha “An empty DLL project”. Abaixo pode-se ver um exemplo de dll. Nesse exemplo, a biblioteca contém 3 funções globais. Uma é dllTest, outra é plus_1, e a terceira é plus_2. A dllTest apenas coloca uma constante string no console. As outras duas, recebem um inteiro como parâmetro e retornam um inteiro (somando 1 e 2 respectivamente). São funções simples de teste, úteis para um tutorial. “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 52 No arquivo mydll.cpp, escreve-se o corpo da dll, acrescentando-se a macro WINAPI ao protótipo da função. As regras de compilação da dll são as mesma de qualquer arquivo cpp. /////////////////////////////////////////////////////// // mydll.cpp #include <iostream.h> #include "mydll.h" void WINAPI dllTest() { cout << "You're inside a Dll" << endl; } int WINAPI plus_1(int i) { return i+1; } int WINAPI plus_2(int i) { return i+2; } No arquivo mydll.h, coloca-se apenas os protótipos das funções globais da dll, acrescentando-se a mesma macro WNAPI. Uma outra macro _MYDLL_H_ controla a possibilidade de inclusão múltipla do header mydll.h. /////////////////////////////////////////////////////// // mydll.h #if !defined(_MYDLL_H_) #define _MYDLL_H_ #include <afxwin.h> // place the prototypes of dll functions void WINAPI dllTest(); int WINAPI plus_1(int i); int WINAPI plus_2(int i); #endif // _MYDLL_H_ Além do cpp e do header, é preciso que exista um arquivo texto de definição. No caso esse arquivo é mydll.def. O modelo abaixo mostra como fazer esse arquivo. Além do nome e descrição, é preciso que se faça uma lista dos identificadores a serem exportados (no caso o nome das 3 funções globais). Para “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 55 2.1.7.4 DLL para Windows Tipos de dll com Visual C para Windows - Projeto “MFC AppWizard (dll)”. 1. Regular DLL with MFC static linked 2. Regular DLL using shared MFC DLL 3. MFC Extension DLL (using shared MFC DLL) A dll tipo “regular” (caso 1. e 2.) pode em princípio ser usada em outra linguagem que não Visual C++ (como Delphi). A dll tipo “extension” somente pode ser usada para programas com Visual C++. 2.1.7.5 Otimização do linker para alinhamento de código Na versão 6.0 do Visual C++, há uma opção de otimização do linker que é “/OPT:WIN98”, que é definida como verdadeira implicitamente. Com essa definição, o alinhamento do código é feito com 4K de tamanho (sem essa opção ativa, o alinhamento é de 512 bytes). O alinhamento em 4K torna o código um pouco maior. Pode-se comandar esse flag diretamente pelo código usando #pragma. No exemplo abaixo, o flag é resetado (desativado). Esse código deve ser acrescentado no início do código fonte em questão. #pragma comment(linker, “/OPT:NOWIN98”) 2.1.8 Detectando vazamento de memória Para detectar vazamento de memória, é preciso duas funcionalidades: 1. Salvar a condição da memória alocada 2. Checar a condição corrente da memória alocada. Se for igual a que está salva, conclui-se que entre o momento que se salvou e o momento que se checou não houve vazamento de memória. Ao contrário, se não for igual, conclui-se que houve vazamento de memória. Uma forma prática de lidar com o problema de vazamento de memória é escrever uma classe para essa finalidade. Abaixo está escrita essa classe específica para o compilador Visual C++ 6.0. A classe vb_memCheck possui apenas 2 métodos. O construtor salva a condição de memória alocada. O outro método é check, que checa o vazamento e manda para o console informação de vazamento de memória caso haja algum. Se não houver vazamento, o método check não faz nada. #include <crtdbg.h> // include necessary to handle memory leak debug (win32 only) // use this class for Visual C++ 6.0 only !! class VBMemCheck { _CrtMemState s1; public: VBMemCheck() { // store memory on constructor // Send all reports to STDOUT _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE ); _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT ); _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE ); _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT ); _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE ); _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDOUT ); // Store memory checkpoint in s1 (global variable) memory-state structure _CrtMemCheckpoint( &s1 ); }; void check() { _CrtDumpMemoryLeaks(); “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 56 }; }; No exemplo de utilização abaixo, não há vazamento de memória. void main () { cout << "hello" << endl; VBMemCheck c; // construtor salva condição da memória int *p_i=new int; // código que pode ter vazamento de memória delete p_i; c.check(); // manda aviso para console caso haja vazamento } Nesse caso, o resultado é: hello Caso haja vazamento de memória, como no caso abaixo, void main () { cout << "hello" << endl; VBMemCheck c; // construtor salva condição da memória int *p_i=new int; // código que pode ter vazamento de memória c.check(); // manda aviso para console caso haja vazamento } O resultado é: hello Detected memory leaks! Dumping objects -> {20} normal block at 0x00780DA0, 4 bytes long. Data: < > CD CD CD CD Object dump complete. 2.2 Borland C++ builder 5.0 Essa versão do compilador C++ da Borland foi lançada no ano de 2000. Trata-se de um produto com muitas funcionalidades. A mesma Borland possui também um produto chamado Delphi, que é uma variante de Pascal, e é considerado um RAD (Rapid Application Environment, ou ambiente de [desenvolvimento] rápido de aplicação) muito aceito no mercado. O Borland builder é uma tentativa de refazer o ambiente RAD do Delphi em C++. As semelhanças entre o ambiente gráfico do Delphi e do builder são óbvias. Com respeito a programação para Windows, a Borland já recomendou o uso da biblioteca OWL. Posteriormente, já há algum tempo, vem recomendando o uso de outra biblioteca chamada VCL. Tanto OWL quanto VCL são de autoria da Borland. É interessante lembrar que a Microsoft recomenda o uso da biblioteca MFC, de sua própria autoria. Não é viável na prática desenvolver programas para Windows em C++ sem uma biblioteca de apoio. A decisão de qual biblioteca usar é estratégica, pois trata-se de algo que requer tempo para se aprender. Por várias razões, principalmente por razões estratégicas e de mercado, eu recomendo o uso de MFC (que pode ser usado tanto pelo compilador da Borland quanto pelo compilador da Microsoft). Nessa seção, fala-se de como usar o Borland C++ builder para programas DOS. “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 57 2.2.1 Reconhecendo o Compilador O builder 5 é um programa que não usa a estrutura (framework) padrão de SDI nem de MDI. O programa em si é uma pequena janela apenas (na forma padrão) com barra de título (title bar), menu, e duas barras de ferramentas (toolbars) (veja figura abaixo). Pode-se editar mais de um arquivo ao mesmo tempo, por isso o programa é de certa forma parecido com a estrutura MDI. Geralmente, ao abrir-se o builder 5, automaticamente outras janelas de edição são automaticamente inicializadas. Mas nesse tutorial se está partindo do programa em si (considerando que os arquivos que foram abertos automaticamente foram fechados). 2.2.2 “Hello world” para DOS Para fazer um programa para console com builder 5, escolha no menu File-New. Na caixa de diálogo “New Items”, escolha “console Wizard”. Na caixa de diálogo “Console Wizard”, escolha as opções como mostrado na figura abaixo. “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 60 2.3 C++ for win32 gratuito 2.3.1 Ming (da GNU) O compilador Ming é gratuito, baseado no compilador da GNU e funciona em DOS (também em Windows). A página web desse compilador é mostrada abaixo. http://www.xraylith.wisc.edu/~khan/software/gnu-win32/ 2.3.2 djgpp A página do djgpp é www.delorie.com/djgpp/. Nessa página, há todas as informações necessárias para copiar, instalar e usar esse compilador. Abaixo há um resumo das informações de instalação. O uso do djgpp é muito parecido com o do g++ do unix. Pegue num dos servidores ftp listados, no diretório v2gnu, os arquivos abaixo (pequenas variações nas versões dos arquivos em princípio são aceitas). As descrições do significado desses arquivos estão disponíveis na página do djgpp. • bnu2951b.zip • djdev203.zip • gcc2953b.zip • gpp2953b.zip • txi40b.zip Descompacte todos esses arquivos para um diretório de instalação. Digamos que esse diretório de trabalho. Digamos que o nome desse diretório seja c:\winap\djgpp. Para simplificar, se quiser, crie um arquivo chamado djgpp.bat com o conteúdo abaixo. @echo off set PATH=C:\winap\DJGPP\BIN;%PATH% set DJGPP=c:/winap/djgpp/djgpp.env echo DJGPP enviromnent installed (SBVB) Um problema dessa versão de compilador é que muitas bibliotecas são acrescentadas no programa executável final. Com isso mesmo um programa pequeno (tipo “hello world” fera um executável grande (maior que 300K). 2.4 g++ (do unix) O compilador geralmente é chamado de cc, ou de gcc ou de g++. Verifique como é no seu sistema. A menos que se comande de forma diferente, o arquivo executável resultante é a.out. Lembre-se que em unix qualquer arquivo pode ser executável e não apenas os que tem extensão *.exe ou *.com. Para ver a versão do seu compilador, digite como mostrado abaixo. Uma das últimas versões disponíveis é 2.95. g++ -v Para compilar e linkar g++ main.cpp // programa com 1 só arquivo fonte “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 61 g++ main.cpp file1.cpp file2.cpp // programa com 3 arquivos fonte Caso se modifique apenas o main.cpp, pode-se compilar apenas esse arquivo e linkar com os demais com g++ main.cpp file1.o file2.o Ensina-se o compilador a procurar arquivos include em mais um diretório com a opção “- I<diretório>”. No Exemplo abaixo acrescenta-se o diretório ./include na busca para includes. G++ -I./include main.cpp file1.cpp file2.cpp 2.4.1 “Hello world” Crie o arquivo de texto f1.cpp (veja na página 42). Para criar esse arquivo de texto, use um editor de texto, como o vi ou emacs. Compile-o com cc f1.cpp. Execute-o com o comando a.out, que é o arquivo executável final (o nome a.out é padrão, mas nada impede que seja mudado posteriormente). 2.4.1.1 Adicionando argumentos para a linha de comando Chamar um programa passando argumentos pela linha de comando faz particularmente muito sentido no caso de compiladores que tem interface tipo linha de comando, como é o caso do g++ do unix (que também tem versão para Windows). Ao construir-se um programa, surge um arquivo executável com um nome, digamos “myprog”. Suponha que na linha de comando escrever-mos como abaixo. myprog 1 2 3 “abc def” Suponha também que o programa myprog seja como abaixo #include <iostream.h> void main(int argc, char**argv) { cout << "Hello, world\n"; int i; for (i=0; i<argc; i++) cout << "Arg[" << i << "]:" << argv[i] << endl; } Nesse caso, a saída do programa será como abaixo. Hello, world Arg[0]:myprog Arg[1]:1 Arg[2]:2 Arg[3]:3 Arg[4]:abc def 2.4.2 Usando o Help O help do g++ em unix é em grande parte baseado no comando man (manual), que adicionalmente dá ajuda em todo o sistema operacional unix. Por exemplo: para saber ajuda sobre a função c chamada “printf”, na linha de comando digite como abaixo. man printf 2.4.3 Projetos (programas com múltiplos fontes) Para construir programas com g++ a partir de múltiplos fontes, basta adicionar todos os fontes que pertencem ao projeto na linha de comando. Por exemplo: caso um projeto seja composto pelos arquivos f1.cpp, f2.cpp e f3.cpp (sendo que um desses arquivos contém a função main), construa o programa digitando como abaixo na linha de comando. g++ f1.cpp f2.cpp f3.cpp Caso se esteja depurando o f1.cpp, enquanto se mantém constante o conteúdo de f2.cpp e f3.cpp, pode-se compilar apenas o f1.cpp e ligar com f2.o (versão compilada de f2.cpp) e f3.o (idem f3.cpp). Para isso, compile apenas o f2.cpp e f3.cpp com o comando como na linha abaixo. “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 62 g++ -c f2.cpp f3.cpp Com esse comando, a opção “-c” (compile only) irá fazer gerar o f2.o e f3.o. Para construir o programa executável final a partir da compilação de f1.cpp com f2.o e f3.o, basta comandar como mostrado na linha abaixo. g++ f1.cpp f2.o f3.o Caso exista uma biblioteca estática que se deseje usar num projeto, simplesmente acrescentando-a à linha de comando se está incluindo a biblioteca no projeto. No exemplo abaixo, uma biblioteca chamada “libsomething.a” é acrescentada ao projeto. g++ f1.cpp libsomething.a 2.4.4 Bibliotecas Em unix, as bibliotecas estáticas têm extensão .a e as dinâmicas tem extensão .so (como referência, em DOS/Windows, geralmente a extensão das bibliotecas estáticas é .lib, e das dinâmicas é .dll). No caso de unix, é comum que as bibliotecas dinâmicas coloquem a versão após o .so. unix_static_lib.a unix_dynamic_lib.so dos_static_lib.lib dos_dynamic_lib.dll O utilitário para criar e manter bibliotecas é o ar. Para referência completa do ar, comande man ar. Para facilitar a compreensão, heis uma sugestão de convenção de nomes para bibliotecas em unix. Pense num nome que identifique a biblioteca. A sua biblioteca deve se chamar lib_nome.a. 2.4.4.1 Incluir uma biblioteca num projeto Na linha abaixo, compila-se o fonte m1.cpp, que tem chamadas a biblioteca lib_teste.a. O arquivo de include usado dentro de m1.cpp está no diretório corrente (.), portanto esse diretório foi incluído na busca de includes. g++ -I. m1.cpp libmylib.a 2.4.4.2 Fazer uma biblioteca Para se criar a biblioteca libmylib.a contento os arquivos myfile1.o, myfile2.o, etc usa-se o comando abaixo: ar -q libmylib.a myfile1.o myfile2.o ... Exemplo: Para se criar a biblioteca lib_teste.a com 2 arquivos f1.cpp e f2.cpp g++ -c f1.cpp f2.cpp // compila os fontes, criando f1.o e f2.o ar -q libmylib.a f1.o f2.o // cria library “libmylib.a” contendo f1.o e f2.o 2.4.4.3 Examinar uma biblioteca Para verificar o conteúdo de uma biblioteca estática, use o comando abaixo. Tente esse comando com uma biblioteca que já esteja pronta do seu sistema. Provavelmente há várias no diretório /usr/lib. ar -t unix_static_lib.a // exemplo $ ar -t /usr/lib/libz.a __.SYMDEF uncompr.o gzio.o crc32.o compress.o inflate.o “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 65 O resultado deve ser parecido com o mostrado abaixo. /usr/bin/install -c .libs/libvblib.so.0.0.0 /usr/local/lib/libvblib.so.0.0.0 (cd /usr/local/lib && rm -f libvblib.so.0 && ln -s libvblib.so.0.0.0 libvblib.so.0) (cd /usr/local/lib && rm -f libvblib.so && ln -s libvblib.so.0.0.0 libvblib.so) /usr/bin/install -c .libs/libvblib.lai /usr/local/lib/libvblib.la /usr/bin/install -c .libs/libvblib.a /usr/local/lib/libvblib.a ranlib /usr/local/lib/libvblib.a chmod 644 /usr/local/lib/libvblib.a PATH="$PATH:/sbin" ldconfig -n /usr/local/lib ldconfig: warning: /usr/local/lib/libdb_cxx-3.1.so is not a symlink ldconfig: warning: /usr/local/lib/libdb-3.1.so is not a symlink ---------------------------------------------------------------------- Libraries have been installed in: /usr/local/lib If you ever happen to want to link against installed libraries in a given directory, LIBDIR, you must either use libtool, and specify the full pathname of the library, or use `-LLIBDIR' flag during linking and do at least one of the following: - add LIBDIR to the `LD_LIBRARY_PATH' environment variable during execution - add LIBDIR to the `LD_RUN_PATH' environment variable during linking - use the `-Wl,--rpath -Wl,LIBDIR' linker flag - have your system administrator add LIBDIR to `/etc/ld.so.conf' See any operating system documentation about shared libraries for more information, such as the ld(1) and ld.so(8) manual pages. ---------------------------------------------------------------------- // ainda há o que melhorar ! // Exemplo para usar a plus_n após ter sido instalada: // Usando a biblioteca sem fazer a sua instalação no sistema. 2.4.6 Debug Existe uma ferramenta de debug gráfica para unix e sistema GUI tipo X. Mas na prática, eu acabo usando o debug de outro sistema (um bom compilador em Windows) e passo para unix os componentes de programação já testados. Essa é uma estratégia. Quando é fundamental depurar programas no próprio unix, pode-se usar uma série de artifícios para depurar um programa sem o uso de ferramentas de debug. Por exemplo, pode-se mandar exteriorizar variáveis no meio do programa para verificar o seu conteúdo. Diretivas de compilação podem criar versões de “debug” e “release” do sistema em desenvolvimento, sendo que a versão debug é igual a versão release, a menos do acréscimo de algumas linhas de exteriorização de valores de variáveis. 2.4.7 Definindo um identificador para compilação condicional A compilação condicional é a compilação de trechos de código fonte a partir de uma condição. // vb100.cpp // in unix compile it with the comand line below // g++ -DGCC vb100.cpp #include <iostream.h> void main () { cout << "hello" << endl; #ifdef WIN32 cout << "I am compiling for WIN32" << endl; “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 66 #endif #ifdef GCC cout << "I am using g++ compiler (UNIX)" << endl << "and I defined the \"GCC\" constant in the compiler line command " << endl; #endif } 2.4.8 O pacote RPM do linux Originalmente, o unix exige uma quantidade de conhecimentos considerável para a instalação de um programa. Geralmente um arquivo compactado é fornecido. Ao ser aberto em um diretório, há que se ler um as instruções num arquivo geralmente nomeado como INSTALL. Essas instruções são algo como executar “./config”, e depois “make install”. Mas na prática, não é incomum que se exija vários parâmetros de configuração a mais na hora da instalação. O sistema operacional linux possui uma forma de instalação de programas que é bastante mais fácil que a forma tradicional. Essa forma é conhecida como rpm (uma extensão de arquivo). O significado de rpm é Redhat package manager (Redhat é uma distribuição famosa de linux). Procure “rpm” no site do Redhat, ou vá direto para a página deles ensinando a usar rpm, em [1]. O resumo de rpm é mostrado nessa seção. O pacote rpm é compatível com diversos variantes de unix, e não apenas para linux. Dentre os serviços que o rpm oferece incluem-se • Instalar ou dar upgrade do software, verificando dependências. • Enquanto instala o software, verificar se o executável fica pronto para usar. • Recuperar arquivos que por ventura tenham sido acidentalmente apagados de uma instalação prévia. • Informar se o pacote já está instalado. • Descobrir a qual pacote corresponde um determinado arquivo. 2.4.8.1 rpm binário e rpm com fonte Há dois tipos de arquivos rpm. Um deles é binário (pré-compilado), e o outro vem com os fontes, e instala-se a partir da compilação (forma mais lenta de instalar, contudo mais segura e mais portável). A designação do rpm binário é *.rpm. A designação do rpm com fonte é *.src.rpm. 2.4.8.2 Alguns comandos do rpm Veja todos os comandos do rpm rodando simplesmente rpm • Instalando um pacote rpm: rpm -i <package>.rpm • Desinstalando um pacote rpm: rpm -e <package_name> • Instalando um rpm diretamente da rede (sem haver cópia local). rpm -i ftp://<site>/<directory>/<package>.rpm Exemplo: rpm -i ftp://ftp.redhat.com/pub/redhat/rh-2.0-beta/RPMS/foobar-1.0-1.i386.rpm “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 67 • Verificando o sistema (conferindo o que está instalado) rpm -Va • Digamos que você encontra um arquivo e quer saber de que pacote rpm ele pertence. No exemplo abaixo, o arquivo “/home/httpd/icons/uuencoded.gif” está sendo. rpm -qf /home/httpd/icons/uuencoded.gif A saída deve ser como abaixo apache-1.3.12-2 • Pegando informações de um rpm sem instala-lo rpm -qpi <package>.rpm • Verificando quais rpm -qpl <package>.rpm 2.4.8.3 Construindo um rpm 2.4.8.3.1 Introdução Construir um pacote rpm é relativamente fácil de se fazer, especialmente se você tem o fonte do software para o qual quer fazer o pacote. O procedimento passo a passo é mostrado abaixo. 1. Prepare o código fonte do pacote, deixando-o pronto para compilar. 2. Faça um arquivo de especificação (spec file) para o pacote. 3. Execute o comando de construir (build) o pacote rpm. O arquivo de especificação é um arquivo texto requerido para se construir um pacote rpm. Nesse arquivo texto há uma descrição do pacote, instruções para permitir contrui-lo, e uma lista de arquivos binários que são instalados com o pacote. O melhor é seguir a convenção do arquivo de especificação, como mostrado no exemplo abaixo. Com essa convenção, o sistema poderá lidar com múltiplas versões de um pacote com o mesmo nome. Recomendo que a descrição do software, nome, etc. seja feita no idioma inglês. Summary: A program that ejects removable media using software control. Name: eject Version: 2.0.2 Release: 3 Copyright: GPL Group: System Environment/Base Source: http://metalab.unc.edu/pub/Linux/utils/disk-management/eject-2.0.2.tar.gz Patch: eject-2.0.2-buildroot.patch BuildRoot: /var/tmp/%{name}-buildroot %description The eject program allows the user to eject removable media (typically CD-ROMs, floppy disks or Iomega Jaz or Zip disks) using software control. Eject can also control some multi- disk CD changers and even some devices' auto-eject features. Install eject if you'd like to eject removable media using software control. %prep %setup -q %patch -p1 -b .buildroot %build make RPM_OPT_FLAGS="$RPM_OPT_FLAGS" %install “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 70 Capítulo 3) Princípios de C/C++ 3.1 O primeiro programa #include <stdio.h> void main() { printf("Hello world\n"); } A saída do programa é: Hello world Basicamente, um compilador é uma ferramenta que transforma um arquivo de texto (conhecido como texto fonte) num arquivo executável. Chama-se esse procedimento “construir (build) um executável”. As seções abaixo abordam os conceitos básicos sobre como se pode escrever o arquivo de texto fonte. 3.2 Formato livre Formato livre (free format) que significa que o compilador observa o texto fonte sem atenção a posicionamento relativo dos caracteres. Em FORTRAN, que por exemplo não possui formato livre, o código fonte só pode ser escrito a partir da coluna 7 do texto e o return no final da linha significa que o comando acabou. A maioria das linguagens modernas como C e C++ podem ser escritas em formato livre o que significa também que no lugar de 1 espaço podem haver qualquer número de espaços, returns e tabs sem qualquer alteração na compilação. Com o formato livre, as funções myinc e myinc2 abaixo são exatamente iguais. int myinc(int in) { return in+1; } int myinc2 ( int in ) { return in + 1 ; } 3.3 Chamada de função A chamada de uma função corresponde à chamada de uma sub-rotina, como ilustrado na figura abaixo. “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 71 fun1(); fun1 Figura 4: representação gráfica do fluxo de um programa na chamada de uma função Para se chamar uma função em C, basta escrever o nome da função seguido de (). Caso haja parâmetros, eles devem ser colocados dentro dos parênteses, separados por vírgulas. Mesmo que não haja parâmetros é necessário que se escreva o abre-e-fecha parêntesis vazio (). Depois da chamada da função, como depois de qualquer comando, é necessário que se pontue com ponto-e-vírgula ;. Caso haja retorno da função, uma variável de retorno colocada antes da função e o uso do operador = fazem com que a variável receba o retorno da função. Não é necessário que o retorno de uma função seja usado. Caso não seja necessário usar o retorno de uma função, basta ignorar esse valor de retorno. Exemplo: double triple(double d) { return 3*double; } void main () { double d=2.2; double dd = triple(d); triple(d); // o retorno não é usado. Nesse caso não faz nada, mas é legal. } 3.4 Declaração e definição de funções É importante entender bem a diferença desses dois conceitos. 1. “Declarar uma função” signigica dizer qual é o protótipo dessa função, isto é, quantos são os parâmetros e de que tipo, bem como o tipo de retorno. 2. “Definir uma função” significa escrever o conteúdo da função. Ao se definir uma função, se está declarando também. Mas não o contrário. O compilador somente pode compilar uma função se ela tiver sido declarada antes de ser usada. Declaração Definição int plus_3(int); int plus_3(int in) { return in+3; } 3.5 Comentários É muito útil que se possa inserir comentários num texto fonte. Em C, os comentários são tudo que se situa entre a abertura de comentário /* e o fechamento de comentário */. Veja o exemplo abaixo. int num_alunos; /* variável que armazena o numero de alunos */ num_alunos = 4; /* carrega o número de alunos que há na primeira fila */ /* etc */ “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 72 Uma das utilidades de um comentário é que se retire temporariamente do programa um trecho de código. Chama-se isso de “comentar para fora”5. Mas pela definição da linguagem, os comentários não aninham6 (embora em algumas implementações do compilador os comentários aninhem). Portanto uma tentativa de se comentar para fora um trecho de programa que contenha comentários pode levar a problemas. Veja o exemplo abaixo. Nesse caso, o início do comentário para fora é fechado no fim da segunda linha. Portanto o código num_alunos=4; será compilado. /* ========================= comentado para fora - início int num_alunos; /* variável que armazena o numero de alunos */ num_alunos = 4; /* carrega o número de alunos que há na primeira fila */ ============================ comentado para fora - fim */ /* etc */ Em C++, além de se usar o comentário como em C, usa-se também outro tipo de comentário. C++ considera comentário tudo que estiver a direita de //, sendo desnecessário fechar o comentário, pois o fim da linha já significa fim de comentário. Veja o exemplo abaixo. int num_alunos; // variável que armazena o numero de alunos num_alunos = 4; // carrega o número de alunos que há na primeira fila // etc 3.6 Identificador Identificador (identifier) se refere as palavras que o programador coloca no programa para dar nome a suas variáveis, funções, tipos, etc. Em C e C++, que são linguagens fortemente tipadas, todos identificadores devem ser declarados antes de serem usados, conforme será visto. void g() { int i; // int é palavra reservada; "i" é um identificador que representa uma //ocorrência (instância) de uma variável do tipo int (inteiro). i=3; // "i" é um identificador que representa uma variável tipo int, declarada acima. // essa variável recebe uma constante inteira 3. float area_do_circulo(float raio); // float é palavra reservada. Essa linha de programa é a declaração de uma // função, cujo identificador é "area_do_circulo". Essa função // recebe um parâmetro que é uma variável tipo float identificador é “raio”. } 3.7 Constantes literais Pode-se carregar valores constantes literais em variáveis, conforme mostrado no exemplo abaixo. int i = 3; float f = 4.5; double pi = 3.14; char ch = 'c'; char *string = "Bom dia"; // uma constante string retorna um ponteiro para char 3.8 Escopo O escopo significa “mira, alvo, intenção”7. Para a programação em C++, significa um trecho de código onde é permitido que novas definições tomem precedência sobre definições feitas anteriormente. Esse trecho de código é delimitado por { (abre escopo) e } (fecha escopo). 5 Pode-se também tirar temporariamente trechos de código com diretivas de compilação. 6 Aninhar em inglês é nest 7 Segundo o dicionário Aurélio “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 75 Capítulo 4) Estrutura do Compilador 4.1 Entendendo o Compilador Caso se utilize o sistema operacional Windows [ unix ], o que o compilador fez no exemplo “hello world” foi compilar o seu texto fonte (*.c ou *.cpp) criando um código compilado (*.obj [ *.o ]). Em seguida foi chamado o linker que ligou este último arquivo com a biblioteca padrão (standard library) do C / C++ (c.lib) e criou um arquivo executável (*.exe [qualquer extensão]). Um compilador comercial (como Visual C++, ou Borland C++ Builder) possui geralmente ambiente integrado que chama a execução de (*.exe) sob debug, mas como não foi ativada nenhuma função de debug, nada além da execução normal ocorreu e o programa rapidamente chega ao fim, retornando então ao ambiente integrado. Um programa fonte pasa por um processo de construção (build), para que seja produzido o programa executével. O processo de construção do programa é separado em duas etapas – compilação e ligação, como será explicado com mais detalhes. A figura abaixo ilustra o processo de construção de um programa. // hello.cpp #include <stdio.h> void main() { printf("Hello World\n"); } ligação (link) hello.execompilação build Figura 2: Processo de construção de um programa executável Os programas em C++ são escritos como um conjunto de funções. Uma função em C++ é uma subrotina que retorna um valor do tipo return_type, possui um nome identificador function_name e possui um número maior ou igual a zero de argumentos (mesmo que não haja argumento nenhum, é necessário o abre e fecha parênteses ()). O corpo da função é escrito no block statement, que é o espaço entre as chaves {}. Os comentários (não geram código compilado) são o que estiver entre /* e */ ou a direita de //. <return_type> function_identifier (<arguments>) { // function body } Ou em português. <tipo_de_retorno> identificador_da_função (<argumentos>) { // corpo da função } Em C++, o programa é a execução da função main. A função main, bem como todas as funções, pode chamar quaisquer funções definidas no universo do programa. O arquivo hello.cpp possui apenas a função main. Como não se deseja retorno desta função, escreve-se a palavra reservada void (cancelado) como o tipo de retorno da função main. O corpo da função contém apenas a chamada da função printf, da biblioteca padrão, cuja finalidade é colocar no console de saída (tela) o argumento “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 76 que recebeu, que é a string "Hello, world\n". O \n no final significa <return>, isto é, mudar de linha. A linha #include <stdio.h> no início do programa serve para declarar o protótipo (prototype) da função printf, conforme será visto mais tarde. 4.2 Protótipos (prototypes) Conforme foi dito, os identificadores precisam ser declarados antes de serem usados8, ou seja, antes que se possa gerar código a partir deles. Caso o identificador seja uma função global, essa função pode estar definida antes de ser usada, ou pode ser apenas declarada (protótipo) antes de ser usada. No segundo caso, é preciso que a definição exista em algum lugar do projeto, pois do contrário ocorre erro de ligação (link). A definição de uma função inclui a declaração dessa função, mas não vice-versa. Para declarar um identificador como função deve-se declarar o protótipo (prototype) da função. O protótipo da função contém apenas o tipo do retorno, o identificador da função, os argumentos entre parentesis e um ponto-e-vírgula (;) no final. O protótipo não contém o corpo propriamente dito da função nem gera código executável, apenas faz a sua declaração para permitir que o programa abaixo possa usar a função. Seja o programa abaixo. Nesse programa, define-se (e portanto declara-se) a função global “hello”, e em seguida a função global “bye”. Por último, define-se a função main, que chama a função hello e a função bye. O programa está correto (pode ser construído sem erros), pois quando se está gerando código a partir dos identificadores das funções hello e bye, esses identificadores já estão definidos. #include <iostream.h> // definição da função hello (inclui declaração) void hello() { cout << "Hello, world" << endl; } // definição da função bye (inclui declaração) void bye() { cout << "Bye bye, world" << endl; } // definição da função main void main() { hello(); // chama-se a função hello bye(); // chama-se a função bye } Saída do programa Hello, world Bye bye, world Considere agora uma variante desse programa, como mostrado abaixo. Nessa variante, primeiro declara-se os protótipos das funções globais hello e bye. A declaração desses protótipos não gera código, mas faz o compilador aprender o significado dos identificadores. Com isso, quando o compilador pode gerar código normalmente na função main (que chama hello e bye). Posteriormente à função main está a definição das funções hello e bye, em compatibilidade com os protótipos previamente declarados. Esse programa é construído sem problemas, e dá o mesmo resultado do programa anterior. #include <iostream.h> 8 Em C não é obrigatório declarar os protótipos das funções antes de usá-las, é apenas fortemente recomendável. Em C++ é obrigatório. “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 77 // declaração de funções globais (não gera-se código) void hello(); // declaração (protótipo) da função hello void bye(); // declaração (protótipo) da função hello // definição da função main void main() { hello(); // chama-se a função hello bye(); // chama-se a função bye } // definição da função hello void hello() { cout << "Hello, world" << endl; } // definição da função bye void bye() { cout << "Bye bye, world" << endl; } Como exercício, imagine que o programa acima fosse modificado e as linhas após a função main fossem apagadas, de forma que a definição das funções hello e bye não existisse mais. Nesse caso, o programa compilaria, mas não passaria pela ligação (link), que acusaria a falta das funções que foram apagadas. 4.3 Projetos em C/C++ Um projeto e m C/C++ é a forma de construir um programa executável a partir de mais de um arquivo fonte (*.c ou *.cpp). A forma como se representa a informação de quais arquivos fonte fazem parte de um dado projeto não é padrão. Ou seja, compiladores diferentes tem formas diferentes de informar quais arquivos fonte fazem parte de um projeto (ainda que usem os mesmos arquivos fonte). Para construir o programa executável a partir de um projeto, o compilador compila cada um dos arquvos fonte (*.c ou *.cpp), gerando arquivos objeto de mesmo nome e extensão *.obj (no caso de Windows) ou *.o (no caso de unix). Cada arquivo objeto contém a informação do código compilado de funções globais (e outras) definidas no arquivo fonte correspondente. // fn.c // f2.c void f2_1() { /* ... */ } void f2_2() { /* ... */ } void f2_3() { /* ... */ } // f1.c void f1_1() { /* ... */ } void f1_2() { /* ... */ } void f1_3() { /* ... */ } f2_1 f1.obj f2.obj fn.obj f1_1 f1_2 f1_3 f2_2 f2_3 fn_m ... comp. comp. comp. Figura 3: Etapa de compilação de um projeto em C/C++ Após concluída a etapa de compilação de todos os arquivos fonte, ocorre a etapa de ligação. Nessa etapa, todos os arquivos objeto do projeto são incluídos, e também a biblioteca padrão (standard library). A biblioteca padrão é automaricamente incluída em todos os projetos. Um e somente um “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 80 padrão por definição está sempre disponível em qualquer compilador. Qualquer outra biblioteca que se use deve ser adicionada manualmente. Por isso, geralmente quem usa uma biblioteca não padrão “x”, costuma ter (ou querer ter) os arquivos fonte dessa biblioteca. Assim, pode-se criar a biblioteca sempre que necessário, em qualquer compilador. 4.5.1 Utilizando Bibliotecas prontas Uma biblioteca é um conjunto de funções prontas para serem usadas. Geralmente uma biblioteca se apresenta como 2 arquivos: 1. nome_da_biblioteca.lib 2. nome_da_biblioteca.h Para se usar uma biblioteca feita por outra pessoa, basta acrescentar a biblioteca no projeto. Um projeto de teste típico com uma biblioteca conterá 2 arquivos 1. nome_da_biblioteca.lib 2. main.cpp (um arquivo fonte com a função main) Geralmente a biblioteca vem com pelo menos 1 arquivo header, com as declarações das funções que contém a biblioteca. Portanto um programa que use as funções da biblioteca deverá incluir o tal header. Exemplo: #include "nome_da_biblioteca.h" void main () { fun_da_biblioteca(); } 4.5.2 Fazendo bibliotecas Além de se criar arquivos executáveis, o compilador pode também criar uma biblioteca. Se um executável (um aplicativo) é um produto para o usuário, uma biblioteca deve ser encarada como um produto para o programador. Uma biblioteca não é executável, é um conjunto de funções compiladas (*.obj) mas ainda não ligadas a nenhum arquivo executável. Para se criar uma biblioteca, todo compilador possui uma ferramenta de criação de bibliotecas. “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 81 // f1.cpp ... ferramenta de criação de bibliotecascomp. mylib.lib mylib.a // f2.cpp ... comp. // f3.cpp ... comp. f2_1 f1.obj f2.obj f1_1 f1_2 f1_3 f2_2 f2_3 f3_1 f3.obj f3_2 f3_3 f1_1 f1_2 f1_3 f2_1 f2_2 f2_3 f3_1 f3_2 f3_3 Figura 5: diagrama da criação de bibliotecas O objetivo dessa prática é entender a criação e uso de bibliotecas. Nesse sentido, será feita uma biblioteca que não tem utilidade prática. Isto é, as funções da biblioteca não são úteis realmente; são apenas funções bastante simples para teste. Prática: Fazer uma biblioteca com as especificações abaixo: 1. Nome da biblioteca: plus_n, contendo 5 funções: plus_1, plus_2, plus_3, plus_4, plus_5. Cada uma dessas funções deve somar 1, 2, 3, 4 ou 5 a entrada (conforme o nome) e Resposta: Para a implementação das 5 funções serão criados 5 arquivos diferentes (não é necessário que os arquivos sejam diferentes, mas é recomendável para que a biblioteca seja mais “fatiada”, isto é, que cada fatia da biblioteca entre ou deixe de entrar no programa executável final de acordo com a necessidade do linker). Os 5 arquivos plus_?.cpp estão mostrados abaixo. // plus_1.cpp int plus_1 (int in) { return in+1; } // plus_2.cpp int plus_2 (int in) { return in+2; } // plus_3.cpp int plus_3 (int in) { return in+3; } // plus_4.cpp int plus_4 (int in) { return in+4; } // plus_5.cpp int plus_5 (int in) { return in+5; } “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 82 Para permitir o uso da biblioteca, é preciso que haja um arquivo de header com os protótipos das funções que existem. O arquivo merece o mesmo nome da biblioteca, com a extensão .h. O arquivo plus_n.h é mostrado abaixo. // plus_n.h int plus_1 (int in); int plus_2 (int in); int plus_3 (int in); int plus_4 (int in); int plus_5 (int in); Utilizando-se a ferramenta de criação de bibliotecas do seu compilador, a partir dos arquivos fonte mostrados acima, cria-se a biblioteca plus_n.lib (ou libplus_n.a). Para se testar a biblioteca, é preciso que exista um programa principal com a função main (a biblioteca não contém a função main). O programa abaixo test_plus_n.cpp usa funções da biblioteca. // test_plus_n.cpp #include <iostream.h> #include "plus_n.h" void main() { int k = 10; cout << "k = " << k << "; k+3 = " << mais_3(k) << endl; } A saída do programa é como mostrado abaixo. k = 10; k+3 = 13 Exercício: Acrescente à biblioteca plus_n, feita na prática anterior, as funções plus_6 e plus_7. Altere o programa principal para que use uma dessas duas funções para testar a nova biblioteca. 4.6 Regras do compilador O compilador segue um conjunto pequeno de regras simples para fazer o seu trabalho de construir o programa executável. Nessa seção, fala-se desse pequeno conjunto de regras. O nome “compilador” é ligeiramente inadequado. O nome mais correto do programa compilador seria programa “construtor” (builder), pois é isso (construir) que o programa compilador realmente faz. A construção é o procedimento que inclui “compilar” e “ligar (link)”. • Quando analisa um código, o compilador faz uma das duas coisas: o Gera código. o Aprende uma informação, que poderá ser útil para gerar código mais tarde. • O compilador somente pode gerar código a partir de identificadores que tenham sido previamente declarados. • Ao definir-se uma função, também se está declarando-a. Mas ao declarar-se uma função, não se está definindo. Declarar uma função é o mesmo que escrever o seu protótipo. • O compilador precisa conseguir compilar cada arquivo fonte (*.c ou *.cpp) em uma única passagem, de cima para baixo. Do contrário, ocorre erro de compilação. • A construção de um executável é feita em duas etapas – compilação e ligação. “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 85 cout << "a=" << a << endl; f3(a); cout << "a=" << a << endl; } Resultado: a=10.1 a=10.1 a=2.2 a=3.3 Em C, a única forma de se passar parâmetros por referência é como mostrado em f2. Em C++, pode-se usar como mostrado em f3, que é mais elegante. Os motivos para se optar por passar um parâmetro por valor ou por referência são vários (não apenas o fato de a função alterar ou não alterar o valor do parâmetro). Um deles trata do tempo de execução. Como as variáveis passadas por valor recebem uma cópia do seu valor quando é chamada, se essa variável é grande (pode ocorrer no caso de variáveis estruturadas, veja a seção 7.4 ) o tempo de cópia pode ser significativo, principalmente se essa chamada é feita num trecho repetitivo de programa, como um loop. Uma variável passada por referência passa somente o ponteiro da variável para a função, e o ponteiro tem valor fixo independente do tamanho da variável. 5.2 Tipos de dados definidos pelo programador Além dos tipos padrão, o programador pode definir tipos próprios com diversas finalidades, que após definidos passarão a ser tão válidos como os demais. Pode-se, por exemplo, criar o tipo REAL que será usado no lugar dos tipos de ponto flutuante com finalidade de facilitar a substituição do tipo básico de ponto flutuante em todo o programa. No exemplo abaixo, foram definidas duas funções com parâmetros em ponto flutuante onde foi usado o tipo do usuário definido como REAL. que corresponde ao tipo padrão float. Caso se deseje substituir em todo o programa, para efeito das funções definidas pelo usuário, o tipo float pelo tipo double, basta trocar a definição do tipo do usuário REAL de float para double. Exemplo: typedef float REAL; // defino o tipo real REAL myinverse(REAL x) { // declaro e defino uma função usando o meu tipo REAL return (1./x); } REAL mydoubleinverse(REAL x) { // outra função com o tipo REAL return (1./x/x); } Também é considerado tipo do usuário (data type) uma lista de identificadores com a palavra reservada enum. Por exemplo: typedef enum days {sun,mon,tue,wed,thu,fri,sat}; // cria o tipo days days today; // cria ocorrência do tipo days com today ou em português typedef enum dias {dom,seg,ter,qua,qui,sex,sab}; // cria o tipo dias dias hoje; // cria ocorrência do tipo dias com hoje 5.3 Maquiagem de tipos (type casting) Muitas vezes é preciso converter um tipo para outro. Por exemplo: int para float, etc. Em alguns casos o compilador sabe que tem que fazer a conversão e faz automaticamente para você. Algumas vezes a conversão não é feita automaticamente mas pode-se forçar a conversão maquiando o tipo. Para fazer a maquiagem, basta colocar antes da variável ou função em questão o novo tipo entre parênteses. No exemplo abaixo, a maquiagem de tipo garante a divisão em ponto flutuante. “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 86 #include <iostream.h> void main () { float f; f = 2/5; // divisão de ints cout << "f = " << f << endl; // resultado errado f = (float)2/(float)5; // type cast garante divisão de floats cout << "f = " << f << endl; // resultado certo } Muitos autores estão recomendando evitar o uso direto de maquiagem de tipos, como mostrado no programa acima. É mais seguro a utilização de static_cast (palavra reservada), como mostrado no programa abaixo. #include <iostream.h> void main () { float f; f = 2/5; // divisão de ints cout << "f = " << f << endl; // resultado errado f = static_cast<float>(2)/static_cast<float>(5); // type cast garante divisão de floats cout << "f = " << f << endl; // resultado certo } Em ambos os programas, a saída é como mostrado abaixo. f = 0 f = 0.4 5.4 Operações matemáticas Para se escrever operações matemáticas básicas, basta escreve-las no programa da mesma forma como no papel, respeitando-se a precedência dos operadores da mesma forma também. double z,y,x; y=3.33; z=4.5677; x=y*y+z*3-5; A biblioteca padrão oferece também inúmeras funções matemáticas de interesse geral, listadas abaixo. Para maiores informações sobre essas funções, consulte qualquer referência ou o help do compilador. Funções matemáticas da biblioteca padrão de C acos asin atan atan2 sin tan cosh sinh tanh exp frexp ldexp log log10 modf pow sqrt ceil fabs floor fmod 5.5 Controle de fluxo do programa Em todos os casos o teste do controle de fluxo, que é interpretado como booleano, é qualquer variável ou função de qualquer tipo (inclusive ponteiro). 0 significa falso e 1 significa verdadeiro. Em todos os lugares onde há <statement> pode-se substituir por <block statement>, que é um conjunto de statements dentro de um escopo de chaves. { // block statement <statement1>; <statement2>; } Exemplo: void fun2() { /* ... */ } “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 87 void fun3() { /* ... */ } void fun4() { /* ... */ } // uma maneira de se chamar 3 procedimentos em seqüência void fun1 () { if (i==1) { fun2(); fun3(); fun4(); } } // função auxiliar void fun_auxiliary() { fun2(); fun3(); fun4(); } // outra maneira de se chamar 3 procedimentos em seqüência void fun1_new () { if (i==1) fun_auxiliary(); } 5.6 Execução condicional if (<variavble>) <statement> else <statement>; // optional Exemplo: #include <iostream.h> float a,b,c; // variáveis globais void main () { a=2; b=1.5; if (b==0) cout <<"c is undefined" << endl; else { c = a / b; cout << “c = “ << c << endl; } } // fim da função main 5.7 Laços (loop) de programação Os laços de programação são estruturas de uma linguagem de programação para comandar instruções que se repetem num programa. Há 3 estruturas de laço em C++, mostradas abaixo. 5.7.1 Laço tipo “do-while” do <statement>; while (<variable>); Exemplo: #include <iostream.h> void main() { int i=5; do { cout << "i = " << i << endl; i--; // i = i - 1 } “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 90 } } void main() { int tab_min=3; int tab_max=6; for (int i=tab_min ; i <= tab_max ; i++) imprime_tabuada(i); } O Visual C++ possui uma sutil diferença na implementação do for, como mostrado na seção 17.1.1 (página 204). 5.8 switch-case O switch, case e default (implícito) são palavras reservadas que servem para definir múltiplo redirecionamento do fluxo do programa. Freqüentemente também se usa a palavra reservada break. Heis a sintaxe: switch (<expr>) { case <item>: <statements>; case <item>: <statements>; default: <statements>; // quando nenhum dos itens coincide } Exemplo: #include <iostream.h> enum days {sun,mon,tue,wed,thu,fri,sat}; // cria o tipo days days today; // cria ocorrência do tipo days com today void m() { today = sat; switch (today) { case mon: case tue: case wed: case thu: case fri: cout << "Vá para o trabalho" << endl; break; case sat: cout << "Limpe o jardim e "; case sun: cout << "relaxe." << endl; break; default: cout << "Erro, dia não é definido"; // quando nenhum dos itens coincide } } void main () { m(); } 5.9 arrays Os arrays estáticos são declarados como: <tipo_do_array> <nome_do_array>[<dimensão>]; Um array reserva espaço na memória para <dimensão> elementos do tipo <tipo_do_array> desde a posição [0] até a posição [<dimensão> - 1]. Exemplo: double vector_a[10]; // vector_a[0] até vector[9] “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 91 vector_a[2] = 1.23; // uso do array vector_a[0] vector_a[1] vector_a[2] vector_a[9] ... vector_a vector_a = = &vector_a[0] Figura 6: Visualização gráfica do array na memória No exemplo acima, o identificador vector_a é uma constante do tipo (double *), ou seja, ponteiro para double. Ao declarar double vector_a[10], o compilador reserva espaço para 10 variáveis do tipo escolhido double e a própria variável vector_a é o ponteiro double* que aponta para o início das 10 variáveis. Ao usar uma das variáveis do array com o uso do operador [], o que realmente se está fazendo é uma indireção do ponteiro somado ao índice escolhido, conforme será explicado na seção abaixo. Ao se utilizar um array, não há range-check, isto é, checagem de tentativa de acesso fora da dimensão máxima do array. Exemplo: #include <iostream.h> void main() { double valores[4]; // define-se um array // carrega-se valores no array valores[0] = 1.0; valores[1] = 1.1; valores[2] = 1.2; valores[3] = 1.3; for (int i=0; i<4 ; i++) cout << "valores[" << i << "] = " << valores[i] << endl; } Resultado: valores[0] = 1.0; valores[1] = 1.1; valores[2] = 1.2; valores[3] = 1.3; No exemplo abaixo, define-se um array de strings com 4 posições, devidamente carregado com constantes. Nesse caso, existem as posições [0], [1], [2] e [3]. Em seguida, executa-se um laço que manda imprimir o conteúdo do array, mas o programa comanda o laço indo até a posição [4]. Isso não gera um erro de compilação ou de execução, mas é um erro de lógica, pois o valor do array na posição [4] não é definido. Exemplo: #include <iostream.h> void main() { char* nomes[4] = {"Manuel", "Joaquim", "Maria", "Bruno"}; for (int i=0; i<5 ; i++) “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 92 cout << "Nome[" << i << "] = " << nomes[i] << endl; } Resultado: Manuel Joaquim Maria Bruno sldflaskf j;alsdkj (indefinido) 5.9.1 Arrays multidimensionais São muito semelhantes aos arrays de 1 dimensão. Para a definição, apenas acrescenta-se a segunda dimensão após a primeira. A utilização é feita da mesma forma que a definição, com múltiplas indireções ([i][j]...). Na declaração de um array estático, caso se queira carrega-lo com um valor de inicialização na compilação, pode-se declarar o array omitindo-se a primeira dimensão, pois os dados declarados a seguir contém esta informação. Todas as dimensões exceto a primeira precisam ser declaradas. Veja o exemplo: Exemplo: void fun() { // aqui também se exemplifica como inicializá-lo na compilação int a [][4] = { {1,2,3,4} , {5,6,7,8} , {9,10,11,12} }; int b [][4][5] = { {1,2,3,4} , {5,6,7,8} , {9,10,11,12} }; int i = a[1][1]; // uso de array multivariável } 5.10 Parâmetros da função main Na verdade, o programa gerado por um compilador C / C++ deve ser entendido como o código fonte abaixo: // inicializações do compilador exit_code = main (argc, argv); // finalizações do compilador A função main é aquela que chama o próprio programa, conforme já foi explicado. Esta função admite ter parâmetros (argumentos) que são as palavras escritas na linha de comando que chamou o programa. O protótipo da função main é: int main (int argc, char *argv[]); O retorno da função main é o código de retorno ao sistema operacional, que só interessa para que um arquivo *.bat do DOS (em programas para Windows), ou um script em um programa em unix, mas isso não será abordado aqui. O primeiro argumento int argc é o número de parâmetros passados ao programa (incluindo o próprio nome dele) e o segundo char **argv é um array de strings (char*) cujos conteúdos são exatamente os parâmetros passados. Veja o exemplo. Exemplo: #include <iostream.h> void main (int argc, char *argv[]) { for (int i=0 ; i < argc ; i++) cout << "o argumento de chamada numero " << i << " é " << argv[i] << endl; } “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 95 5.16 Número variável de parâmetros Uma função pode ter número variável de parâmetros. Mas para usar esse recurso, a função deve de alguma forma saber quantos parâmetros serão chamados. Veja o exemplo abaixo. #include <iostream.h> #include <stdarg.h> double sum_parameters(int num,...) { double sum = 0.0; double t; va_list argptr; va_start(argptr,num); // initialize argptr // sum the parameters for ( ; num ; num--) { t = va_arg(argptr,double); sum += t; } va_end(argptr); return sum; } void main () { cout << "the sum is " << sum_parameters(2, 1.2, 3.4) << endl; cout << "the sum is " << sum_parameters(3, 1.2, 3.4, 4.4) << endl; } A saída do programa é como mostrado abaixo. the sum is 4.6 the sum is 9.3 “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 96 Capítulo 6) Técnicas para melhoria de rendimento em programação 6.1 Reutilização de código O trabalho de programação é um trabalho caro. Projetos grandes na área de software requerem uma quantidade muito significativa de homem-hora e com isso a produção de um programa pode representar um investimento vultuoso. Além disso, a crescente complexidade do software torna praticamente impossível que apenas um indivíduo possa desenvolve-lo completamente. Até mesmo software de “média complexidade” tende a ser feito por um time. Uma das chaves para se melhorar o rendimento da programação é o reaproveitamento de “blocos de código”, também conhecido como “componentes”. Concretamente isso significa ser capaz de usar uma biblioteca feita por outra pessoa ou de entregar para outra pessoa uma biblioteca desenvolvida por você. A biblioteca, no caso, é um conjunto de componentes prontos para serem reaproveitados. Para que se possa aproveitar trabalho de outros e permitir que outros usem nosso trabalho, é preciso entre outras coisas definir uma nomenclatura para o que se está trabalhando. Para isso, define-se os termos abaixo. 1. Componente - Um componente de software é um bloco de código que pode ser usado de diversas formas dentro de um programa. Por exemplo: listas, arrays e strings são componentes que podem ser usados em muitos programas. Também são considerados componentes de software elementos de interface, como check box, ou radio button. Os componentes devem ser escritos como uma função de propósito genérico, de forma que possa ser usado das mais variadas formas. Quem desenvolve uma aplicação e quer usar um componente de software, não precisa saber como é o funcionamento interno desse componente. Tipicamente “descobre-se” um componente quando se está programando e percebe-se que há trechos de programação que estão se repetindo naturalmente. É como se algo estivesse pedindo que todos esses trechos se tranformassem num componente genérico que possa ser usado sempre que aquela necessidade surja. 2. Biblioteca (library) - É um conjunto de componentes de software prontos para serem usados pelo programador. 3. Estrutura (framework) - Um estrutura é um esqueleto de programa contendo algum código e indicação para a introdução de código extra. Uma estrutura é usada para se gerar uma aplicação com determinadas características. Uma estrutura deve ser de fácil entendimento para que um programador possa usa-la para fazer um aplicativo. Um exemplo de estrutura é um conceito usado pelo VisualC, chamado “application wizard”, que cria uma estrutura pronta para o programador. 4. Aplicação - uma aplicação é um programa completo. Os exemplos são inúmeros - editores de texto, jogos, planilhas, etc. Uma aplicação frequentemente baseia-se numa estrutura e usa diversos componentes. “C / C++ e Orientação a Objetos em Ambiente Multiplataforma”, versão 5.1 Esse texto está disponível para download em www.del.ufrj.br/~villas/livro_c++.html Por Sergio Barbosa Villas-Boas (www.del.ufrj.br/~villas) pág. 97 Seja um projeto de software cuja especificação requer que se faça gráficos a partir de dados que vem de um sensor. Nesse caso, seria muito útil ter em mãos uma biblioteca pronta com componentes que fazem gráficos de forma genérica a partir de dados também genéricos. Assim, o programador precisaria apenas escrever a parte do código para ler os dados do sensor em seguida chamar os componentes da biblioteca gráfica para que os gráficos fossem feitos. Conclusão: deve-se pensar em programação sempre considerando se um trecho de programa é de aplicação genérica ou de aplicação específica. Caso se perceba que uma funcionalidade do programa é de aplicação genérica, essa funcionalidade é candidata a um componente. No exemplo acima, as funções de uso do sensor são (a princípio) específicas. São também específicas os detalhes de como os dados devem ser mostrados no gráfico. Mas as funções que desenham gráficos são genéricas, pois desenham qualquer coisa. Nesse sentido, faz sentido colocar as funções gráficas como componentes numa biblioteca, que poderia se chamar grafico. Qualquer novo problema que precise de gráficos poderia usar esses mesmos componentes. Caso o sensor que se está usando seja ligado a uma placa de aplicação genérica acoplada ao computador, poderá ser uma boa idéia que se faça uma biblioteca também para as funções de uso desta placa. Assim, qualquer outro projeto que precise usar a tal placa com sensor poderá partir de funções de uso básico do sensor. Não se esqueça: programar é usar e desenvolver bibliotecas. Portanto, antes de se iniciar um esforço de programação, pense se o problema em questão é genérico ou específico. Caso seja genérico, procure por uma biblioteca pronta, que possivelmente existe. Caso não exista uma, ou a que exista não seja satisfatória, considere desenvolver uma biblioteca para o problema genérico em questão. Assim, a próxima pessoa que pensar nesse assunto possa aproveitar parte do seu esforço de programação. É importante também que se saiba encomendar um serviço de programação. Para um certo problema pode-se solicitar a terceiros (um profissional autônomo, uma empresa, etc) que se desenvolva uma biblioteca de forma a atender as necessidades do problema, contendo funções básicas. A partir de uma biblioteca, torna-se relativamente fácil fazer “em casa” (isto é, dentro da instituição em que se trabalha) a customização do programa que se está desenvolvendo. O termo customização é um inglesismo que vem de customization, isto é, fazer alguma coisa de acordo com o gosto do custom (cliente, freguês). Portanto, customizar um programa significa implementar ao detalhe as solicitações de quem solicita o trabalho. Por exemplo: escrever as telas de entrada e saída de dados, efeitos de multimedia, etc. Pense neste exemplo: há uma placa com um sensor que se deseja usar. Pode-se solicitar a terceiros que desenvolva uma biblioteca, com fonte, contendo funções básicas de uso da placa com sensor  seleção do sensor, inicialização do sensor, leitura do sensor, etc. Tudo feito com tutorial ensinando a usar as funções desenvolvidas. A partir das funções da biblioteca, seria em princípio fácil se desenvolver um programa para usar a placa com sensor. 6.2 Desenvolvimento e utilização de componentes Para que se possa desenvolver e utilizar componentes, é preciso se pensar se um problema a ser resolvido é específico ou genérico. É muito comum que um problema possa ser dividido em uma componente específica e uma componente genérica. Por exemplo: Um programa precisa fazer uns gráficos a partir de dados que vem de um sensor. Os detalhes de como o gráfico deve ser (valor mínimo e máximo do eixo das abcissa e da ordenada, tipo
Docsity logo



Copyright © 2024 Ladybird Srl - Via Leonardo da Vinci 16, 10126, Torino, Italy - VAT 10816460017 - All rights reserved