InícioVeja Isto!@!CalendárioFAQBuscarMembrosGruposRegistrar-seConectar-se
SITE BUSCA HACKER - AONDE SUA BUSCA ACABA.

FACEBOOK - https://www.facebook.com/pages/Busca-Hack-TI/541680135902664

BLOGGER - http://buscahack.blogspot.com.br/
TEMAS
Adicionar FTN aos favoritos
Adicionar FTN aos favoritos

Compartilhe | 
 

 Entendendo profundamente C C++ Aula 2 [Madinbu] Top

Ver o tópico anterior Ver o tópico seguinte Ir em baixo 
AutorMensagem
[FTN]MaDinbu
PointBlank TOP
PointBlank TOP
avatar

Masculino
Mensagens Mensagens : 676
Pts FTN Pts FTN : 90980
Reputação Reputação : 416 Inscrição Inscrição : 05/11/2011
Pretendo ser Pretendo ser :
  • Programador


ClicksPoints
ClicksPoints: ClicksPoints
ClicksPoints:
8450/10000  (8450/10000)
Patente Especial ?oO?:






MensagemAssunto: Entendendo profundamente C C++ Aula 2 [Madinbu] Top   11/1/2012, 23:33






Para muitos a transição de C para C++ não é

fácil. De fato, essa transição é freqüentemente acompanhada de muita ansiedade porque

C++ é popularmente envolto em uma aura de inacessibilidade. Por exemplo, você pode pegar

um livro sobre C++, abri-lo em uma página qualquer e deparar-se com um parágrafo mais

ou menos assim:

Do ponto de vista de

projeto, derivação privada é equivalente a compartimentação, exceto pela,

ocasionalmente importante, questão de sobreposição. Um uso importante disso é a

técnica de derivar uma classe publicamente a partir de uma classe base abstrata,

definindo uma interface, e privativamente de uma classe concreta provendo uma

implementação. Porque a herança implícita na derivação privada é um detalhe de

implementação que não é refletido no tipo da classe derivada, ela é algumas vezes

denominada "herança de implementação" e contrasta com a declaração

pública, onde a interface da classe base é herdada e a conversão implícita para o tipo

da classe é permitida. O restante é algumas vezes referido como uma a sub-tipificação

ou "herança de interface
". (Trecho extraído

de "The C++ Programming Language,

second edition, by Bjarne Stroustrup, page 413)



É realmente difícil iniciar-se em C++ com uma literatura

assim tão rebuscada, tão hermética.



Essa série de tutoriais respondem a três questões

bastante comuns:



  • Porque C++ existe e quais são suas vantagens sobre o C?


  • Que recursos estão disponíveis no C++ para materializar

    idéias orientadas a objeto?


  • Como você projeta e implementa código usando os

    princípios da orientação a objeto?




Uma vez que você tenha compreendido os recursos básicos

disponíveis no C++, e saiba como e porque usá-los, você se tornará um programador em

C++. Essas série de tutoriais vão iniciá-lo nessa direção, e tornar outros textos

sobre C++, inclusive os de Stroustrup, mais fáceis de entender.



Esses tutoriais presumem que você conhece a linguagem C.

Se esse não é o seu caso, gaste uma semana ou duas aprendendo C e então retorne a esses

tutoriais. C++ é um superset do C, portanto quase tudo que você souber sobre C vai

encontrar conexão nessa nova linguagem.



Porque C++ existe?



As pessoas que são novatas em C++, ou aqueles que lêem

livros sobre C++, geralmente tem duas perguntas:



  • "Tudo o que leio tem um vocabulário maluco:

    encapsulamento, herança, funções virtuais, classes, sobrecarga, amigos... De onde vem

    tudo isso?


  • Essa linguagem - e programação orientada a objeto de um

    modo geral - obviamente implicam em uma mudança de mentalidade, então como eu faço para

    aprender a pensar em modo C++?




Ambas essas questões podem ser respondidas, e o projeto do

C++ como um todo é facilmente inteligível, se você souber o que os projetistas do C++

pretendiam atingir quando criaram essa linguagem. Se você entender porque os projetistas

fizeram as opções que fizeram, e porque introduziram certos recursos específicos na

linguagem, então será muito mais fácil compreender a linguagem integralmente.



O projeto de linguagens de programação é um processo

evolucionário. Uma nova linguagem é criada a partir de lições aprendidas com

linguagens antigas, ou na tentativa de introduzir novos recursos e facilidades a uma

linguagem existente. Por exemplo, a linguagem Ada foi projetada originalmente para

resolver um problema aflitivo enfrentado pelo Pentágono. Os programadores, escrevendo

código para diferentes sistemas de defesa militar, tinham usado centenas de linguagens de

programação diferentes, o que tornaria, de fato, impossível manter ou aprimorar esses

sistemas no futuro. Ada tenta resolver alguns desses problemas combinando os bons recursos

de várias linguagens em uma única linguagem de programação.



Um outro bom exemplo é o processo evolucionário que

ocorreu com as linguagens de programação a partir do desenvolvimento das linguagens

estruturadas. Essas linguagens vieram em resposta a um grande problema não previsto pelos

projetistas das linguagens de programação mais antigas: o uso abusivo do comando

goto em programas muito

grandes. Em um programa pequeno o comando goto

não causa maiores problemas. Mas em um programa muito grande,

especialmente quando desenvolvido por alguém viciado no comando goto, os problemas tornam-se terríveis. O código torna-se

absolutamente incompreensível por um outro programador que tente lê-lo pela primeira

vez. As linguagens de programação evoluíram para resolver esse problema, eliminando o

comando goto inteiramente, e

tornando simples subdividir um programa muito grande em módulos ou funções pequenas,

compreensíveis e manejáveis.



C++ é uma linguagem orientada a objeto. Programação

orientada a objeto é uma reação a problemas que foram percebidos pela primeira vez em

programas muito grandes desenvolvidos na década de 70. Todas as linguagens orientadas a

objeto tentam atingir três objetivos, como uma forma de impedir que ocorram os problemas

inerentes a projetos muito grandes:



Todas as linguagens de programação orientadas a objeto

implementam data abstraction de uma forma clara usando um conceito denominado

classes. Vamos examinar data abstraction em maiores detalhes mais adiante, até porque

esse é um conceito central, muito importante, em C++. Em poucas palavras,
color="#0000A0">data abstraction é um modo de combinar dados e

as funções usadas para manipulá-los, de tal forma que os detalhes da implementação

fiquem ocultos para outros programadores
. Data

abstraction
possibilita o desenvolvimento de programas mais fáceis de manter e de

aprimorar. Todas as linguagens orientadas a objeto tentam tornar facilmente reutilizáveis

e extensíveis cada uma das partes que compõem os programas. Aqui é que o termo

objeto começa a fazer sentido. Os programas são quebrados, subdivididos, em objetos

reutilizáveis. Esse objetos podem ser agrupados de diferentes maneiras para formar novos

programas. Objetos existentes podem ainda ser estendidos. Dando aos programadores um modo

muito simples de reutilizar código, e virtualmente forçando os programadores a escrever

códigos para serem reutilizados, torna-se muito mais fácil desenvolver novos programas

remontando peças já existentes.



Linguagens orientadas a objeto visam

tornar um código existente facilmente modificável sem, na realidade, alterar fisicamente

o código
. Esse é um conceito único e muito

poderoso, porque a primeira vista parece não ser possível modificar alguma coisa sem de

fato alterá-la. Entretanto, é plenamente possível fazer isso usando dois novos

conceitos: herança e polimorfismo.

O objeto

existente permanece o mesmo, e as alterações são como que assentadas sobre ele
. A habilidade dos programadores para manter e aprimorar código de

um modo livre de erros é drasticamente melhorada usando essa abordagem.



Como C++ é uma linguagem orientada a objeto, ela contém

os três benefícios da orientação a objeto recém apresentados. C++ acrescenta ainda a

tudo isso duas outras importantes melhorias, para eliminar problemas existentes na

linguagem C original, e para tornar a programação em C++ mais fácil que em C.



C++ acrescenta um conceito denominado sobrecarga de operador. Esse recurso permite que você especifique em seus programas novos

modos de uso para operadores padrões, tais como
+

e
>>.

Por exemplo, se você quiser adicionar um novo tipo de dado, como um tipo número

complexo
em um programa em C, tal implementação não será simples. Para somar dois

números complexos, você terá que criar uma função denominada, por exemplo,

soma,   e então escrever

c3=soma(c1,c2);, onde

c1,

c2

e
c3

são valores do novo tipo

número complexo. Em C++ você pode, ao invés de criar uma nova função, sobrecarregar

os operadores
+

e
=, de tal

forma que você pode escrever
c3=c1+c2.

Dessa maneira, novos tipos de dados podem ser adicionados à linguagem de uma maneira

clara, simples, sem ajeitamentos. O conceito de sobrecarga aplica-se a todas as

funções criadas em C++.



C++ ainda simplifica a implementação de várias partes da

linguagem C, principalmente no que se refere a operações de I/O e alocação de

memória. Essas novas implementações foram criadas contemplando-se a sobrecarga de

operadores, de tal modo que tornou-se fácil adicionar novos tipos de dados e providenciar

operações de I/O e alocação de memória para os novos tipos, sem truques ou

artifícios.



Vamos examinar alguns problemas que você provavelmente

enfrentou usando a linguagem C, e então ver como eles são resolvidos pelo C++



O primeiro problema pode ser visto em toda biblioteca de

programas construída em C. O problema é demonstrado no código a seguir, o qual atribui

um valor a um string e então concatena esse valor a um outro string:



char s[100];


strcpy(s, "hello ");


strcat(s, "world");



Essa codificação não é muito bonita, mas o seu formato

ilustra muito tipicamente o que se encontra em bibliotecas criadas em C. O tipo

string

é construído a partir do

tipo matriz-de-caracteres, que é nativo em C. Devido ao fato de que o novo tipo,

string, não é parte integrante da linguagem original, o programador é

forçado a usar chamadas de funções para fazer qualquer operação com o novo tipo de

dado. O desejável é que, ao invés disso, se possa criar novos tipos de dados e lidar

com eles naturalmente, com os próprios recursos da linguagem. Alguma coisa como



string s;


 


s = "hello ";


s += "world";



Se algo assim é possível, a linguagem pode ser

estendida

ilimitadamente. C++ suporta esse tipo de extensão através da sobrecarga de operadores e

de classes. Repare ainda que usando um novo tipo
face="Courier New" size="2">
string, a implementação

tornou-se completamente oculta. Ou seja, você não precisa saber como, ou se ,o tipo

string

foi criado usando uma matriz de caracteres, uma lista ligada, etc. ou ainda se

string

tem um tamanho máximo. Melhor ainda, é fácil alterar-se, no futuro, a

implementação do tipo
string, sem

afetar negativamente os códigos que estiverem utilizando-o



Outro exemplo usando uma biblioteca pode ser visto na

implementação de uma biblioteca para tratamento de pilhas.



Os protótipos das funções para uma típica biblioteca de

tratamento de pilhas - normalmente encontrado no
size="2">
header file


-
é mostrado a seguir:



void stack_init(stack s, int

max_size);


int stack_push(stack s, int value);


int stack_pop(stack s, int *value);


void stack_clear(stack s);


void stack_destroy(stack s);



O programador usuário dessa biblioteca pode usar funções

para push, pop e

clear a pilha, mas antes, e para que qualquer uma dessas operações seja

válida, de inicializar a pilha com a função
stack_init. Ao concluir com

a utilização da pilha, deve destruí-la com a função
stack_destroy. E o que

acontece se você se esquece da inicialização ou da destruição? Em um caso real, o

código não vai funcionar e pode ser bem difícil rastrear o problema, a menos que todas

as rotinas dessa biblioteca detectem a falta da inicialização e indiquem isso

especificamente. A omissão da etapa de destruição da pilha pode causar um problema

denominado
href="CPPGlos.htm#MemoLeak">memory leak,

que é também difícil de rastrear. C++ resolve esse problema usando construtores e

destrutores, que automaticamente manejam a inicialização e a destruição de

objetos, inclusive de pilhas.



Continuando ainda com o exemplo da pilha, note que a pilha,

uma vez definida, pode push e pop números inteiros. O que acontece se você quer criar uma outra

pilha para lidar com números reais, ou uma outra ainda para caracteres? Você terá que

criar três bibliotecas separadas, ou, alternativamente, usar uma
union

e deixar a
union

manejar todos os tipos de dados possíveis. Em C++, um

conceito denominado modelo permite que você crie uma única biblioteca para tratar a pilha e

redefina os tipos de dados a serem armazenados na pilha quando esta for declarada.



Um outro problema que você já deve ter tido programando

em C envolve a alteração de bibliotecas. Digamos que você esteja usando a função

printf

definida na biblioteca
stdio, mas você quer modificá-la para manejar um novo tipo de dado que

você criou em seu programa. Exemplificando, você deseja modificar
printf

para que ela imprima

números complexos. Você não tem como fazer isso, a menos que você tenha o código

fonte da implementação de
printf. Mas

ainda que você tenha o código fonte de
printf,

essa pode ser uma péssima estratégia porque você pode gerar um código não portável.

Não há realmente um modo de extender facilmente uma biblioteca C uma vez que ela tenha

sido compilada. Para resolver o problema de impressão de números complexos em C, como no

nosso exemplo, você teria que criar uma nova função com a mesma finalidade que

printf. Se você tiver vários novos tipos de dados, você terá que criar

várias e diferentes novas funções de saída, à semelhança de
printf. C++ lida com todos esses problemas com uma nova técnica para

saída padrão. Uma combinação de sobrecarga de operador e classes permite integrar

novos tipos de dados ao esquema padrão de I/O do C++.



Ainda pensando sobre a função printf, reflita sobre seu projeto e pergunte-se a si mesmo: Esse é um bom

modo de se projetar um código? Dentro do código de
printf

há um comando
switch, ou uma cadeia de

if-else-if

que avalia um string de formatação da

saída. Um
%d é usado para números decimais, um

%c

é usado para caracteres,

um
%s

é usado para strings, e assim por diante. Há, no mínimo, três

problemas com essa implementação:



O programador da implementação de printf

tem que manter o comando
switch, ou cadeia de
size="2">
if-else-if, e modificá-lo para cada novo

tipo de formatação que se quiser implementar. Modificações sempre significam a

possibilidade de se introduzir novos bugs.



Não há qualquer garantia de que o programador usuário de

printf

vai combinar corretamente

o tipo do dado com string de formatação, o que significa que a função contém um risco

de falha.



Essa implementação não é extensível, a menos que você

possua o código fonte, você não pode ampliar as capacidades de
printf.



C++ resolve esses problemas completamente porque força o

programador a estruturar o código de uma nova maneira. O comando
switch

é ocultado e manejado

automaticamente pelo compilador através da sobrecarga de função. Torna-se assim

impossível combinar erradamente os parâmetros ao invocar uma função, primeiro porque

eles não são implementados como parâmetros em C++, e segundo porque o tipo da variável

controla automaticamente o mecanismo de
switch

que é implementado pelo compilador.



C++ resolve ainda vários outros problemas. Por exemplo,

resolve o problema de código comum

replicado em vários lugares
, permitindo que você

controle código comum em uma terceira dimensão. Resolve o problema eu quero alterar o tipo de dado passado para uma

função sem alterar a função
, permitindo que

você sobrecarregue o mesmo nome de função com múltiplas listas de parâmetros. Resolve

o problema eu quero fazer uma

pequena alteração no modo como isso funciona, mas eu não tenho o código fonte
, e ao mesmo tempo resolve o problema

eu quero reformular essa função inteiramente, sem alterar o

restante da biblioteca
usando o conceito de

herança.



C++ torna a criação de bibliotecas mais simples e melhora

drasticamente a tarefa de manutenção do código. E muito mais.



Você precisará mudar um pouco o seu modo de pensar em

programação para obter as vantagens de todos esses recursos poderosos, e isso significa

que você vai ter que dedicar-se um pouco mais ao projeto de seu código. Sem isso, você

perderá vários dos benefícios do C++. Como em tudo na vida, a migração para C++

significa custos e benefícios, mas nesse caso o conjunto dos benefícios supera em muito

os custos. 

Voltar ao Topo Ir em baixo
Ver perfil do usuário http://fraternidade.foruns.com.pt
[FTN]gomes08
Profissional
Profissional
avatar

Masculino
Mensagens Mensagens : 345
Pts FTN Pts FTN : 1033
Reputação Reputação : 87 Inscrição Inscrição : 10/12/2011
Pretendo ser Pretendo ser :
  • Nivel Alcançado


ClicksPoints
ClicksPoints: ClicksPoints
ClicksPoints:
150/10000  (150/10000)
Patente Especial ?oO?:

MensagemAssunto: Re: Entendendo profundamente C C++ Aula 2 [Madinbu] Top   5/2/2012, 01:14

meneiiro muito top Very Happy
Voltar ao Topo Ir em baixo
Ver perfil do usuário
 
Entendendo profundamente C C++ Aula 2 [Madinbu] Top
Ver o tópico anterior Ver o tópico seguinte Voltar ao Topo 
Página 1 de 1
 Tópicos similares
-
» Entendendo o ADF, QDR e QDM (em flash)
» Entendendo o Back Course
» Flight Simulator X é um simulador ou um jogo ?
» Aulas Particulares
» Curso de voo by Paulo Marcelo Soares

Permissão deste fórum:Você não pode responder aos tópicos neste fórum
 :: PROGRAMAÇAO-EDUCAÇAO :: [C++] [DELPHI] [VISUAL BASIC]-
Ir para: