C++

Origem: Wikipédia, a enciclopédia livre.
Ir para: navegação, pesquisa
C++
Hello World C++.png
Programa Olá Mundo, escrito em C++
Paradigma Abstração de dados,
Orientação a objeto,
Programação genérica,
Programação procedural
Surgido em 1985
Última versão ISO/IEC 14882:2011 (setembro de 2011)
Criado por Bjarne Stroustrup
Estilo de tipagem: Estática, fraca ou forte, segura
Compiladores G++, MinGW, Microsoft Visual C++, Clang
Dialetos: ISO/IEC 14882:1998
ISO/IEC 14882:2003
ISO/IEC 14882:2011
Influenciada por Ada 83, ALGOL 68, C, CLU, ML, Simula
Influenciou Ada 95, C♯, D, Java, PHP, Squirrel

C++ (em português lê-se "cê mais mais", em inglês lê-se see plus plus) é uma linguagem de programação multi-paradigma e de uso geral. A linguagem é considerada de médio nível, pois combina características de linguagens de alto e baixo níveis. Desde os anos 1990 é uma das linguagens comerciais mais populares, sendo bastante usada também na academia por seu grande desempenho e base de utilizadores.

Bjarne Stroustrup desenvolveu o C++ (originalmente com o nome C with Classes,[1] que significa C com classes em português) em 1983 no Bell Labs como um adicional à linguagem C. Novas características foram adicionadas com o tempo, como funções virtuais, sobrecarga de operadores, herança múltipla, gabaritos e tratamento de exceções. Após a padronização ISO realizada em 1998 e a posterior revisão realizada em 2003, uma nova versão da especificação da linguagem foi lançada em setembro de 2011, conhecida informalmente como C++11 ou C++0x.[2] [3] [4]

História[editar | editar código-fonte]

A evolução da linguagem[editar | editar código-fonte]

O C++ foi inicialmente desenvolvido por Bjarne Stroustrup dos Bell Labs, durante a década de 1980 com o objetivo implementar uma versão distribuída do núcleo Unix.[1] Como o Unix era escrito em C, dever-se-ia manter a compatibilidade, ainda que adicionando novos recursos. Alguns dos desafios incluíam simular a infraestrutura da comunicação entre processos num sistema distribuído ou de memória compartilhada e escrever drivers para tal sistema. Stroustrup percebeu que a linguagem Simula 67 possuía características bastante úteis para o desenvolvimento de software, mas que era muito lenta para uso prático. Por outro lado, a linguagem BCPL era rápida, mas possuía demasiado baixo nível, dificultando sua utilização no desenvolvimento de aplicações. A partir de sua experiência de doutorado, começou a acrescentar elementos do Simula 67 no C, especialmente os recursos de criação e manipulação de objetos. O C foi escolhido como base de desenvolvimento da nova linguagem pois possuía uma proposta de uso genérico, era rápido e também portável para diversas plataformas. Algumas outras linguagens que também serviram de inspiração para o cientista da computação foram ALGOL 68, Ada, CLU e ML.

Ainda em 1983 o nome da linguagem foi alterado de C with Classes para C++. Antes implementada usando um pré-processador, a linguagem passou a exigir um compilador próprio, escrito pelo próprio Stroustrup.[1] Novas características foram adicionadas, como funções virtuais,[1] sobrecarga de operadores e funções,[1] referências, constantes, gerenciamento manual de memória, melhorias na verificação de tipo de dado e estilo de comentário de código de uma linha (//). Em 1985 foi lançada a primeira edição do livro The C++ Programming Language, contendo referências para a utilização da linguagem, já que ainda não era uma norma oficial. A primeira versão comercial foi lançada em outubro do mesmo ano.[5] Em 1989 a segunda versão foi lançada, contendo novas características como herança múltipla, classes abstratas, métodos estáticos, métodos constantes e membros protegidos, incrementando o suporte a orientação a objeto. Em 1990 foi lançado o livro The Annotated C++ Reference Manual, que tornou-se base para o futuro padrão. Outras adições na linguagem incluem gabaritos, tratamento de exceções, espaço de nomes, conversão segura de tipo de dado e o tipo booleano.

Assim como a linguagem, sua biblioteca padrão também sofreu melhorias ao longo do tempo. Sua primeira adição foi a biblioteca de E/S, e posteriormente a Standard Template Library (STL); ambas tornaram-se algumas das principais funcionalidades que distanciaram a linguagem em relação a C. Criada primordialmente na HP por Alexander Stepanov[6] no início da década de 1990 para explorar os potenciais da programação genérica, a STL foi apresentada a um comitê unificado ANSI e ISO em 1993 à convite de Andrew Koenig. Após uma proposta formal na reunião do ano seguinte, a biblioteca recebe o aval do comitê.

Depois de anos de trabalho, o mesmo comitê ANSI/ISO padronizou o C++ em 1998 (ISO/IEC 14882:1998). Após alguns anos foram reportados defeitos e imprecisões no documento, e uma correção foi lançada em 2003.[7]

Por muito tempo, o C++ foi encarado como um superconjunto do C.[nota 1] Entretanto, em 1999 o novo padrão ISO para a linguagem C tornou as duas linguagens ainda mais diferentes entre si. Devido a essas incompatibilidades, muitas empresas que desenvolvem compiladores não oferecem suporte à versão mais recente da linguagem C.

Pode-se dizer que C++ foi a única linguagem entre tantas outras que obteve sucesso como uma sucessora à linguagem C, inclusive servindo de inspiração para outras linguagens como Java, a IDL de CORBA e C♯.

Etimologia[editar | editar código-fonte]

Durante sua fase inicial de desenvolvimento, a linguagem era chamada "novo C", "C84" ou ainda "C com classes".[1] O termo "C++" é creditado a Rick Mascitti,[8] e foi utilizado pela primeira vez em dezembro de 1983. Ele é uma referência ao operador de incremento ++, significando um acréscimo (uma evolução) à linguagem C. Em tom humorado, desenvolvedores software e especialistas em informática no início da década de 1990 costumavam relacionar o ++ do nome à grande insistência dos programadores em utilizar o C++ da mesma forma que a linguagem C, não usufruindo das novas facilidades que a linguagem poderia fornecer. Assim como o ++ estava sendo aplicado de maneira pós-fixa à letra C, a linguagem C++ era uma evolução do C pós-fixada, que só tornar-se-ia realidade em algum futuro remoto, não naquele momento.

Trabalhos futuros[editar | editar código-fonte]

A linguagem continua evoluindo de forma a fornecer novas funcionalidades. O grupo de desenvolvimento Boost.org trabalha para evoluir a biblioteca padrão, informando o comitê oficial da linguagem quais facilidades possuem maior retorno positivo dos usuários, seja por qualidade ou por utilidade, e quais ainda devem ser desenvolvidas. Tudo indica que o C++ continuará com sua natureza multiparadigma. Por exemplo, o trabalho da Boost.org dedica-se a acrescentar as qualidades da programação funcional e genérica. O padrão C++ não define a implementação para a definição de nomes e tratamento de exceções, entre outras facilidades específicas, o que frequentemente torna incompatíveis códigos objeto produzidos por diferentes compiladores. Apesar disso, existem padrões periféricos específicos para certas plataformas ou sistemas operacionais para padronizar compiladores dessas plataformas, como por exemplo o C++ ABI.[nota 2]

As empresas de desenvolvimento de compiladores ainda se esforçam para suportar inteiramente o padrão, especialmente na área de gabaritos. Uma das disputas se refere à palavra reservada export, que permite que a definição de um gabarito seja separada de sua declaração. O primeiro compilador a implementar export foi o Comeau C++ em 2003 (cinco anos após o lançamento do padrão), e no ano seguinte uma versão beta do Borland C++ Builder X também suportava a facilidade. Interessante notar que ambos os compiladores são baseados na versão EDG do C++. Muitos livros fornecem exemplos de códigos para implementar export[nota 3] que não são compiláveis, mas não há referências para o problema mencionado. Outros compiladores como o Microsoft Visual C++ e o GCC não suportam a facilidade. O secretário do comitê oficial do C++ Herb Sutter recomendou que a palavra fosse removida de versões futuras do padrão da linguagem,[9] mas após discussão a decisão final foi mantê-la.[10]

Outras disputas relativas a gabaritos se referem à especialização parcial, que foi pouco suportada por muitos anos depois que o C++ padrão foi lançado.

Atualmente a linguagem tem uma nova especificação, conhecida por C++11 e publicada como 14882:2011.[11]

Características[editar | editar código-fonte]

Filosofia[editar | editar código-fonte]

No livro In The Design and Evolution of C++ (1994), Bjarne Stroustrup descreve algumas regras que ele utiliza para desenvolver a linguagem, como exemplificado abaixo:

  • C++ é desenvolvido para ser uma linguagem tipada estaticamente e de propósito geral que é tão eficiente e portátil quanto o C.
  • C++ é desenvolvido para suportar múltiplos paradigmas.
  • C++ é desenvolvido para fornecer ao programador escolhas, mesmo que seja possível ao programador escolher a opção errada.
  • C++ é desenvolvido para ser o mais compatível com C possível, fornecendo transições simples para código C.
  • C++ evita fornecer facilidades que são específicas a certas plataformas ou a certos grupos de desenvolvedores.
  • C++ não exige overhead para facilidades que não são utilizadas.
  • C++ é desenvolvido para ser utilizado mesmo sem um ambiente de desenvolvimento sofisticado.

Stanley B. Lippman documenta em seu livro Inside the C++ Object Model (1996)[12] como compiladores convertem código de programas C++ em mapeamentos de memória. Lippman trabalhou implementando e mantendo o C-front, a implementação original do C++ nos Bell Labs.

Stroustrup sempre desejou que o C++ fosse mantido como uma linguagem de especificação pequena, apesar de pressões externas para adições de novas funcionalidades na especificação da própria linguagem ao invés da codificação de novas bibliotecas para a biblioteca padrão. Brian Kernighan notou que enquanto em C existe geralmente uma maneira de resolver problemas, em C++ existem várias. Na maioria das linguagens de programação, um padrão ou um conjunto bastante restrito de padrões de projeto de software é escolhido para o desenvolvimento. Entretanto, isso não acontece em C++, pois a escolha é delegada ao desenvolvedor. É um conceito que prega que não existe paradigma de programação ou padrão de desenvolvimento que resolva todos os problemas, por isso a pluralidade e generalidade de aplicações para a linguagem. Tal filosofia assusta iniciantes e professores, que sentem que a linguagem deveria ser de fácil aprendizado, algo que o C++ não é.

Biblioteca padrão[editar | editar código-fonte]

A biblioteca padrão do C++ incorpora a biblioteca padrão do C com algumas pequenas modificações para trabalhar melhor com as novas funcionalidades criadas pela linguagem. Outra grande parte da biblioteca é composta pela biblioteca padrão de gabaritos (STL). Ela fornece ferramentas úteis como containers (vetores, listas, entre outros), algoritmos (filtragem de elementos de container, busca, ordenação, entre outros) e iteradores (ponteiros inteligentes genéricos para acessar tais containers e interligá-los aos algoritmos). Usando gabaritos é possível escrever algoritmos genéricos que funcionam para qualquer container ou sequência definida por iteradores. Tendo em vista que um iterador nada mais é que um ponteiro encapsulado, é possível também utilizar os algoritmos genéricos em vetores C, utilizando-se ponteiros comuns para tal. Como em C, os módulos da biblioteca são acessadas utilizando a diretiva #include; ao todo são fornecidos 69 cabeçalhos-padrão, dos quais 19 estão em depreciação.

Devido ao fato da biblioteca padrão ter sido desenvolvida por especialistas e de já ter sido amplamente utilizada comercialmente e academicamente, é recomendado utilizar seus componentes ao invés de componentes próprios. Por exemplo, utilizar std::vector e std::string ao invés de declarar vetores herdados do C não somente torna o desenvolvimento mais simples, como também traz mais segurança e escalabilidade para o sistema.

A biblioteca STL foi originalmente desenvolvida pela HP[6] e posteriormente pela SGI, antes de sua incorporação na biblioteca padrão do C++. O padrão não a define como "STL", mas ainda utiliza-se esse termo para distingui-la do resto da biblioteca. O projeto STLPort mantém uma implementação atualizada da biblioteca, e é baseado na SGI STL. O projeto Boost fornece elementos adicionais à STL, dos quais alguns já são considerados a serem parte da biblioteca padrão no futuro.

Operadores[editar | editar código-fonte]

Os operadores em C++ são um conjunto de todos os operadores do C mais novas adições à linguagem. Um grupo de novos operadores do C++ são os relativos à conversão de tipo de dado, e consistem em const_cast, static_cast, dynamic_cast e reinterpret_cast. Eles são uma evolução a conversão de dados utilizada em C, que limitava-se a oferecer um método para conversão tal qual static_cast. dynamic_cast refere-se diretamente ao suporte de herança e polimorfismo oferecido pela linguagem, e está relacionado a outro novo operador, typeid, que retorna informações sobre o tipo de dado derivado pelo operando. Ambos os operadores requerem a habilitação de RTTI para funcionar. Outro grupo de novos operadores são os relativos à alocação de memória, e consistem em new e delete. Assemelham-se às funções malloc e free respectivamente, que estão presentes na biblioteca padrão do C. Outro novo operador é o de resolução de âmbito, ::, e que refere-se diretamente ao suporte de espaço de nomes e orientação a objeto oferecido pela linguagem. Com ele é possível declarar e acessar espaços de nomes, e também declarar classes e acessar objetos.

O C++ define que alguns dos operadores podem ser sobrecarregados, o que permite, assim como na sobrecarga de funções, que diferentes tipos de dados sejam passados para um operador de forma a produzir diferentes resultados. Essa técnica também permite que classes definidas por utilizadores também possam usufruir de operadores próprios, tornando possível que uma classe Lista possa sobrecarregar o operador de apêndice += para que diversos elementos possam ser adicionados a lista, como elementos ou outras listas. Alguns operadores de classes definidas pelo utilizador devem ser obrigatoriamente sobrecarregados (definidos) a fim de poderem ser utilizados pela STL. Por exemplo, uma classe Funcionario deve fornecer o operador menor que (<) para ser utilizada pela função de ordenação (sort). De acordo com o padrão atual da linguagem, este requerimento é implícito durante a compilação: caso a função sort seja invocada para a um container da classe Funcionario e esta não define o operador <, há erro de compilação. Para padrões futuros planeja-se introduzir os "conceitos", que auxiliaram a programação genérica na especificação dos requerimentos de um tipo de dado para que ele seja usado em uma função. Por exemplo, os iteradores passados para sort estarão associados ao conceito "tipo de dado comparável", isto é, um tipo de dado que declara o operador <. Ao explicitar essa relação o código se torna mais consistente, e o compilador é auxiliado a fim de retornar uma mensagem de erro mais adequada ao utilizador caso haja problemas durante a compilação.

Pré-processador[editar | editar código-fonte]

O C++ é compilado em três fases: pré-processamento, compilação propriamente dita (tradução para código objeto) e ligação.[13] [14] Durante a primeira fase, as diretivas de pré-processamento são aplicadas através de transformações léxicas no próprio código fonte, que então alimenta as próximas fases de compilação. Elas são identificadas no código através do caractere #. O pré-processamento é utilizado para substituir partes de código, para inutilizar partes de código e para importar módulos externos.

Por exemplo, o código #define PI 3.1415926535897932384626433 fará com que sempre que PI aparecer no código, este será substituído por 3.1415926535897932384626433 e isso ocorre antes de começar a compilar, é como se o usuário tivesse digitado o valor de PI ao invés do texto PI. Outro uso do pré-processador é o que segue: #include <iostream> fará com que seja incluído (importado) todo o conteúdo da cabeçalho iostream da biblioteca libc.

Gabaritos[editar | editar código-fonte]

Os gabaritos são diferentes de macros de programação (que também podem ser usadas em C++, um artifício herdado do C): enquanto ambas as facilidades podem ser utilizadas para produzir código em tempo de compilação, gabaritos não restringem-se à substituições léxicas. Eles possuem conhecimento da semântica e do sistema de tipagem da linguagem, e são utilizados principalmente para polimorfismo estático (ver exemplo em anexo) e programação genérica. Um gabarito também é uma máquina de Turing completa.

No campo de programação genérica, um tipo de dado parametrizado em C++ é chamado uma classe gabarito. Ela define através de parâmetros como devem ser os tipos de dado internos utilizados ao instanciar o objeto. Dessa maneira é possível codificar uma classe genérica arranjo, que ao ser instanciada pode tornar-se um arranjo de números inteiros ou um arranjo de carros de corrida (desde que carro de corrida esteja definido no âmbito da instancialização).

Objetos[editar | editar código-fonte]

O C++ introduziu alguns conceitos de orientação a objetos ao C, como exemplificado pelas classes, que apresentam quatro características comumente presentes em linguagens de programação orientadas a objeto: abstração, encapsulamento, herança e polimorfismo. Cada vez que uma classe é instanciada é criado um objeto na memória, que é basicamente um conjunto de atributos e operações reunidos.

Encapsulamento[editar | editar código-fonte]

O encapsulamento permite que os atributos de classes possam ser declarados como públicos, privados ou protegidos. Um atributo público (o menos restrito) pode ser acessado a partir de qualquer método que tenha acesso ao objeto. Um atributo privado (o mais restrito) só pode ser acessado por métodos da própria classe e por métodos explicitamente declarados como permitidos para tal (utilizando a palavra reservada friend). Atributos protegidos só podem ser acessados por métodos da mesma classe, por métodos de classes herdadas e por métodos explicitamente declarados (utilizando a palavra reservada friend). É considerado como uma boa prática de programação restringir ao máximo o acesso aos atributos, de forma a isolar detalhes de implementação de uma classe, tornando públicas somente as funções membro que realizam uma interface mínima da classe com outros componentes.

O isolamento dos dados proposto pelo encapsulamento não é infalível, podendo ser contornado ao realizar operações de baixo nível em objetos. Dessa maneira, um atributo privado pode ser acessado e modificado a partir de um ponteiro para seu endereço de memória sem problemas, ainda que isso seja considerado uma má prática de programação. Tal característica, herdada da linguagem C, é reflexo direto da liberdade que o C++ fornece ao desenvolvedor em relação a padrões de projeto de software, cabendo a ele decidir qual é o mais adequado para seu algoritmo. O desenvolvedor tanto pode esquecer tal característica, atendo-se somente a detalhes de especificação em alto nível, quanto adequar tais características em sua especificação de forma mais baixo nível, visando desempenho ou algum outro objetivo.

Herança[editar | editar código-fonte]

A herança de uma classe para com outra pode ser declarada como pública, protegida ou privada. Isso determina o quão relacionadas as classes serão entre si. Somente a herança pública corresponde ao conceito usual de herança, pois permite acesso total aos atributos da classe-base. Entretanto, pode-se também declarar heranças protegidas e privadas, com características parecidas como as detalhadas anteriormente sobre encapsulamento. Essa funcionalidade adicionou ao C++ a possibilidade de criação de classes abstratas, que não podem ser instanciadas, mas que oferecem interfaces de funcionamento para suas respectivas classes herdadas. Ela é um princípio básico da orientação a objeto para a reutilização de código, pois permite que classes (possivelmente escritas por outros desenvolvedores e então não modificáveis) possam ser herdadas de forma a ser incrementadas em funcionalidade.

A herança múltipla é uma das características do C++ mais controversas. Ela permite que uma classe possa ser derivada de mais de uma classe base, o que pode resultar em um complicado grafo de herança e relacionamento entre classes. Por exemplo, uma classe Gato voador pode ser derivada tanto das classes Gato quanto Mamífero voador. A mistura de heranças reflete em uma mistura de espaços de nomes na classe herdada, o que pode ser resolvido através da declaração local de espaço de nomes, como explicado adiante.

Polimorfismo[editar | editar código-fonte]

Polimorfismo é a capacidade de usar um operador ou uma função de diferentes maneiras, permitir fornecer diferentes significados de acordo com o contexto. Uma vez que um aplicativo é escrito utilizando o conceito de polimorfismo, pode ser facilmente estendido, oferecendo novos objetos que estejam em conformidade com a interface original. Não é necessário recompilar programas originais, adicionando novos tipos. Apenas a re-vinculação é necessária para expor as novas mudanças juntamente com a antiga aplicação. Ele auxilia na reutilização de código e contribui para a criação de aplicações robustas. C++ suporta diversos tipos de polimorfismos, sejam estáticos (resolvidos em tempo de compilação de código) ou dinâmicos (resolvidos em tempo de execução de código).

Estático[editar | editar código-fonte]

A sobrecarga de funções é um polimorfismo estático que permite que um programa possa declarar várias funções com o mesmo nome, diferenciando entre si pela quantidade de parâmetros apresentados e por seus respectivos tipos de dado. Assim, o mesmo nome de função pode referir-se a diferentes funções dependendo do contexto em que ela é usada. O tipo retornado pela função não é utilizado para distinguir funções sobrecarregadas. A sobrecarga de operadores também é um polimorfismo estático que permite que a definição de certos operadores resultem em uma chamada de função que depende dos tipos de dado dos operadores sendo utilizados.

O C++ também suporta argumentos padrão para os parametros das funções, o que permite omitir tal parâmetro na invocação da função. Quando uma função é chamada com menos argumentos que o esperado e os argumentos explícitos são compatíveis com os parâmetros da esquerda à direita, os últimos parâmetros são atribuídos de acordo com o argumento padrão. Semanticamente parecida com a sobrecarga de funções, essa técnica permite simplificar situações em que uma função é declarada somente para invocar uma sobrecarga dela própria com algum parâmetro especificado.

O C++ implementa polimorfismo paramétrico através de gabaritos, que fazem o compilador gere uma instância separada da classe ou função usada como gabarito para cada permutação de parâmetros de tipo usado com ele, o que pode levar a dificultar a depuração de código. Um benefício que os gabaritos C++ têm sobre Java e C♯ é permitir a metaprogramação por gabaritos, uma forma de pré-avaliação de parte do código em tempo de compilação ao invés de tempo de execução.

Os gabaritos em C++ fornecem um mecanismo sofisticado para a criação de código genérico polimórfico. Em particular, por meio da técnica Curiously Recurring Template Pattern é possível implementar uma forma de polimorfismo estático que imita a sintaxe para substituir as funções virtuais. Uma vez que gabaritos são sensíveis aos tipos de dados e também são Turing completos, também podem ser usados para permitir que o compilador resolva condicionais recursivas e gerar programas substanciais através de metaprogramação por gabaritos.

Entre os usos de polimorfismo estático, inclui-se funções com o mesmo nome mas que tratam de diferentes parâmetros, como soma(int, int) e soma(double, double) (o que, entretanto, ignora as facilidades dos gabaritos.) Também, versões novas da mesma função que recebem parâmetros adicionais, como ExportarDados(void* buffer, int tamanho) e ExportarDados(void* buffer, int tamanho, unsigned long opcoes). Mais um uso é um mesmo nome de método para atribuir ou obter o valor de uma propriedade, como Classe::Propriedade(int x) e int x Class::Property() const.

Dinâmico[editar | editar código-fonte]

O polimorfismo por herança é um exemplo de polimorfismo dinâmico no qual ponteiros de uma classe base podem referenciar objetos de classes derivadas, o que permite que uma chamada de função virtual seja resolvida em tempo de execução de código. Ponteiros e referências de uma classe base podem referenciar objetos de qualquer classe derivada de si, o que permite que arranjos e outros containers de um dado tipo possam armazenar ponteiros de diversos tipos de dados, o que não poderia ser feito de outra maneira em C++. Como não é possível descobrir se a conversão do tipo base para o tipo derivado é segura em tempo de compilação, a verificação deve ser feita durante a execução do código. Para isso é fornecido o operador dynamic_cast, que permite tentar a conversão segura de uma classe mais abstrata (classe base) para outra mais específica (classe derivada). Para sua utilização a linguagem dispõe do RTTI, uma técnica para manter em memória informações sobre o tipo de dado de objetos. Caso a conversão não seja possível uma exceção específica é lançada.

Normalmente, quando uma função em uma classe derivada substitui uma função em uma classe base, a função chamada é determinada pelo tipo do objeto. Uma dada função é sobrescrita quando não existe nenhuma diferença no número ou tipo de parâmetros, entre duas ou mais definições para aquela função. Assim, em tempo de compilação pode não ser possível determinar o tipo do objeto e, portanto, a função a ser chamada, tendo apenas um ponteiro de classe base, a decisão é adiada até o tempo de execução. Isso é chamado de despache dinâmico. Funções ou métodos virtuais permitem a implementação mais específica da função a ser chamada, de acordo com o tipo do objeto em tempo real. Em C++, isto é geralmente feito usando tabelas de funções virtuais. Se o tipo de objeto é conhecido, isso pode ser contornado, antecipando o nome da classe antes da chamada de função, mas, em geral chamadas de funções virtuais são resolvidas em tempo de execução.

Além das funções de membro padrão, sobrecargas do operador e destrutores podem ser virtuais. A regra geral é que, se todas as funções da classe são virtuais, o destrutor também deve ser assim. Como o tipo de criação de um objeto é conhecido em tempo de compilação, construtores de cópia e de extensão, não pode ser virtuais. No entanto pode acontecer de uma cópia de um objeto ser criado quando um ponteiro para um objeto derivado é passado como um ponteiro para um objeto base. Nesse caso, uma solução comum é criar um clone() (ou similar) e declarar que a função como virtual. O método clone() cria e retorna uma cópia da classe quando chamado.

Um membro da função também pode ser declarado puramente virtual, acrescentando = 0 após o parêntese de fechamento e antes do ponto e vírgula. Os objetos não podem ser criados de uma classe com uma função virtual pura e são chamados de tipos de dados abstratos. Esses tipos de dados abstratos só podem ser derivados. Qualquer classe derivada herda a função virtual pura deve apresentar uma definição não-pura (e todas as outras funções virtuais puras), antes de objetos da classe derivada poderem ser criados.

Regra dos três[editar | editar código-fonte]

Uma regra informal no desenvolvimento orientado a objeto em C++ clama que se uma classe ou estrutura possui um dos seguintes itens, ela provavelmente deveria ter todos os três:[15] destrutor, construtor de cópia e operador de atribuição (=).

Esse três métodos são funções membros especiais criadas pelo compilador automaticamente se não são definidas pelo desenvolvedor.[nota 4] Se um desses métodos é definido explicitamente pelo desenvolvedor, isso significa que a versão gerada pelo compilador não serve para um dos casos, e portanto muito provavelmente também não serve para os outros casos.

Um adendo a essa regra diz respeito à técnica RAII:[16] se ela for usada então o destrutor pode ser deixado sem definição (também conhecida como "regra dos dois"[17] ).

Tratamento de exceções[editar | editar código-fonte]

O tratamento de exceção é um mecanismo desenvolvido para lidar com a ocorrência de algumas condições (chamadas exceções) que alteram o funcionamento normal do fluxo de um programa de computador. O C++ suporta tal tratamento, de forma que o estado atual de um programa após uma exceção é alterado automaticamente para outro estado pré-definido para a recuperação do sistema.

Para isso foram adicionadas à linguagem as palavras reservadas try e catch. A primeira especifica um bloco de código que será vigiado em relação à exceções, de forma que se uma for identificada, o fluxo de programa será desviado para um bloco especificado pela segunda palavra reservada. Para um dado bloco try podem existir diversos blocos catch, capturando exceções de diferentes tipos de dado. Alternativamente, a sintaxe catch(…) foi introduzida para especificar um bloco de tratamento de exceção independente do tipo da exceção, genérico.

O conceito puro da ciência da computação para tratamento de exceções ainda inclui o bloco de instruções finally, que indica um bloco de código executado após um bloco try caso nenhuma exceção tenha sido lançada, indicando sucesso na operação. Tal abordagem não foi adicionada ao C++, sendo substituível por outras técnicas como RAII[16] [18] . De qualquer forma, é possível que essa funcionalidade seja adicionada na próxima especificação da linguagem.

Espaço de nomes[editar | editar código-fonte]

O C++ introduziu os espaços de nomes para a organização das bibliotecas, e sua função é agrupar um contexto para identificadores (variáveis, funções, classes, estruturas, entre outros). No contexto de sistemas operativos, o espaço de nomes poderia ser representado por diretórios. Toda a biblioteca padrão está contida no espaço de nomes std (abreviação de standard, que em inglês significa padrão). Para utilizar um espaço de nomes pode ser feita tanto uma declaração global dos espaços quanto local. Uma declaração global é normalmente inserida no início dos módulos, após a importação dos módulos externos, utilizando a palavra reservada using (como em using namespace std;, ver exemplo contextualizado em anexo). Ela também pode ser usada em um âmbito pré-determinado por um bloco de código. Uma declaração local é inserida antes de invocar o identificador envolvido, utilizando o operador de resolução de âmbito :: (como em std::cout, ver exemplo contextualizado em anexo). A declaração global é útil para reduzir a quantidade de código produzido, sub entendendo a origem dos identificadores utilizados em todo um âmbito. Apesar disso, ela deixa margem à ambiguidades, pois é possível que um mesmo identificador esteja presente em mais de um espaço de nome importado no módulo. Para eliminar esse problema deve-se, além de utilizar a declaração global, declarar o identificador ambíguo localmente cada vez que ele for utilizado.

Em determinadas ocasiões, espaços de nome não considerados durante a primeira verificação do espaço de nomes de uma função podem também ser utilizados na busca, dependendo dos tipos de dados utilizados nos argumentos. A técnica, chamada busca de nomes dependente de argumento ou Koening lookup, ocorre quando a busca explícita pela função não encontra correspondente, começando então a procurar por espaços de nomes associados. Um padrão muito utilizado pela Standard Template Library é declarar sobrecarga de operadores que somente são encontrados pelo compilador através dessa técnica.

Ponteiros e referências[editar | editar código-fonte]

O C++ herdou a funcionalidade de ponteiros do C e toda a aritmética de ponteiros disponível para aquela linguagem: tratando um ponteiro como um tipo inteiro é possível mover-se facilmente por regiões de memória. A instância de um ponteiro em C++ é uma variável que armazena um endereço de memória, e que pode ser nula. A biblioteca padrão ainda fornece auto_ptr, uma espécie de ponteiro inteligente para contagem de referências que pode ser utilizado em algumas situações como uma alternativa segura aos ponteiros primitivos do C, automatizando o processo de desalocação de memória do objeto apontado pelo ponteiro.

Por questões de segurança, o C++ introduziu também o tipo de dado referência, um tipo mais restrito de ponteiro. Uma referência definida para outro objeto não pode ser mais referenciada, qualquer ocorrência do nome no código diz respeito ao objeto referenciado. Como consequência, não é possível realizar "aritmética de referências". Outra consequência é que não é possível alterar uma referência para que ela defina outro objeto; após definida, essa relação vale para todo o tempo de vida. Em contrapartida, um mesmo ponteiro frequentemente aponta para diferentes áreas de memória.

Apesar de teoricamente possível[nota 5] , a existência de referências nulas não é considerada, podendo-se assumir que uma referência sempre indica um objeto válido em memória.

Incompatibilidade com C[editar | editar código-fonte]

É incorreto considerar o C++ como um super conjunto de C, isto é, uma linguagem que implementa o C completamente e que adiciona novas funcionalidades.[19] Grande parte de código C pode ser perfeitamente compilado em C++, mas existem algumas pequenas diferenças sintáticas e semânticas entre as linguagens que tornam alguns trechos de código C válidos em código C++ inválido, ou códigos que exibem comportamentos diferentes em cada linguagem.[20]

Talvez a diferença mais comum é que C permite a conversão implícita entre o tipo de dado void* para ponteiros para outros tipos, algo que o C++ não permite. Logo, o seguinte código em C é válido:

int *i = malloc(sizeof(int) * 5);         /* conversão implícita de void* para int* */

Para assegurar-se que o código funcione tanto em C quanto C++ é necessário explicitar a conversão, acrescentando o que é chamado de "cast":

int *i = (int *) malloc(sizeof(int) * 5); /* conversão explícita de void* para int* */

Outra questão de portabilidade entre as linguagens é o fato do C++ adicionar várias novas palavras reservadas, como new e class, que podem ser utilizadas como identificadores (por exemplo nomes de variáveis) em C, gerando incompatibilidade.

Algumas outras incompatibilidades foram removidas no padrão C99, que agora suporta facilidades como comentários por //.[20] Tanto C99 quanto C++ definem o tipo de dado bool e suas respectivas constantes true e false. Apesar disso, enquanto a definição no C++ é embarcada na própria linguagem, tornando tais elementos palavras reservadas, em C tais identificadores são declarados através da biblioteca padrão stdbool.h.

Algumas construções sintáticas são válidas tanto em C quanto C++, mas produzem resultado diferente. Por exemplo, o valor literal 'a' possui tipo de dado int em C e char em C++, o que significa que uma chamada sizeof('a'), que retorna a quantidade de bytes ocupada pelo identificador, pode resultar em resultados diferentes entre as duas linguagens. Na prática, esse exemplo específico não é realmente um problema já que caracteres literais são convertidos para o tipo int implicitamente pelo compilador tanto em C quanto em C++.

Análise sintática do código fonte[editar | editar código-fonte]

Como a gramática C++ é bastante complexa, é difícil construir um bom analisador sintático para código fonte C++ utilizando algoritmos clássicos como o LALR(1).[21] Por exemplo, com o LALR é possível analisar código Java.[22] A flexibilidade da linguagem também é fruto de ambiguidades que um analisador simples não consegue distinguir. Por esse motivo, existem poucas ferramentas para análise e transformação não trivial de código, como refatoração. Em suas primeiras especificações o C++ era uma gramática LALR, entretanto, com a adição de funcionalidades como espaço de nomes, exceções, gabaritos e o tipo bool, essa característica logo se tornou inválida.[21]

A análise sintática não é a tarefa mais difícil na construção de uma ferramenta C++. Outras tarefas incluem entender o significado dos identificadores do programa que um compilador deve possuir. Sistemas práticos de processamento não devem somente analisar o código fonte, mas também compreender exatamente cada identificador em diferentes usos, lidando com as regras de âmbito de identificadores (ver um código contextualizado em anexo).

O grupo Boost possui um projeto para a construção de um analisador sintático C++ com base na biblioteca Spirit,[23] de forma que se torna um método padrão e livre de análise sintática para a linguagem.

Exemplos de código[editar | editar código-fonte]

Exemplo de um programa que imprime na tela "Olá, Mundo!".

#include <iostream>
 
int main()
{
    std::cout << "Olá, Mundo!" << std::endl;
    return 0;
}

Críticas[editar | editar código-fonte]

Wikiquote
O Wikiquote possui citações de ou sobre: Bjarne Stroustrup
Cquote1.svg C faz com que dar um tiro no pé seja fácil; C++ torna isso mais difícil, mas quando nós o fazemos arrebentamos com a perna toda. Cquote2.svg
Bjarne Stroustrup

A citação de Stroutrup trata com humor o fato de o C++, ao possibilitar a programação de alto nível, ter facilitado a codificação de algoritmos e organização de projetos em relação ao C, uma linguagem que requer constante atenção contra erros lógicos de programação devido à sua alta flexibidade. Por outro lado, o C++ possui nuances da sintaxe e semântica da linguagem muito sutis, difíceis de serem identificados, e que quando não percebidos podem levar a comportamentos indesejados no código.

Pontos positivos do C++ incluem a produção de código o quanto mais eficiente possível, fazendo uso de otimizações agressivas e sofisticadas dos compiladores. Entretanto, a linguagem ainda mantem alta flexibilidade, portabilidade e consistência. Um exemplo da flexibilidade é a possibilidade de programação de alto e baixo nível. Outro exemplo é a possibilidade de metaprogramação e programação genérica. Mais um ponto positivo é ampla disponibilidade e suporte, devido principalmente à grande base de desenvolvedores. Além disso, a compatilidade com C, resultando em vasta base de código. Fora do lado técnico, um positivo é que a linguagem não está sob o domínio duma empresa (em contraste do JavaSun Microsystems (atualmente pertencente a Oracle Corporation) ou Visual BasicMicrosoft); a padronização é responsabilidade da ISO.

Por outro lado, pontos negativos do C++ incluem grande período para o aprendizado devido à complexidade da linguagem. Também, os compiladores atuais, que nem sempre produzem o código mais otimizado, tanto em velocidade quanto tamanho do código, e que geralmente produzem mensagens de erro difíceis de serem interpretadas em problemas relacionados com gabaritos. Ainda relacionado a aprendizado e uso, a biblioteca padrão não cobre áreas importantes da programação, como threads (suportada por C++11), conexões TCP/IP, interface gráfica e manipulação de sistemas de arquivos, o que implica na necessidade de criação de bibliotecas próprias para tal, que pecam em portabilidade e padronização. Apesar da ampla base de código legada do C, o C++ também herdou daquela linguagem problemas de entendimento de sintaxe do mesmo. Mais um ponto negativo é que devido à grande flexibilidade no desenvolvimento, é recomendado o uso de padrões de programação mais amplamente que em outras linguagens.

Comunidade de desenvolvimento[editar | editar código-fonte]

Pessoas notáveis[editar | editar código-fonte]

O desenvolvimento da linguagem C++ é fruto do trabalho de milhares de pessoas associadas à academia e à indústria de software, e pode consistir na utilização da linguagem, em seu ensino, na construção de bibliotecas de rotinas ou na participação no comitê de padronização, entre outras atividades. Algumas pessoas tiveram participação fundamental durante a história para o desenvolvimento.[24] Primeiramente, o próprio Bjarne Stroustrup, criador da linguagem e de seu primeiro compilador.[1] O cientista ainda participa na padronização e divulga o C++ no meio acadêmico. Andrew Koenig é outro pesquisador notável, bastante atuante na padronização e creditado pela técnica Koenig lookup (demonstrada em anexo). Já Scott Meyers é um doutor em ciência da computação, e escritor de diversos livros sobre o desenvolvimento de software utilizando a linguagem. Assim como Meyers, Herb Sutter é escritor de diversos livros sobre C++ e centenas de colunas e artigos, e um notável pesquisador sobre programação concorrente e multitarefa. Andrei Alexandrescu é considerado um dos maiores especialistas em programação C++ avançada. Na área de programação genérica destaca-se o programador russo Alexander Stepanov, a figura chave na criação da Standard Template Library.

Bibilioteca Boost[editar | editar código-fonte]

Parte da comunidade de desenvolvimento do C++ foi responsável pela criação da Boost, um conjunto de bibliotecas que estendem a funcionalidade da linguagem, mais especificamente, da bibilioteca padrão. O processo de disponibilização de bibliotecas da Boost é mais rápido do que o do comitê de padronização da linguagem, e o projeto acaba servindo como uma forma de teste em campo das bibliotecas, que eventualmente podem ser migradas para a especificação da linguagem. Para o TR1 do C++0x, pelo menos dez bibliotecas já foram aceitas.[25] A base de usuários da Boost é grande, o que reflete no controle de qualidade. Funcionalidades oferecidas vão desde bibliotecas gerais como smart_ptr[26] a abstrações do sistema operacional como o filesystem[27] a bibliotecas para usuários avançados como a MPL.[28]

Ferramentas[editar | editar código-fonte]

Ambientes de desenvolvimento[editar | editar código-fonte]

Abaixo é mostrada uma lista dos principais ambientes de desenvolvimento C++, sejam eles compiladores ou ambientes de desenvolvimento integrado (IDE).

Nome Comentário Tipo de licença É compilador? É IDE? É depurador? Plataformas
G++ Um componente do GCC, compilador padrão do Projecto GNU Livre Unix, Linux, Mac OS X, Windows e AmigaOS
Dev-C++ IDE livre famosa entre iniciantes. Seu compilador é o MinGW, uma versão do G++ para Windows. Livre Windows[nota 6]
Ultimate++ U++ é um framework C++ multi-plataforma, para desenvolvimento rápido de aplicações, focado na produtividade de programadores. Livre Unix, Linux, Mac OS X e Windows
Intel C++ Produz código otimizado para processadores Intel Proprietária Windows e Linux
Microsoft Visual C++ É o mais conhecido para a plataforma Windows, com ferramentas e tecnologias auxiliares para desenvolvimento nessa plataforma (como MFC, ATL, COM, entre outras). Oferece ainda uma versão gratuita com restrições de uso[29] Proprietária Windows
C++ Builder Ferramenta da Embarcadero (anteriormente da Borland), que compartilha a mesma IDE do Delphi chamada de RAD Studio, sendo possível a utilização dos mesmos componentes visuais do Delphi (VCL) em um código C++. Proprietária Windows
Qt Creator IDE especializada em (mas não restrita a) desenvolvimento na plataforma Qt. Utiliza o g++ como compilador e o gdb como depurador (ou seus equivalentes para MinGW em Windows). Livre/Proprietária Linux, Windows e Mac OS X
Open Watcom Suporta plataformas antigas, até então sem suporte completo à biblioteca padrão Livre DOS, Windows, OS/2 e Netware
Comeau C++ Pode ser experimentado pela Internet[30] Proprietária Windows, Linux e Solaris
Turbo C++ Possui versão gratuita[31] no sítio oficial e também uma versão paga.[32] É similar ao C++ Builder. Proprietária Windows
Eclipse Disponível para C++ através da extensão CDT.[33] Livre Windows, Linux, JVM
Anjuta Suporta muitas capacidades avançadas como gerenciamento de projetos e um poderoso editor de código fonte. Uma nova versão do Anjuta (Anjuta 2.*) que integra o Glade está em desenvolvimento ativo. Livre Linux
Code::Blocks Ambiente aberto e multi-plataforma, em sua versão para Windows utiliza o compilador MinGW, apesar de também suportar outros compiladores como o Visual C++, Digital Mars, Borland C++ 5.5 e Open Watcom.[34] Livre Windows, Linux, Mac OS X
Digital Mars Proprietária Windows, DOS
Codelite Livre Windows, Linux, Mac OS X
Geany Livre Windows, Linux
GNAT Programming Studio Utiliza o compilador GCC Livre Windows, Linux, Solaris
KDevelop Utiliza o compilador GCC Livre Windows, Linux

Aplicativos desenvolvidos em C++[editar | editar código-fonte]

Abaixo segue uma lista de exemplos de aplicativos parcial ou totalmente escritos em C++, de acordo com Bjarne Stroustrup, que não garante sua precisão e veracidade, ainda que seja responsável por sua publicação.[35]

Ver também[editar | editar código-fonte]

Wikilivros
O Wikilivros tem um livro chamado Programar em C++
Wikilivros
O Wikilivros tem um livro chamado Referência rápida de C++
Wikcionário
O Wikcionário possui o verbete C++.

Notas

  1. Uma discussão sobre o tema encontra-se na seção de incompatibilidades.
  2. Mais informações sobre o C++ ABI podem ser obtidas no sumário sobre a extensão (em inglês)
  3. Um exemplo é o livro de Ivor Horton:
    Ivor Horton. Beginning ANSI C++. 3 ed. [S.l.]: APRESS, 2004. 827 p. ISBN 1-59059-227-1
  4. O construtor padrão também é criado automaticamente pelo compilador caso o desenvolvedor não tenha definido nenhum outro construtor para a classe.
  5. Dado um tipo de dado T, uma referência pode ser definida para nulo através de T& var = *(T*)0;. Notar entretanto que obter o conteúdo de nulo resulta em comportamento indefinido, o que indica má prática de programação.
  6. Uma versão para Linux começou a ser desenvolvida, mas foi abandonada em 2002

Referências

  1. a b c d e f g Naomi Hamilton (25 de junho de 2008). The A-Z of Programming Languages: C++ (em inglês). Entrevista com Bjarne Stroustrup. Computerworld. Página visitada em 25 de junho de 2008.
  2. Bjarne Stroustrup (maio de 2005). The Design of C++0x (PDF) (em inglês). C/C++ Users Journal.
  3. Doc No. 2697: ISO/IEC DTR 19768 (June 15, 2008) Minutes of WG21 Meeting June 8-15, 2008 (em inglês). Página visitada em 26 de agosto de 2010.
  4. We have an international standard: C++0x is unanimously approved (em inglês). Página visitada em 25 de novembro de 2011.
  5. Bjarne Stroustrup. Quando o C++ foi inventado? (em inglês). FAQ de Bjarne Stroustrup.
  6. a b Alexander Stepanov e Meng Lee (7 de março de 1994). The Standard Template Library (em inglês). Hewlett-Packard, Technical Report X3J16/94-0095, WG21/N0482.
  7. Descrição da norma (em inglês)
  8. Bjarne Stroustrup. Where did the name "C++" come from?. FAQ de Bjarne Stroustrup. Página visitada em 8 de março de 2007.
  9. Herb Sutter, Tom Plum (3 de março de 2003). Why We Can’t Afford Export (em inglês). Sítio oficial do comitê de padronização do C++. Página visitada em 10 de setembro de 2007.
  10. J16 Reunião 36/WG21, realizada entre 7 e 11 de abril de 2003 (em inglês)
  11. ISO/IEC 14882:2011 (em inglês). sítio ISO (2 de setembro de 2011). Página visitada em 25 de novembro de 2011.
  12. Stanley B. Lippman. Inside the C++ Object Model. [S.l.]: Addison-Wesley Professional, 1996. 304 p. ISBN 978-0201834543
  13. Processo de compilação explicado pela IBM (em inglês)
  14. Processo de compilação explicado pela HP (em inglês)
  15. Marshall P. Cline; Greg Lomow; Mike Girou. C++ FAQs. 2 ed. [S.l.]: Addison-Wesley Professional, 1998. 624 p. ISBN 978-0201309836
  16. a b Bjarne Stroustrup. resource acquisition is initialization (em inglês). Glossário de Bjarne Stroustrup.
  17. Bjorn Karlsson e Matthew Wilson (1 de outubro de 2004). The Law of The Big Two (em inglês). C++ Source. Página visitada em 21 de abril de 2007.
  18. Herb Sutter realiza uma comparação entre as técnicas RAII e Dispose (que depende do conceito de finally) em seu blog pessoal:
    Herb Sutter (31 de agosto de 2004). C++ RAII compared with Java Dispose pattern (em inglês). Página pessoal do autor. Página visitada em 29 de setembro.
  19. Bjarne Stroustrup. Is C a subset of C++? (em inglês). FAQ no sítio pessoal do autor. Página visitada em 7 de fevereiro de 2008.
  20. a b David R. Tribble (5 de agosto de 2001). Incompatibilities Between ISO C and ISO C++ (em inglês). Sítio pessoal do autor. Página visitada em 28 de setembro de 2007.
  21. a b Andy (Março de 2001). Parsing C++ (em inglês). Página visitada em 7 de fevereiro de 2008.
  22. The Java Language Specification LALR(1) Grammar (em inglês). The Java Language Specification. Sun Microsystems (3 de abril de 1998). Página visitada em 7 de fevereiro de 2008.
  23. Boost.Spirit based C++ parser (library) (em inglês). Grupo Boost. Página visitada em 29 de abril de 2007.
  24. Scott Meyers (30 de agosto de 2006). The Most Important C++ People…Ever (em inglês). Artima Developer. Página visitada em 30 de setembro de 2007.
  25. Library Technical Report (em inglês). Comitê de padronização do C++ (2 de julho de 2003). Página visitada em 18 de outubro de 2008.
  26. Boost: Smart Pointers (em inglês). Sítio oficial da Boost (25 de setembro de 2005). Página visitada em 17 de fevereiro de 2008.
  27. Boost: Boost Filesystem Library (em inglês). Sítio oficial da Boost (3 de junho de 2007). Página visitada em 17 de fevereiro de 2008.
  28. THE BOOST MPL LIBRARY (em inglês). Sítio oficial da Boost (15 de novembro de 2004). Página visitada em 17 de fevereiro de 2008.
  29. Visual Studio Express (em inglês). MSDN, sítio da Microsoft Corporation. Página visitada em 25 de outubro de 2007.
  30. Test Drive Comeau C++ Online (em inglês). Comeau Computing (31 de março de 2007). Página visitada em 7 de fevereiro de 2008.
  31. David Intersimone. Antique Software: Turbo C++ version 1.01 (em inglês). Página visitada em 24 de outubro de 2007.
  32. Turbo C++ (em inglês). Borland. Página visitada em 24 de outubro de 2007.
  33. Eclipse C/C++ Development Tooling - CDT (em inglês). Eclipse Foundation. Página visitada em 24 de outubro de 2007.
  34. Code::Blocks Features (em inglês). Sítio oficial do Code::Blocks. Página visitada em 24 de outubro de 2007.
  35. Bjarne Stroustrup. C++ Applications (em inglês). Sítio pessoal de Stroustrup. "I (Bjarne Stroustrup) don't make any guarantees about the accuracy of the list. I believe that it's accurate -- I trust the people who sent me examples, but I have not seen the source code myself."
  36. Descrição do Googlebot, desenvolvido em C++ (em inglês)

Bibliografia[editar | editar código-fonte]

  • Bjarne Stroustrup. The Design and Evolution of C++. [S.l.]: Addison-Wesley, 1994. ISBN 0-201-54330-3
  • Andrei Alexandrescu e Herb Sutter. C++ Design and Coding Standards: Rules and Guidelines for Writing Programs. [S.l.]: Addison-Wesley, 2004. ISBN 0-321-11358-6


Livro: Programação em C++ Builder 3, Autor: Roberto Falanga Júnior, Visual Books, Editora Catarinense de Informática, ISBN 85-85943-51-3

Ligações externas[editar | editar código-fonte]

Material de estudo
Bibliotecas e repositórios de código