Menu

Classes em C++: defina objetos, membros e métodos

Aprenda como as classes em C++ agrupam dados e comportamento em tipos reutilizáveis: declarar variáveis-membro e métodos, criar objetos, a divisão public/private e armadilhas como membros não inicializados e o ponteiro this.

Esta página tem editores executáveis - edite, execute e veja a saída na hora.

O que é uma classe

Uma classe é uma planta para um tipo personalizado que agrupa dados (variáveis-membro) e comportamento (funções-membro) em uma única unidade. Enquanto os tipos embutidos como int e double descrevem valores individuais, uma classe permite modelar um conceito inteiro - uma conta bancária, um ponto 2D, um jogador - como um único valor que você pode passar adiante.

Você já usou classes sem definir nenhuma: std::string e std::vector são classes da biblioteca padrão. Chamar name.length() ou v.push_back(3) é chamar uma função-membro de um objeto. Agora você vai construir seus próprios tipos da mesma forma e depois seguir para os construtores para inicializá-los.

Definindo uma classe e criando objetos

A definição de uma classe lista seus membros entre chaves e termina com ponto e vírgula - esquecer esse ; final é um dos erros mais comuns de iniciantes. Cada objeto que você cria a partir da classe recebe sua própria cópia das variáveis-membro.

rex e luna são dois objetos distintos. Alterar rex.name não afeta luna.name - cada objeto guarda seus próprios dados. Você acessa um membro com o operador ponto . sobre um objeto (ou -> quando tem um ponteiro para ele).

public vs private

Por padrão, tudo em uma class é private: somente as próprias funções-membro da classe podem acessá-lo. O rótulo public: abre os membros para o código externo. Essa divisão é o coração do encapsulamento - você expõe uma interface segura e esconde os dados internos para que não possam entrar em um estado inválido.

Como count é private, nenhum chamador pode inserir um valor negativo ou sem sentido - eles precisam passar por increment(). O const após a lista de parâmetros de value() promete que a função não modificará o objeto, o que permite chamá-la em objetos const e sinaliza a intenção para quem lê o código. Veja os especificadores de acesso para a história completa sobre public, private e protected.

Declaração vs. definição de métodos

Para classes pequenas, definir os métodos inline (como acima) está ótimo. Para classes maiores, é comum declarar os métodos dentro da classe e definir seus corpos fora, usando a sintaxe de escopo ClassName::method. Isso mantém a definição da classe legível como um resumo da interface.

O prefixo Rectangle:: informa ao compilador a qual classe a função pertence. Dentro de uma definição assim você ainda se refere aos membros pelos nomes simples (width, area()) - o compilador sabe que eles pertencem ao objeto sobre o qual o método foi chamado.

O ponteiro this

Dentro de qualquer função-membro não estática, this é um ponteiro para o objeto sobre o qual a função foi invocada. Você normalmente não precisa dele, já que o nome simples de um membro já se refere ao objeto atual. Ele se torna útil quando um parâmetro encobre (shadow) um membro - eles têm o mesmo nome - e você precisa desambiguar.

Sem this->, escrever x = x; dentro de setX atribuiria o parâmetro a si mesmo e deixaria o membro intocado - um bug silencioso. this->x torna tudo inequívoco. Muitos projetos evitam o problema por completo dando nomes diferentes aos parâmetros (por exemplo, setX(int newX)), mas você verá this-> o tempo todo em código real.

Erros comuns

Algumas armadilhas das classes pegam as pessoas repetidamente:

  • Esquecer o ponto e vírgula de fechamento. A definição de uma classe termina com };. Tire o ; e você terá uma enxurrada de erros confusos apontando para o que vem depois da classe, não para a classe em si.
  • Esquecer de inicializar os membros. Membros de tipos embutidos como int e double não são zerados automaticamente. Ler um membro não inicializado é comportamento indefinido. Dê valores padrão aos membros (int count = 0;) ou inicialize-os em um construtor.
  • Acessar membros private de fora. c.count = 5; em um membro private é um erro de compilação - use um método público em vez disso. Isso é o encapsulamento funcionando como esperado.
  • Confundir a classe com um objeto. Dog.bark(); está errado - Dog é o tipo. Você chama métodos sobre objetos: rex.bark();.
// Membro não inicializado - ler 'age' é comportamento indefinido:
class Cat {
public:
    int age;            // sem valor padrão
};

Cat c;
std::cout << c.age;     // valor lixo, não 0

Próximo: Construtores

Definir cada membro à mão depois de criar um objeto - rex.name = ...; rex.age = ...; - é tedioso e fácil de esquecer, que é exatamente como você acaba com membros não inicializados. A próxima página aborda os construtores: funções especiais que rodam automaticamente quando um objeto é criado, permitindo garantir que todo objeto comece em um estado válido com uma sintaxe limpa de uma linha Dog rex("Rex", 4);.

Perguntas frequentes

Qual é a diferença entre uma classe e um objeto em C++?

Uma classe é a planta - ela descreve quais dados (variáveis-membro) e qual comportamento (funções-membro) um tipo possui. Um objeto é uma instância concreta construída a partir dessa planta. class Dog { ... }; define o tipo uma única vez; Dog rex; cria um Dog de verdade que você pode usar. Uma mesma classe pode produzir vários objetos independentes.

Qual é a diferença entre class e struct em C++?

Tecnicamente, apenas o nível de acesso padrão: os membros de uma class são private por padrão, enquanto os de uma struct são public por padrão. Ambos podem ter funções-membro, construtores e herança. Por convenção, struct é usada para agrupamentos simples de dados e class para tipos com comportamento e invariantes a proteger.

O que o ponteiro this faz em uma classe C++?

Dentro de uma função-membro, this é um ponteiro para o objeto sobre o qual a função foi chamada. Use-o para distinguir um parâmetro de um membro (this->x = x;) ou para retornar o objeto atual. Você raramente precisa dele para o acesso normal a membros - escrever x já se refere ao x do objeto atual.

Coddy programming languages illustration

Aprenda a programar com o Coddy

COMEÇAR