C++
Origem: Wikipédia, a enciclopédia livre.
| 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 C++ 2003 (2003) |
| Criado por | Bjarne Stroustrup |
| Estilo de tipagem: | Estática, fraca ou forte, insegura |
| Compiladores | C++ Builder, G++, MinGW, Microsoft Visual C++ |
| Dialetos: | ISO/IEC C++ 1998 ISO/IEC C++ 2003 |
| Influenciada por | Ada 83, ALGOL 68, C, CLU, ML, Simula |
| Influenciou | Ada 95, C#, D, Java, PHP, Action Script |
| Licença: | {{{licença}}} |
| Página oficial | {{{website}}} |
O C++ (em português lê-se "cê mais mais") é uma linguagem de programação de alto nível com facilidades para o uso em baixo nível, multiparadigma e de uso geral. 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 do padrão da linguagem está em desenvolvimento. Conhecida informalmente como C++0x[2], seu lançamento está previsto para 2009, tornando-se então o padrão C++09[3].
[editar] História
[editar] A evolução da linguagem
O C++ foi inicialmente desenvolvido por Bjarne Stroustrup dos Bell Labs, durante a década de 1980 com o objectivo implementar uma versão distribuída do kernel 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 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 no C. 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[4]. 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[5] 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[6].
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#.
[editar] Etimologia
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[7], 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.
[editar] Trabalhos futuros
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 freqüentemente 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[8], mas após discussão a decisão final foi mantê-la[9].
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 o comitê de padronização do C++ está trabalhando para estender a linguagem em uma nova especificação, conhecida informalmente por C++0x.
[editar] Características
[editar] Filosofia
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)[10] 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 é.
[editar] Biblioteca padrão
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[5] 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.
[editar] Operadores
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.
[editar] Pré-processador
O C++ é compilado em três fases: pré-processamento, compilação propriamente dita (tradução para código objeto) e ligação [11][12]. 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á substituido por 3.1415926535897932384626433. Outro uso do pré-processador é o que segue: #include <iostream> fará com que seja incluído (importado) todo o conteúdo da biblioteca iostream.
[editar] Gabaritos
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).
[editar] Objetos
O C++ introduziu alguns conceitos da orientação a objeto 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.
[editar] Encapsulamento
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.
[editar] Herança
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.
[editar] Polimorfismo
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).
Polimorfismo é um poderoso recurso da linguagem de programação orientada a objeto C++. Um simples operador pode ter uma utilização diferente em diferentes contextos, por exemplo quando se utiliza tipos de dados diferentes tais como números inteiros, ponto flutuante ou strings. strings. O exemplo mostrado acima leva a uma sobrecarga do operador + . O conceito de sobrecarga é também um ramo de polimorfismo. Quando o operador ou função opera em novo tipo de dados que está sobrecarregado este recurso do polimorfismo leva ao conceito de métodos virtuais.
No polimorfismo, uma função ou um operador que podem funcionar de várias maneiras dependem do tipo de aplicação para que funcionem de maneira correta. Para que isso ocorra, as seguintes condições devem ser aplicadas:
- Todas as diferentes classes devem ser derivadas de uma única classe base.
- A função membro deve ser declarada como virtual na classe base.
Em C++ o polimorfismo possui duas classes: estático e dinamico:
[editar] Polimorfismo estático (compile-time)
Sobrecarga de funções permite aos programas declarar várias funções com o mesmo nome (mas com argumentos diferentes). As funções são distinguidas pelo número e/ou tipos dos seus parâmetros formais. 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. Ao declarar uma função, um programador pode especificar os argumentos padrão para um ou mais parâmetros. Isso permite que os parâmetros com os padrões serem opcionalmente omitidos quando a função é chamada, caso em que os argumentos padrão serão usados. 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 para a direita, parâmetros no final da lista de parâmetros que estão sendo atribuídos aos argumentos padrão. Em muitos casos, os argumentos padrão especificados através de uma declaração única de função são preferíveis a criação de várias sobrecargas de funções com diferentes números de parâmetros.
Templates em C + + fornecem um mecanismo sofisticado para a criação de código genérico polimórfico. Em particular, por meio do 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 templates C + + são type-aware e Turing-complete, também podem ser usados para permitir que o compilador resolva condicionais recursivas e gerar programas substanciais através de metaprogramming em templates.
Entre seus usos mais comuns estão os seguintes:
- Ter funções com o mesmo nome mas que tratam de diferentes parâmetros: ex.: soma(int, int) e soma(double, double)
Obs.: Isso ignora, é claro, as facilidades dos templates.
- Versões novas da mesma função que recebem parâmetros adicionais ex.: export_data(void* buffer, int size) e export_data(void* buffer, int size, unsigned long options);
- Mesmo nome de método para setar e obter o valor de uma propriedade;
- Class::Property(int x); // setter
- int x Class::Property() const; // getter
[editar] Polimorfismo dinâmico (run-time)
Ponteiros para variáveis (e referências) a um tipo de classe base em C + + podem se referir a objetos de quaisquer classes derivadas desse tipo, além de objetos de correspondência exata do tipo de variável. Isso permite que matrizes e outros tipos de recipientes(containers) para armazenar ponteiros para objetos de diferentes tipos. Porque a atribuição de valores a variáveis geralmente ocorre em tempo de execução.
C++ também fornece um operador dynamic_cast, que permite que o programa de forma segura faça uma tentativa de conversão de um objeto em um objeto de um tipo mais específico (em oposição a conversão para um tipo mais geral, que sempre é permitido). Este recurso depende de informações sobre tipos em tempo de execução(em inglês RTTI). Objetos dos quais se sabe o tipo também podem ser convertido para outro tipo de static_cast, puramente em tempo de compilação, que é mais rápido e não requer RTTI.
[editar] Funções Virtuais
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 dynamic dispatching. 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 real-time. 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 feito "pure 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.
[editar] Tipos de Polimorfismo
C + + oferece três diferentes tipos de polimorfismo:
- Polimorfismo paramétrico (através do uso da palavra reservada template)
- Polimorfismo de sobrecarga
- Polimorfismo de Inclusão
A definição de cada um deles:
[editar] Ad-Hoc
O polimorfismo ad-hoc é um tipo de polimorfismo run-time e é implementado com herança e funções virtuais em C++. Este tipo de polimorfismo permite a existência de vários métodos de mesmo nome, porém com assinaturas levemente diferentes ou seja variando no número e tipo de argumentos e no valor de retorno. Ficaria a cargo do compilador escolher de acordo com as listas de argumentos os procedimentos ou métodos a serem executados.
[editar] Paramétrico
O polimorfismo compile-time é implementado com modelos. Se todo o código está escrito, sem menção de qualquer tipo específico e, portanto, pode ser usado de forma transparente com qualquer número de novos tipos é chamado de polimorfismo paramétrico.
[editar] Inclusão
Polimorfismo de inclusão modela herança e subtipos. Permite a um objeto pertencer a várias classes simultaneamente, criando uma hierarquia de herança. Numa subclasse, um objeto pode ter um comportamento modificado com relação à classe original. A assinatura do método tem que ser idêntica, ou seja, teremos redefinição quando uma classe filha fornece apenas uma nova implementação para o método herdado e não um novo método.
[editar] Polimorfismo Ad-Hoc (Sobrecarga)
Uma forma de C++ alcançar o polimorfismo é por meio do uso de sobrecarga de função. A sobrecarga, simplificadamente, consiste na redefinição de itens já existentes. Em outras palavras, ela permite que sejam redefinidas duas ou mais funções com o mesmo nome, desde que suas listas de argumentos sejam suficientemente diferentes para as chamadas a serem resolvidas. Nesta situação, quando diversas declarações de funções diferentes são especificadas por um único nome no mesmo escopo, diz-se que as funções que compartilham o mesmo nome estão sobrecarregadas. Quando esse nome é utilizado, a função correta é selecionada pela comparação dos tipos dos argumentos reais com os tipos dos argumentos formais. Um exemplo prático de sobrecarga de funções é ilustrado pelo programa a seguir. C e C++ não contêm funções de bibliotecas que pedem ao usuário para digitar e aguardar uma resposta. Entretanto, este programa cria três funções chamadas "prompt()" que efetuam essa tarefa para dados do tipo int, double e long:
#include <iostream>
using namespace std;
void prompt (char *str, int *i);
void prompt (char *str, double *d);
void prompt (char *str, long *l);
main() {
int i;
double d;
long l;
prompt("Digite um inteiro: ", &i);
prompt("Digite um double: ", &d);
prompt("Digite um long: ", &l);
cout << i << " " << d << " " << l;
}
void prompt (char *str, int *i) {
cout << str;
cin >> *i;
}
void prompt (char *str, double *d) {
cout << str;
cin >> *d;
}
void prompt (char *str, long *l) {
cout << str;
cin >> *l;
}
A sobrecarga de funções é importante porque pode ajudar a gerenciar a complexidade. Para compreender como, considere o seguinte exemplo. O Borland C++ contém as funções "atoi()", "atof()" e "atol()" em sua biblioteca padrão. Coletivamente, essas funções convertem uma string para diferentes tipos de números equivalentes (int, double e long). Embora estas funções realizem ações quase idênticas, em C três nomes diferentes precisam ser usados para representar essas tarefas, o que torna a situação mais complexa do que realmente é. Em outras palavras, mesmo que o conceito subjacente de cada função seja o mesmo, o programador deve lembrar de três nomes. Entretanto, em C++ é possível usar o mesmo nome para todas as três funções. Assim, o nome representa a ação geral que está sendo realizada e o compilador escolhe a versão específica para uma determinada circunstância. Portanto, aplicando-se sobrecarga, três nomes para memorizar são reduzidos a um. Esta seção apresenta a sintaxe e a semântica para a sobrecarga de operadores. Baseando-se nos conceitos definidos, a sobrecarga de operador consiste na redefinição de seu significado para tipos diferentes daqueles com os quais ele tinha sido previamente definido. Por meio da sobrecarga de operadores, o programador pode redefinir o significado da maior parte dos operadores de C++, quando pelo menos um operando é um objeto de classe. Isto é, em geral, pode-se sobrecarregar os operadores de C++ definindo o que eles significam em relação a uma classe específica. Existe duas formas de se definir sobrecarga de operadores em C++: declarando-a como função membro ou friend da classe que a utilizará. Há uma pequena diferença entre as sintaxes de declaração e definição da sobrecarga em cada forma. Inicialmente, serão observadas as sintaxes gerais e, posteriormente, serão discutidas estas diferenças. As sintaxes são as seguintes: • Sobrecarga como função membro
Declaração:
class Nome_Classe
{
...
tipo_retorno> operator op (<lista_de_parametros>);
};
Definição:
<tipo_retorno> Nome_Classe :: operator op (<lista_de_parametros>)
{
// definição da função membro
}
• Sobrecarga como função amiga
Declaração:
class Nome_Classe{
...
friend <tipo_retorno> operator op (<lista_de_parametros>);
};
Definição:
<tipo_retorno> operator op (<lista_de_parametros>)
{
// definição da função friend
}
Observando-se as declarações de sobrecarga, conclui-se que elas são muito semelhante à sintaxe de declaração de qualquer função membro. A diferença está na inclusão da palavra-chave operator e no nome da função ("op") que, na sobrecarga, é o operador sobrecarregado. A palavra reservada operator identifica uma função operadora. <tipo_retorno> consiste em algum tipo conhecido da linguagem, porém, geralmente, é a própria classe para a qual o operador está sendo redefinido. Deve-se ter cuidado com o retorno do operador e lembrar-se de como este é utilizado originalmente. Por exemplo, se o operador de atribuição "=" for sobrecarregado para uma classe String, é possível que se queira continuar fazendo atribuições encadeadas, tais como:
String str1, str2, str3("Exemplo");
str1 = str2 = str3;
Se a sobrecarga declarar o retorno como void, será impossível fazer esta atribuição encadeada
[editar] Polimorfismo Paramétrico
C + + implementa polimorfismo paramétrico através de templates ou modelos. O uso de templates requer que o compilador gere uma instância separada da classe ou função usada como template 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 templates C + + têm sobre Java e C# é que eles permitem metaprogramming template, que é uma forma de pré-avaliação de parte do código em tempo de compilação ao invés de tempo de execução. Segue abaixo um exemplo de polimorfismo paramétrico:
#include <iostream>
#include <string>
using namespace std;
class Animal
{
public:
Animal(const string& name) : name(name) {}
virtual string talk() = 0;
const string name;
};
class Cat : public Animal
{
public:
Cat(const string& name) : Animal(name) {}
string talk() { return "Meow!"; }
};
class Dog : public Animal
{
public:
Dog(const string& name) : Animal(name) {}
string talk() { return "Arf! Arf!"; }
};
// O método main irá exibir o seguinte no console:
//
// Missy: Meow!
// Mr. Bojangles: Meow!
// Lassie: Arf! Arf!
//
int main()
{
Animal* animals[] =
{
new Cat("Missy"),
new Cat("Mr. Bo jangles"),
new Dog("Lassie")
};
for(int i = 0; i < 3; i++)
{
cout << animals[i]->name << ": " << animals[i]->talk() << endl;
delete animals[i];
}
}
[editar] Polimorfismo de Inclusão
Um método é uma redefinição de um método herdado, quando está definido em uma classe construída através de herança e possui o mesmo nome, valor de retorno e argumentos de um método herdado da classe pai. A assinatura do método tem que ser idêntica, ou seja, teremos redefinição quando uma classe filha fornece apenas uma nova implementação para o método herdado e não um novo método. Se a classe filha fornecer um método de cabeçalho ou assinatura parecida com a do método herdado (difere ou no número ou no tipo dos argumentos, ou então no tipo do valor de retorno) então não se trata mais de redefinição, trata-se de uma sobrecarga, pois criou-se um novo método. Uma chamada ao método herdado não mais é interceptada por esse novo método de mesmo nome. O método tem o mesmo nome, mas é ligeiramente diferente na sua assinatura (o corpo ou bloco de código {} não importa), o que já implica que não proporciona o mesmo comportamento (behaviour) do método da superclasse. Suponha que um sistema represente um empregado de uma empresa usando seu nome, sobrenome e o departamento ao qual pertence:
class Empregado {
private:
String nome, sobrenome;
int depto;
public:
Empregado (const char *n, const char *s, int d) :
nome(n), sobrenome (s) {
depto = d;
}
};
A sintaxe:
: nome (n)
Indica que o membro nome é inicializado com o valor n. É diferente de:
depto = d;
Que indica atribuição (alteração de valor). Para inicializar vários membros, os construtores devem ser separados por vírgulas. Suponha que um gerente seja representado pelas informações acima, mais um valor que indique seu nível dentro da empresa. Uma forma de representar essa classe poderia ser:
class Gerente {
private:
String nome, sobrenome;
int depto;
int nivel;
...
};
Ou então:
class Gerente {
private:
Empregado emp;
int nivel;
...
};
Nenhuma dessas representações indica que um gerente é também um empregado. Um programa não pode utilizar um objeto da classe gerente onde um objeto empregado é esperado. A solução correta é definir explicitamente que um gerente é um empregado, com algumas informações adicionais:
class Gerente : public Empregado {
private:
int nivel;
public:
Gerente (const char *n, const char *s, int d, int l) :
Empregado (n, s, d) {
nivel = l;
}
};
A classe Empregado é a superclasse e Gerente é a subclasse. Em C++, usa-se dizer que Empregado é a classe base e Gerente é a classe derivada. A classe derivada herda as propriedades da classe base - essa relação é conhecida então como herança.
Diretivas de visibilidade para mebros de classe:
- public: visível em qualquer ponto do programa;
- private: visível por membros da classe e friends;
- protected: visível por membros da classe, friends, classes derivadas e friends das mesmas.
Diretivas de visibilidade usadas na derivação:
- public: visibilidade da classe base não é alterada;
- private: membros public e protected da classe base são private na classe derivada;
- protected: membros public e protected da classe base são protected na classe derivada.
Com a definição acima, um objeto Gerente pode ser usado onde um objeto Empregado é esperado, mas o contrário não é verdadeiro! A mesma regra é válida para apontadores e referências dessas classes.
[editar] Regra dos três
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:[13] 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 à essa regra diz respeito à técnica RAII[14]: se ela for usada então o destrutor pode ser deixado sem definição (também conhecida como "regra dos dois"[15]).
[editar] Tratamento de exceções
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[14][16]. De qualquer forma, é possível que essa funcionalidade seja adicionada na próxima especificação da linguagem.
[editar] Espaço de nomes
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.
[editar] Ponteiros e referências
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.
[editar] Incompatibilidade com C
É incorreto considerar o C++ como um super conjunto de C, isto é, uma linguagem que implementa o C completamente e que adiciona novas funcionalidades[17]. 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[18].
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:
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 //[18]. 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++.
[editar] Análise sintática do 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)[19]. Por exemplo, com o LALR é possível analisar código Java[20]. 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.[19]
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[21], de forma que se torna um método padrão e livre de análise sintática para a linguagem.
[editar] Críticas
| 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. | — 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 metaprogamaçã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 Java — Sun ou Visual Basic — Microsoft); 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, 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.
[editar] Comunidade de desenvolvimento
[editar] Pessoas notáveis
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[22]. 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.
[editar] Bibilioteca Boost
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[23]. 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[24] a abstrações do sistema operacional como o filesystem[25] a bibliotecas para usuários avançados como a MPL[26].
[editar] Ferramentas
[editar] Ambientes de desenvolvimento
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 | Sim | Não | 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 | Não | Sim | Sim | Windows[nota 6] |
| Ultimate++ | U++ é um framework C++ multi-plataforma, para desemvolvimento rápido de aplicações, focado na produtividade de progamadores. | Livre | Não | Sim | Sim | Unix, Linux, Mac OS X e Windows |
| Intel C++ | Produz código otimizado para processadores Intel | Proprietária | Sim | Não | 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[27] | Proprietária | Sim | Sim | Windows | |
| C++ Builder | Ferramenta da Borland que oferece versões antigas gratuitas sem presença de IDE. Possui integração com Delphi | Proprietária | Sim | Sim | Sim | Windows e Linux |
| Open Watcom | Suporta plataformas antigas, até então sem suporte completo à biblioteca padrão | Livre | Sim | Sim | DOS, Windows, OS/2 e Netware | |
| Comeau C++ | Pode ser experimentado pela Internet[28] | Proprietária | Sim | Não | Windows, Linux e Solaris | |
| Turbo C++ | Possui versão gratuita[29] no sítio oficial e também uma versão paga[30]. É similar ao C++ Builder. | Proprietária | Sim | Sim | Windows | |
| Eclipse | Disponível para C++ através da extensão CDT[31]. | Livre | Não | Sim | Sim | 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 | Não | Sim | Sim | 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[32]. | Livre | Não | Sim | Sim | Windows, Linux, Mac OS X |
| Digital Mars | Proprietária | Sim | Sim | Windows, DOS | ||
| Codelite | Livre | Sim | Sim | Windows, Linux, Mac OS X | ||
| Geany | Livre | Não | Sim | Não | Windows, Linux | |
| GNAT Programming Studio | Utiliza o compilador GCC | Livre | Não | Sim | Windows, Linux, Solaris | |
| KDevelop | Utiliza o compilador GCC | Livre | Não | Sim | Sim | Windows, Linux |
[editar] Aplicativos desenvolvidos em C++
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.[33]
|
Notas
- ↑ Uma discussão sobre o tema encontra-se na seção de incompatibilidades.
- ↑ Mais informações sobre o C++ ABI podem ser obtidas no sumário sobre a extensão (em inglês)
- ↑ Um exemplo é o livro de Ivor Horton:
- Ivor Horton. Beginning ANSI C++. 3.ed. APRESS, 2004. pp. 827. ISBN 1-59059-227-1
- ↑ O construtor padrão também é criado automaticamente pelo compilador caso o desenvolvedor não tenha definido nenhum outro construtor para a classe.
- ↑ Dado um tipo de dado
T, uma referência pode ser definida para nulo através deT& 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. - ↑ Uma versão para Linux começou a ser desenvolvida, mas foi abandonada em 2002
Referências
- ↑ 1,0 1,1 1,2 1,3 1,4 1,5 1,6 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.
- ↑ Bjarne Stroustrup (maio de 2005). The Design of C++0x (PDF) (em inglês). C/C++ Users Journal.
- ↑ Danny Kalev (17 de novembro de 2006). C++09: A Glimpse into the Future (em inglês). DevSource (Microsoft). Página visitada em 16 de outubro de 2007.
- ↑ Bjarne Stroustrup. Quando o C++ foi inventado? (em inglês). FAQ de Bjarne Stroustrup.
- ↑ 5,0 5,1 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.
- ↑ Descrição da norma (em inglês)
- ↑ Bjarne Stroustrup. Where did the name "C++" come from?. FAQ de Bjarne Stroustrup. Página visitada em 8 de março de 2007.
- ↑ 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.
- ↑ J16 Reunião 36/WG21, realizada entre 7 e 11 de abril de 2003 (em inglês)
- ↑ Stanley B. Lippman. Inside the C++ Object Model. Addison-Wesley Professional, 1996. pp. 304. ISBN 978-0201834543
- ↑ Processo de compilação explicado pela IBM (em inglês)
- ↑ Processo de compilação explicado pela HP (em inglês)
- ↑ Marshall P. Cline; Greg Lomow; Mike Girou. C++ FAQs. 2.ed. Addison-Wesley Professional, 1998. pp. 624. ISBN 978-0201309836
- ↑ 14,0 14,1 Bjarne Stroustrup. resource acquisition is initialization (em inglês). Glossário de Bjarne Stroustrup.
- ↑ 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.
- ↑ 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. - ↑ 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.
- ↑ 18,0 18,1 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.
- ↑ 19,0 19,1 Andy (Março de 2001). Parsing C++ (em inglês). Página visitada em 7 de fevereiro de 2008.
- ↑ 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.
- ↑ Boost.Spirit based C++ parser (library) (em inglês). Grupo Boost. Página visitada em 29 de abril de 2007.
- ↑ 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.
- ↑ 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.
- ↑ 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.
- ↑ 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.
- ↑ 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.
- ↑ Visual Studio Express (em inglês). MSDN, sítio da Microsoft Corporation. Página visitada em 25 de outubro de 2007.
- ↑ 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.
- ↑ David Intersimone. Antique Software: Turbo C++ version 1.01 (em inglês). Página visitada em 24 de outubro de 2007.
- ↑ Turbo C++ (em inglês). Borland. Página visitada em 24 de outubro de 2007.
- ↑ Eclipse C/C++ Development Tooling - CDT (em inglês). Eclipse Foundation. Página visitada em 24 de outubro de 2007.
- ↑ Code::Blocks Features (em inglês). Sítio oficial do Code::Blocks. Página visitada em 24 de outubro de 2007.
- ↑ 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."
- ↑ Descrição do Googlebot, desenvolvido em C++ (em inglês)
- Bjarne Stroustrup. The Design and Evolution of C++. Addison-Wesley, 1994. ISBN 0-201-54330-3
- Andrei Alexandrescu e Herb Sutter. C++ Design and Coding Standards: Rules and Guidelines for Writing Programs. Addison-Wesley, 2004. ISBN 0-321-11358-6
[editar] Ver também
- Biblioteca padrão do C++
- Biblioteca Boost
- Operadores em C e C++
- Standard Template Library
- Anexo:Lista de exemplos de código C++
[editar] Ligações externas
[editar] Grupos de discussão e de suporte
[editar] Material de estudo
- Página oficial do comitê C++ — JTC1/SC22/WG21 (em inglês)
- Happy Codings (em inglês) — algoritmos em C++
- Comparativo entre compiladores (em inglês)
[editar] Bibliotecas e repositórios de código
- Poco Project (em inglês) — conjunto de bibliotecas C++ revisadas por especialistas.
- csourcesearch.net (em inglês) — repositório de código livre C e C++
- CommonCPP (em inglês) — classes fundamentais portáveis da GNU
- STLSoft (em inglês) — bibliotecas livres, compostas somente de cabeçalhos, com o intuito de servir como extensão à STL
- C/C++ Reference (em inglês) — referências de C e C++