Menu
Coddy logo textTech

Sobrecarga dos Operadores [] e ()

Parte da seção Programação Orientada a Objetos do Journey de C++ da Coddy — lição 45 de 104.

O operador de subscrito ([]) permite que sua classe se comporte como um array, fornecendo acesso indexado aos elementos. O operador de chamada de função (()) transforma objetos em entidades chamáveis, conhecidas como functores.

Aqui está um wrapper de array simples com o operador de subscrito:

class IntArray {
    int* data;
    size_t size;
    
public:
    IntArray(size_t s) : size(s), data(new int[s]()) {}
    ~IntArray() { delete[] data; }
    
    int& operator[](size_t index) {
        return data[index];
    }
    
    const int& operator[](size_t index) const {
        return data[index];
    }
};

Observe que fornecemos duas versões: uma retorna uma referência não-const (permitindo modificação), e a versão const funciona com objetos const. Isso permite que você escreva arr[0] = 5; para leitura e escrita.

O operador de chamada de função cria objetos que podem ser "chamados" como funções:

class Multiplier {
    int factor;
    
public:
    Multiplier(int f) : factor(f) {}
    
    int operator()(int value) const {
        return value * factor;
    }
};

Multiplier triple(3);
int result = triple(10);    // Retorna 30

Functors são poderosos porque podem manter o estado entre chamadas, ao contrário de funções regulares. Eles são comumente usados com algoritmos da STL onde você precisa de um comportamento personalizável que lembre valores de configuração.

challenge icon

Desafio

Fácil

Vamos construir uma classe ScoreTracker que combina os operadores de subscrito e de chamada de função. Esta classe armazenará pontuações para jogadores e permitirá que você as acesse por índice usando [], enquanto também atuará como um functor que aplica um multiplicador de bônus a qualquer pontuação que você passar para ele.

Você criará dois arquivos para organizar seu código:

  • ScoreTracker.h: Defina uma classe ScoreTracker que gerencia um array de pontuações de jogadores e pode aplicar bônus. Sua classe deve ter:
    • Um array int* alocado dinamicamente para armazenar as pontuações
    • Um membro size_t para o número de pontuações
    • Um membro double para o multiplicador de bônus
    • Um construtor que recebe o tamanho e o multiplicador de bônus, inicializando todas as pontuações com 0
    • Um destruidor que limpa adequadamente a memória dinâmica
    • O operador de subscrito [] (versões const e não-const) para acessar as pontuações por índice
    • O operador de chamada de função () que recebe uma pontuação int e retorna a pontuação multiplicada pelo multiplicador de bônus (como um int)
    • Um método getSize() que retorna o número de pontuações

    O operador de subscrito não-const retorna uma referência para que você possa escrever tracker[0] = 100;. A versão const permite acesso de apenas leitura para objetos const. O operador de chamada de função deve ser marcado como const, pois não modifica o estado do objeto.

  • main.cpp: Leia as seguintes entradas (cada uma em uma linha separada):
    1. Número de jogadores (tamanho)
    2. Multiplicador de bônus (como um double)
    3. Pontuações para cada jogador (uma por linha, tantas quanto o tamanho)
    4. Uma pontuação de teste para aplicar o bônus

    Crie um ScoreTracker, use o operador de subscrito para armazenar a pontuação de cada jogador e, em seguida, exiba todas as pontuações. Por fim, use o operador de chamada de função para calcular a pontuação com o bônus aplicado.

    Formato de saída:

    Player 0: <score>
    Player 1: <score>
    ...
    Bonus applied to <test_score>: <result>

Por exemplo, com 3 jogadores, um multiplicador de 1.5, pontuações de 100, 200, 150 e uma pontuação de teste de 80:

Player 0: 100
Player 1: 200
Player 2: 150
Bonus applied to 80: 120

Use std::stoi() e std::stod() para conversão de entrada. Não se esqueça dos header guards em seu arquivo de cabeçalho.

Folha de consulta

O operador de subscrito [] permite que objetos sejam acessados como arrays. O operador de chamada de função () torna os objetos chamáveis como funções (functors).

Operador de Subscrito

Forneça versões const e não-const para acesso de leitura/escrita:

class IntArray {
    int* data;
    size_t size;
    
public:
    IntArray(size_t s) : size(s), data(new int[s]()) {}
    ~IntArray() { delete[] data; }
    
    // Versão não-const: permite modificação
    int& operator[](size_t index) {
        return data[index];
    }
    
    // Versão const: acesso apenas de leitura
    const int& operator[](size_t index) const {
        return data[index];
    }
};

Operador de Chamada de Função

Cria functors que podem manter o estado entre as chamadas:

class Multiplier {
    int factor;
    
public:
    Multiplier(int f) : factor(f) {}
    
    int operator()(int value) const {
        return value * factor;
    }
};

Multiplier triple(3);
int result = triple(10);    // Retorna 30

Functors são úteis com algoritmos STL onde é necessário um comportamento personalizável com configuração armazenada.

Experimente você mesmo

#include <iostream>
#include <string>
#include "ScoreTracker.h"

using namespace std;

// TODO: Implementar o construtor ScoreTracker
ScoreTracker::ScoreTracker(size_t size, double multiplier) {
    // TODO: Inicializar membros e alocar array dinâmico
    // Inicializar todas as pontuações com 0
}

// TODO: Implementar o destrutor ScoreTracker
ScoreTracker::~ScoreTracker() {
    // TODO: Limpar a memória dinâmica
}

// TODO: Implementar o operador de subscrito não-const

// TODO: Implementar o operador de subscrito const

// TODO: Implementar o operador de chamada de função

// TODO: Implementar o método getSize
size_t ScoreTracker::getSize() const {
    // TODO: Retornar o número de pontuações
}

int main() {
    string line;
    
    // Ler o número de jogadores
    getline(cin, line);
    size_t numPlayers = stoi(line);
    
    // Ler o multiplicador de bônus
    getline(cin, line);
    double multiplier = stod(line);
    
    // TODO: Criar ScoreTracker com numPlayers e multiplier
    
    // TODO: Ler as pontuações de cada jogador e armazenar usando o operador de subscrito
    
    // TODO: Ler a pontuação de teste
    
    // TODO: Exibir todas as pontuações dos jogadores no formato: "Player X: <score>"
    
    // TODO: Exibir o resultado do bônus aplicado no formato: "Bonus applied to <test_score>: <result>"
    
    return 0;
}
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos