Como criar uma classe em C++? Exemplo explicado em detalhes

Como criar uma classe em C++?
Stormtrooper representando um objeto da classe Player do exemplo a seguir sobre classe em C++.

Uma classe em C++ nada mais é do que um tipo de dado, assim como os inteiros, doubles etc., mas ela representa um tipo de dado personalizado, um tipo que é definido pelo usuário. Para se criar uma classe em C++, o procedimento é muito simples, como veremos a seguir com a classe Player.

Sintaxe das classes em C++

Os elementos principais dos quais se precisa para se criar uma classe em C++ são a palavra-chave class, o nome da classe, e as palavras-chave public, protected e private. Uma classe em C++ se define com a seguinte sintaxe: class NomeDaClase { ... }; (não esqueça o ponto-e-vírgula após fechar as chaves). Veja a seguir um exemplo de classe que poderia ser usada em um jogo simples para representar os seus personagens, a classe Player.

/*************************************************
 * Como criar uma classe em C++?
 * Exemplo 1 - Classe Player
 * ***********************************************/
 
#include <iostream>
#include <string>

// a palavra-chave final proíbe que outras classes
// herdem da classe Player.
class Player final {
    public:
        Player(unsigned int iHealth, const std::string& iName, const std::string& iClass): health(iHealth), name(iName), playerClass(iClass) {}
        
        // Métodos declarados e definidos no corpo da classe
        unsigned int getHealth() const {return health;}
        const std::string& getClass() const {return playerClass;}
        const std::string& getName() const {return name;}
        // Método definido fora da classe
        void greeting() const;
    private:
        unsigned int health{1};
        std::string name;
        std::string playerClass;
};

void Player::greeting() const {
    std::cout << "Oi, pessoal!" << std::endl;
}

int main() {
    Player merlin{10, "Merlin", "mago"};
    std::cout << "O nome do personagem é: " << merlin.getName() << ". A sua classe é " << merlin.getClass() << ", e ele possui " << merlin.getHealth() << " pontos de vida." << std::endl;

    // A linha a seguir está em erro, pois "name" é um atributo privado de Player
    std::cout << "O nome do personagem é: " << merlin.name << std::endl;
}

O nome do personagem é: Merlin. A sua classe é mago, e ele possui 10 pontos de vida.

Atributos de uma classe

No exemplo 1 criei a classe Player para representar um personagem de um jogo de RPG. O personagem tem 3 atributos, que são os dados (também é possível vê-los como variáveis da classe) que pertencem a cada instância da classe Player. Os atributos são os seguintes: health (que armazena os pontos de vida do personagem), name (que guarda o seu nome), e playerClass (para guardar a classe do personagem). Esses atributos são individuais para cada instância da classe, isto é, para cada objeto que criamos no nosso código e que pertence à classe Player (um exemplo de instância dessa classe é o objeto merlin criado na linha 24 do exemplo 1.

Métodos de uma classe

Além dos atributos, que servem para guardar informações acerca das suas instâncias, as classes também podem possuir funções que lhe pertencem e são chamadas comumente de métodos. Os métodos são como funções normais, mas que podem ser invocados unicamente sobre uma instância da classe a que pertencem (com exceção dos métodos estáticos, que veremos em um outro artigo).

No exemplo 1 há quatro métodos presentes na classe Player: getHealth, getName, getClass e greeting. Cada um dos três primeiros (chamados de getters) faz apenas uma coisa: retornar o atributo que lhe corresponde. getHealth retorna a saúde atual do jogador; getName retorna o seu nome; e getClass retorna a classe do seu personagem. Os três foram definidos dentro da própria classe, ou seja, o corpo da função foi escrito dentro das chaves da classe Player, mas eles também poderiam ter sido definidos fora da classe. Neste caso, todavia, seria preciso preceder o nome do método pelo nome da classe seguido de ::, como foi feito para o método greeting() (linha 25), que apenas imprime na tela a saudação “Oi, pessoal!”.

Note que todos os métodos tem a palavra const após o seu nome. Isso serve para indicar que no corpo daquele método, o objeto sobre o qual ele foi invocado (que pode ser acessado através do ponteiro this) é considerado constante e não pode ser alterado.

Construtor de uma classe em C++

Há ainda um método do qual não falei na classe Player: o construtor com 3 parâmetros da linha 11. Os construtores são métodos especiais que se utilizam quando se deseja inicializar uma instância da classe a que pertencem. Eles também sempre possuem o mesmo nome que o nome da classe. O meu construtor da linha 11, portanto, serve para inicializar objetos da classe Player a partir de 3 valores: a saúde inicial do personagem (iHealth), seu nome (iName) e sua classe no jogo (iClass). Note que esse construtor foi invocado na linha 30 para criar meu personagem merlin, e eu passei-lhe os argumentos dentro de chaves (o que é chamado de inicialização por lista, ou inicialização direta).

Note ainda que após os parênteses dos parâmetros do construto, há o seguinte: `: health(iHealth), name(iName), playerClass(iClass) {}`. Para que serve isso? Como você pode ter adivinhado, essa seção entre os dois-pontos e as chaves serve para dar valores aos atributos do objeto que está sendo criado – health recebe o valor iHealth, name recebe iName e playerClass recebe o valor iClass. Esta região é chamada de lista de inicialização, e nela os atributos são inicializados antes da execução do corpo do construtor (até que eu escreva um artigo sobre esse assunto, há uma boa fonte, mas em inglês, sobre esse assunto no Cpp reference). Sempre que possível os atributos devem ser inicializados na lista de inicialização, ao invés de no corpo da função (isso causaria uma reescritura do valor do atributo, que já teria sido inicializado com o valor padrão para o seu tipo).

Especificadores de controle de acesso de uma classe em C++ – public, private e protected

Um último elemento a analisarmos nesse artigo são as palavras-chave public e private, presentes nas linhas 10 e 19, respectivamente. Elas são chamadas de especificadores de controle de acesso, pois são elas que determinam quais elementos da classe o usuário pode acessar.

Public

Os elementos (métodos ou atributos) abaixo da palavra-chave public (público, em português) podem ser acessados pelo usuário sem nenhum problema (por isso eu pude invocar os métodos get… na linha 31 sobre o meu objeto merlin), como se eles estivessem no domínio público.

Os elementos de uma classe que se segue à palavra-chave private (privado, em português), todavia, só podem ser acessados dentro do métodos da própria classe – não é permitido usá-los em outros lugares do código (por isso que a linha 34 do exemplo 1 está em erro, pois eu tentei acessar o atributo name, que é privado, fora de um método da classe Player).

Private

O private é útil para esconder do usuário de uma classe alguns de seus detalhes de implementação, ou para impedir que ele possa fazer o que quiser com os seus elementos (como trapacear e modificar o valor da saúde do jogador diretamente através do atributo health, sem utilizar os métodos que são destinados a esse fim e que possuem verificações anti-trapaça, por exemplo).

Protected

O terceiro especificador de controle de acesso em C++ é o protected, que funciona como um intermediário entre o public e o private. Os membros de uma classe (métodos ou atributos) que estejam abaixo da palavra-chave protected não podem ser usados fora dos métodos da classe (assim como o private), mas podem ser usados em métodos de classes derivadas (que herdam da classe que possui os membros de tipo protected). Falarei mais sobre esse assunto no artigo sobre classes e herança em C++.

Conclusão

Neste artigo vimos como criar uma classe em C++ de maneira bem simples. Começamos pela sintaxe das classes em C++, por quais são as palavras-chaves utilizadas no contexto das classes e como utilizá-las. Em seguida, vimos o que são os atributos e os métodos das classes em C++, e como criá-los e usá-los. Por fim, falei rapidamente acerca dos construtores e dos especificadores de acesso public, protected e private.

Foto de perfil de Emanoel

Sou apaixonado por tecnologia, literatura e também filosofia. O cultivo dessas paixões ao longo da minha trajetória me inspiraram a compartilhar aquilo que aprendo com os outros da maneira mais clara que eu possa. Sou formado em Engenharia Elétrica no Brasil, e também sou engenheiro formado na França. Trabalho atualmente como programador C++ em uma multinacional francesa, uma das maiores empresas de TI do mundo.

Leave a Reply

Your email address will not be published. Required fields are marked *