Sistema de tipo C++ (guia de programação do C++ moderno)
O conceito de tipo é muito importante em C++.Cada variável, argumento da função, e valor de retorno de função deve ter um tipo para ser compilado.Além disso, cada expressão (incluindo valores literais) é determinada pelo compilador implicitamente um tipo antes de ser avaliado.Alguns exemplos de tipos incluem int para armazenar valores inteiros, double para armazenar os valores de ponto flutuante (também conhecido como tipos de dados escalares ), ou a classe padrão std::basic_string a biblioteca oferece para armazenar texto.Você pode criar seu próprio tipo definindo class ou struct.O tipo especifica a quantidade de memória que será atribuída para a variável (ou o resultado da expressão), os tipos de valores que podem ser armazenados nessa variável, como os valores (como padrão de bits) são interpretados, e as operações que podem ser executadas nele.Este artigo contém uma visão geral informal dos recursos chave do sistema de tipos C++.
Variável: O nome simbólico de uma quantidade de dados para que o nome pode ser usado para acessar os dados que se refere em todo o escopo de código onde está definido.Em C++, “variável” é geralmente usado para se referir a instâncias de tipos de dados escalares, enquanto as instâncias de outros tipos são chamadas geralmente “objetos”.
Objeto: Para simplificar, este artigo consistência e usa o termo “objeto” para referir-se a qualquer instância de uma classe ou estrutura, e quando é usado em geral inclui todos os tipos, mesmo variáveis escalares.
Tipo POD (dados antigos planos): Esta categoria informal dos tipos de dados em C++ referem aos tipos que são escalares (consulte a seção Tipos fundamentais) ou são Classes POD.Uma classe de VAGEM não tem nenhum membro de dados estáticos que não é também vagens, e não tem nenhum construtor definido pelo usuário, destrutor definido pelo usuário, ou operador de atribuição definido pelo usuário.Além disso, uma classe de VAGEM não tem nenhuma função virtual, nenhuma classe base, e membros não particulares ou protegidos de dados não-estático.Os tipos de VAGEM são usados para o troca de dados externos, por exemplo com um módulo escrito em C - o idioma (que tem tipos de VAGEM somente).
C++ é uma linguagem fortemente tipado e estático- é digitadotambém; cada objeto tem um tipo e nunca esse tipo muda (não seja confundido com objetos de dados estáticos).
Quando você declarar uma variável no seu código, você deve especificar explicitamente seu tipo ou, ou use a palavra-chave de auto para instruir o compilador para deduzir o tipo de inicialização.
Quando você declarar uma função em seu código, você deve especificar o tipo de cada argumento e o valor de retorno, ou void se nenhum valor é retornado pela função.A exceção é quando você está usando os modelos de função, que permitem argumentos de tipos arbitrários.
Depois que você primeiro declara uma variável, você não pode alterar o tipo em algum ponto posterior.No entanto, você pode copiar o valor de retorno do valor de variável ou uma função em outra variável de um tipo diferente.Essas operações são chamadas conversões de tipo, que às vezes são necessárias mas também são fontes potenciais de perda de dados ou de incorrecção.
Quando você declara uma variável do tipo de VAGEM, é altamente recomendamo-lo inicializá-la, que significa dar um valor inicial.Até que você inicializa uma variável, possui um valor de “lixo” que consiste no bit que aconteceu estar naquele local da memória anteriormente.Este é um aspecto importante da lembrar C++, especialmente se você é proveniente de outra linguagem que manipula a inicialização para você.Ao declarar uma variável do tipo da classe de não VAGEM, o construtor trata a inicialização.
O exemplo a seguir mostra algumas declarações de variável simples com algumas descrições para cada um.O exemplo também mostra como o compilador informações de tipo para permitir ou não permitir certas operações subsequentes na variável.
int result = 0; // Declare and initialize an integer.
double coefficient = 10.8; // Declare and initialize a floating
// point value.
auto name = "Lady G."; // Declare a variable and let compiler
// deduce the type.
auto address; // error. Compiler cannot deduce a type
// without an intializing value.
age = 12; // error. Variable declaration must
// specify a type or use auto!
result = "Kenny G."; // error. Can’t assign text to an int.
string result = "zero"; // error. Can’t redefine a variable with
// new type.
int maxValue; // Not recommended! maxValue contains
// garbage bits until it is initialized.
Diferentemente de algumas linguagens, C++ não tem nenhum tipo base universal de que todos os outros tipos são derivados.A implementação de Visual C++ de linguagem inclui muitos tipos básicos, também conhecido como o tipo interno.Isso inclui tipos numéricos, como intdouble, long, bool, mais char e wchar_t tipos de caracteres ASCII de UNICODE e, respectivamente.Os tipos mais fundamentais (exceto bool, double, wchar_t e tipos relacionados) têm todas as versões sem sinal, que alteram o intervalo de valores que a variável pode armazenar.Por exemplo, int, que armazena um inteiro de 32 bits com sinal, pode representar um valor de -2.147.483.648 a 2.147.483.647.unsigned int, que também é armazenado como de 32 bits, pode armazenar um valor de 0 a 4.294.967.295.O número total de valores possíveis em cada caso é o mesmo; somente o intervalo é diferente.
Os tipos fundamentais são reconhecidos pelo compilador, que tem regras internos que controlam operações que você pode executar neles, e como eles podem ser convertidas para outros tipos básicos.Para obter uma lista completa de tipos internos e seus limites de tamanho e os numéricos, consulte Tipos fundamentais (C++).
A ilustração a seguir mostra o tamanho relativo dos tipos internos:
A tabela a seguir lista os tipos mais frequentemente usados fundamentais:
Tipo |
Size (Tamanho) |
Comment |
---|---|---|
int |
4 bytes |
A escolha padrão para valores integrais. |
double |
8 bytes |
A escolha padrão para valores de ponto flutuante. |
bool |
1 bytes |
Representa os valores que podem ser verdadeiros e falsos. |
char |
1 bytes |
Use para caracteres ASCII em uma cadeia de caracteres mais antigos ctype -- estilo ou em objetos std::string que nunca têm que ser convertidos a UNICODE. |
wchar_t |
2 bytes |
Representa os valores “a” de caracteres que podem ser codificados no formato UNICODE de UTF-16 (no Windows, outros sistemas operacionais pode diferir).Este é o tipo de caracteres que é usado em cadeias de caracteres de tipo std::wstring. |
gráfico não assinado |
1 bytes |
C++ não tem nenhum tipo interno de byte .Use o caractere sem sinal para representar um valor de bytes. |
unsigned int |
4 bytes |
Usar como padrão a opção para sinalizadores de bit. |
long long |
8 bytes |
Representa os valores inteiro muito grande. |
O tipo de void é um tipo especial; você não pode declarar uma variável do tipo void, mas você pode declarar uma variável do tipo void * (ponteiro para void), que às vezes é necessário a alocar memória (un- tipada) " bruto ".No entanto, os ponteiros a void não são type-safe e seu uso é geralmente desanimado fortemente em C++ modernos.Em uma declaração da função, um valor de retorno de void significa que a função não retorna um valor; este é um aspecto comum e um uso de voidaceitável.Quando C - o idioma necessárias as funções que têm parâmetros zero para declarar void na lista de parâmetros, por exemplo, fou(void), esta prática é desanimada em C++ modernos e deve ser declarada fou().Para obter mais informações, consulte Conversões de tipo e a segurança de tipos (C++).
Interna ou qualquer tipo definido pelo usuário podem ser qualificados pela palavra-chave const.Além disso, as funções de membro podem ser constqualificado - e mesmo const- sobrecarregado.O valor de um tipo de const não pode ser alterado depois que é inicializado.
const double PI = 3.1415;
PI = .75 //Error. Cannot modify const variable.
O qualificador de const é amplamente usado na função e as declarações de variável e “a exatidão const” são um conceito importante em C++; essencialmente significa usar const para garantir, em tempo de compilação, os valores que não são alterados acidentalmente.Para obter mais informações, consulte Const (C++).
Um tipo de const é diferente da sua versão do não; const por exemplo, const int é um tipo diferente de int.Você pode usar o operador C++ const_cast nessas ocasiões raras quando você deve remover o const- Ness de uma variável.Para obter mais informações, consulte Conversões de tipo e a segurança de tipos (C++).
Especificamente, o idioma C++ não tem nenhum tipo interno de cadeia de caracteres “;” char e caracteres únicos de armazenamento de wchar_t – você deve declarar uma matriz desses tipos para aproximar uma cadeia de caracteres, adicionando um valor nulo de terminação (por exemplo, ASCII ‘\0’) a um elemento da matriz passada o caractere válido o último (também chamado de uma cadeia de caracteres “-- " C estilo).As cadeias de caracteres ctype -- estilo de pré-requisito muito mais código a ser gravado ou o uso de biblioteca de funções utilitárias externos de cadeia de caracteres.Mas em C++ modernos, temos os tipos padrão std::string (para charde 8 bits - digite cadeias de caracteres) ou std::wstring de biblioteca (para wchar_tde 16 bits - digite cadeias de caracteres).Esses recipientes de STL podem ser pensados como a cadeia de caracteres nativo tipos porque eles são parte das bibliotecas padrão que são incluídas em qualquer ambiente de correspondência de compilação C++.Use somente a diretiva de #include <string> para fazer esses tipos disponíveis em seu programa.(Se você estiver usando o ou o ATL MFC, a classe de CString também está disponível, mas não é parte do padrão C++.) O uso de matrizes de caracteres NULL- terminadas (o C de estilo cadeia de caracteres mencionado anteriormente) é fortemente desanimado em C++ modernos.Para obter mais informações sobre como decidir qual tipo cadeia de caracteres para usar em um programa modernos C++, e como converter entre os vários tipos, consulte a Seqüências de caracteres e texto (C++ moderno).
Quando você definir class, struct, union, ou enum, que a compilação é usada no restante do código como se fosse um tipo fundamental.Tem um tamanho conhecido na memória, e certas regras sobre como pode ser usada para se aplicam ao tempo de compilação que verifica e, em tempo de execução, durante a vida útil do seu programa.As principais diferenças entre os tipos básicos de interna e tipos definidos pelo usuário são:
O compilador não tem conhecimento interno de um tipo definido pelo usuário.“Sabe” do tipo quando encontra primeiro a definição durante o processo de compilação.
Você especifica operações que podem ser executadas no seu tipo, e como pode ser convertido em outros tipos, definindo (através sobrecarga) os operadores adequadas, para qualquer pessoa como membros da classe ou funções de membro não.Para obter mais informações, consulte Sobrecarga.
Não têm que estaticamente ser digitadas (a regra que um tipo de objeto nunca mudar).Através de mecanismos de herança e polimorfismo, uma variável declarada como um tipo de classe definido pelo usuário (conhecida como uma instância do objeto de uma classe) pode ter um tipo diferente no tempo de execução do que em tempo de compilação.Para obter mais informações, consulte Classes derivadas.
Datando das versões mais adiantadas de C - o idioma, C++ continua a deixar declarar uma variável de um tipo ponteiro usando o declarator especial * asterisco ().Um tipo ponteiro armazena o endereço do local da memória onde o valor real de dados está armazenado.Em C++ modernos, eles são chamados ponteirosnão processada, e acessados no seu código pelos operadores especiais * asterisco () ou -> (sublinhado com grande- de).Isso é chamado da remoção de referência, e quais que você usa depende se você está desreferenciando um ponteiro para um único ou um ponteiro para um membro em um objeto.Trabalhando com tipos ponteiro foi long um dos aspectos mais desafiantes e os mais confusas de C e C++ desenvolvimento de programas.Esta seção descreve alguns eventos e práticas ajudar a usar ponteiros crua se você desejar, mas em C++ modernos exige-se (ou não é recomendado) para usar ponteiros não processada para a propriedade do objeto de todo, devido a evolução de ponteiro inteligente (discutido mais no final dessa seção.)Ainda é útil e usar seguro ponteiros não processada para observar objetos, mas se você deve usar o para a propriedade do objeto, você deve fazer isso e muito cuidado com consideração cuidadosa de como os objetos possuídos por eles são criados e destruídos.
A primeira coisa que você deve conhecer está declarando uma variável de ponteiro " bruto " atribuir apenas a memória que é necessária para armazenar um endereço do local da memória que o ponteiro estará se referindo quando é desreferenciado.A alocação de memória para o valor de dados própria (também chamado armazenamento de backup) não é atribuída ainda.Ou seja declarar uma variável de ponteiro " bruto ", você está criando uma variável do endereço de memória, não uma variável real de dados.Desreferenciar uma variável de ponteiro antes de se certificar que contém um endereço válido a um armazenamento de backup causará comportamento indefinido (geralmente um erro fatal) em seu programa.O exemplo a seguir demonstra esse tipo de erro:
int* pNumber; // Declare a pointer-to-int variable.
*pNumber = 10; // error. Although this may compile, it is
// a serious error. We are dereferencing an
// uninitialized pointer variable with no
// allocated memory to point to.
O exemplo desreferencia um tipo ponteiro não ter nenhuma memória alocada para armazenar os dados reais inteiro ou endereço de memória válido atribuídos a ele.O código a seguir corrigir estes erros:
int number = 10; // Declare and initialize a local integer
// variable for data backing store.
int* pNumber = &number; // Declare and initialize a local integer
// pointer variable to a valid memory
// address to that backing store.
...
*pNumber = 41; // Dereference and store a new value in
// the memory pointed to by
// pNumber, the integer variable called
// “number”. Note “number” was changed, not
// “pNumber”.
A memória local fixa de pilha usos do código de exemplo para criar o armazenamento de backup que a pNumber aponta.Usamos um tipo fundamental para simplificar.Na prática, o armazenamento de backup é ponteiros para os tipos mais freqüência definidos pelo usuário) que são atribuídos em uma área de memória chamada a heap (ou “armazenamento livre ") usando uma expressão de palavras-chave de new (em programação ctype de estilo, a função da biblioteca mais antiga do tempo de execução de malloc() C foi usado).Uma vez que são atribuídos a variáveis”, “esses geralmente são referidos como “objetos”, especialmente se são baseados em uma definição de classe.A memória que é atribuída com new deve ser excluído por uma instrução correspondente de delete (ou, se você usou a função de malloc() para atribuir, a função free()de tempo de execução de C.)
No entanto, é fácil esquecer excluir principalmente um objeto dinâmico atribuído no código complexo, que causa um erro de recurso chamado um vazamento de memória.Por esse motivo, o uso de ponteiros crua é fortemente desanimado em C++ modernos.É quase sempre melhor encapsular um ponteiro " bruto " em ponteiro inteligente, que liberarão automaticamente a memória quando o destrutor é chamado (quando o código sai do escopo para o ponteiro inteligente); usando ponteiros inteligentes você elimina praticamente uma classe inteira de erros em seus programas C++.No exemplo, suponha MyClass é um tipo definido pelo usuário que tem um método DoSomeWork();de público
void someFunction() {
unique_ptr<MyClass> pMc(new MyClass);
pMc->DoSomeWork();
}
// No memory leak. Out-of-scope automatically calls the destructor
// for the unique_ptr, freeing the resource.
Para obter mais informações sobre os ponteiros inteligentes, consulte o Ponteiros inteligentes (guia de programação do C++ moderno).
Para obter mais informações sobre as conversões ponteiro, consulte Conversões de tipo e a segurança de tipos (C++).
Para obter mais informações sobre os ponteiros em geral, consulte Ponteiros.
Em O modo que programa para C e C++, a maioria das funções usam typedefs Windows- específicos e macros de #define (definidos em windef.h) para especificar os tipos de parâmetros e valores de retorno.Esses tipos de dados de “Windows” são basicamente apenas nomes especiais (alias) dados para tipos internos de ++.Para obter uma lista completa desses typedefs e definições pré-processamento, consulte o Windows Data Types.Alguns desses typedefs, como HRESULT e LCID, são úteis e descritivos.Outro, como o INT, não tem significado especial e são apenas alias para tipos fundamentais C++.Outros tipos de dados do Windows têm nomes que são mantidos de dias de programação do c e de processadores de 16 bits, e eles não têm qualquer propósito ou significado no hardware ou em sistemas operacionais modernos.Há também tipos de dados especiais associadas com a biblioteca em Tempo de Execução do Windows, listada como o Windows Runtime base data types.Em C++ modernos, a orientação é preferir os tipos básicos de C++ a menos que o tipo do Windows comunicar qualquer significado adicionais sobre como o valor deve ser interpretada.
Para obter mais informações sobre o sistema de tipos C++, consulte os seguintes tópicos.
Descreve tipos de valor juntamente com problemas em relação ao seu uso. |
|
Descreve problemas de conversão de tipos comuns e mostra como evitá-los. |