Membros de Instância vs Estáticos
Parte da seção Programação Orientada a Objetos do Journey de C++ da Coddy — lição 27 de 104.
Até agora, cada variável de membro que você criou pertence a um objeto específico. Quando você cria dois objetos Player, cada um tem seu próprio name e health. Estes são chamados de membros de instância - eles existem separadamente para cada instância da classe.
Mas e se você precisar de dados compartilhados entre todos os objetos? Por exemplo, rastrear quantos jogadores existem no total.
É aqui que os membros estáticos entram em cena. Um membro estático pertence à própria classe, não a nenhum objeto em particular.
class Player {
std::string name; // Membro de instância - cada jogador tem o seu próprio
int health; // Membro de instância
static int playerCount; // Membro estático - compartilhado por TODOS os jogadores
public:
Player(std::string n) : name(n), health(100) {
playerCount++; // Incrementa quando qualquer jogador é criado
}
~Player() {
playerCount--; // Decrementa quando qualquer jogador é destruído
}
};A principal diferença: membros de instância são acessados por meio de um objeto, enquanto membros estáticos podem ser acessados por meio do próprio nome da classe. Pense nos membros de instância como "um por objeto" e nos membros estáticos como "um por classe".
| Membros de Instância | Membros Estáticos |
|---|---|
| Único para cada objeto | Compartilhado entre todos os objetos |
| Criado quando o objeto é criado | Existe antes de qualquer objeto ser criado |
Acessado via objeto: player.health | Acessado via classe: Player::playerCount |
Membros estáticos são úteis para contadores, valores de configuração ou quaisquer dados que pertençam logicamente à classe em vez de objetos individuais.
Desafio
FácilVamos construir um sistema de inventário de produtos que rastreia tanto os detalhes individuais dos produtos quanto as estatísticas gerais do inventário usando membros de instância e estáticos.
Você criará dois arquivos para organizar seu código:
Product.h: Defina uma classeProductque gerencia produtos individuais enquanto também rastreia dados de todo o inventário. Sua classe deve ter:- Membros de instância:
name(string) eprice(double) — únicos para cada produto - Um membro estático
totalProductsque conta quantos produtos existem atualmente - Um membro estático
totalValueque rastreia o preço combinado de todos os produtos - Um construtor que recebe um nome e preço, inicializa os membros de instância e atualiza ambos os contadores estáticos (incrementa a contagem, adiciona o preço ao valor total)
- Um destrutor que atualiza os contadores estáticos quando um produto é removido (decrementa a contagem, subtrai o preço do valor total)
- Um método
getInfo()que retorna uma string no formato:"<name>: "<name>: $<price>"lt;price>" - Um método estático
getInventoryStats()que retorna uma string:"Products: <count>, Total Value: "Products: <count>, Total Value: $<value>"lt;value>"
- Membros de instância:
main.cpp: Demonstre como os membros estáticos são compartilhados entre todos os objetos enquanto os membros de instância permanecem únicos. Leia dois nomes de produtos e seus preços da entrada (name1, price1, name2, price2 — cada um em uma linha separada), então:- Imprima as estatísticas iniciais do inventário usando o nome da classe:
Product::getInventoryStats() - Crie um bloco de escopo com chaves e, dentro dele, crie um
Productcom o primeiro nome e preço. Imprima suas informações e as estatísticas atuais do inventário. - Após o término do bloco (primeiro produto destruído), imprima
"After first scope:"seguido pelas estatísticas do inventário - Crie outro
Productcom o segundo nome e preço. Imprima suas informações e as estatísticas do inventário. - Crie um terceiro
Productcom o nome"Bonus"e o preço5.00. Imprima as estatísticas finais do inventário.
- Imprima as estatísticas iniciais do inventário usando o nome da classe:
Lembre-se de definir seus membros estáticos fora da classe no arquivo de cabeçalho (após a definição da classe). Formate os preços com duas casas decimais usando std::fixed e std::setprecision(2) de <iomanip>.
Inclua seu arquivo de cabeçalho no main.cpp usando #include "Product.h".
Folha de consulta
C++ suporta dois tipos de membros de classe: membros de instância e membros estáticos.
Membros de instância são exclusivos de cada objeto - cada instância tem sua própria cópia:
class Player {
std::string name; // Cada jogador tem seu próprio nome
int health; // Cada jogador tem sua própria vida
};Membros estáticos são compartilhados entre todos os objetos de uma classe - existe apenas uma cópia que pertence à própria classe:
class Player {
static int playerCount; // Compartilhado por TODOS os jogadores
public:
Player(std::string n) : name(n), health(100) {
playerCount++; // Incrementa o contador compartilhado
}
~Player() {
playerCount--; // Decrementa quando destruído
}
};Principais diferenças:
| Membros de Instância | Membros Estáticos |
|---|---|
| Exclusivo de cada objeto | Compartilhado entre todos os objetos |
| Criado quando o objeto é criado | Existe antes de qualquer objeto ser criado |
Acessado via objeto: player.health | Acessado via classe: Player::playerCount |
Métodos estáticos podem ser chamados usando o nome da classe e podem acessar apenas membros estáticos:
class Player {
static int playerCount;
public:
static int getPlayerCount() {
return playerCount; // Pode acessar apenas membros estáticos
}
};
// Chama usando o nome da classe
int count = Player::getPlayerCount();Membros estáticos devem ser definidos fora da classe (geralmente em um arquivo .cpp ou após a definição da classe em um cabeçalho):
int Player::playerCount = 0;Membros estáticos são úteis para contadores, valores de configuração compartilhados ou quaisquer dados que logicamente pertençam à classe em vez de objetos individuais.
Experimente você mesmo
#include <iostream>
#include <string>
#include "Product.h"
using namespace std;
int main() {
// Ler a entrada
string name1;
double price1;
string name2;
double price2;
getline(cin, name1);
cin >> price1;
cin.ignore();
getline(cin, name2);
cin >> price2;
// TODO: Imprimir as estatísticas iniciais do inventário usando Product::getInventoryStats()
// TODO: Criar um bloco de escopo com chaves
// Dentro do bloco:
// - Criar um Product com name1 e price1
// - Imprimir suas informações usando getInfo()
// - Imprimir as estatísticas atuais do inventário
// TODO: Após o fim do bloco, imprimir "After first scope:"
// Depois, imprimir as estatísticas do inventário
// TODO: Criar outro Product com name2 e price2
// Imprimir suas informações e as estatísticas do inventário
// TODO: Criar um terceiro Product com o nome "Bonus" e o preço 5.00
// Imprimir as estatísticas finais do inventário
return 0;
}
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
1Fundamentos de OOP
Arquivos ExternosBuild e Compilação em C++Arquivos Header e SourceNamespaces e EscopoIntrodução a OOP em C++Classes vs ObjetosO Ponteiro 'this'Métodos (Funções Membro)Atributos (Membros de Dados)Básico de Ctors e DtorsRecapitulação - Calculadora Simples4Propriedades de Classe
Membros de Instância vs EstáticosGetters e SettersFunções de Membro ConstPalavra-chave MutableMétodos e Variáveis EstáticosFunções e Classes FriendRecapitulação - Gerenciador de Conta Bancária7Herança
Herança BásicaNíveis de Acesso na HerançaOrdem de Chamada de Ctor e DtorSobrescrita de MétodosFunções Virtuais e VTableHerança MúltiplaHerança VirtualRecapitulação - Hierarquia de Funcionários2Gerenciamento de Memória
Memória Stack vs HeapPonteiros e ReferênciasMemória Dinâmica (new/delete)Smart Pointers em C++RAII em C++Recapitulação - Gerenciador de Array Dinâmico5Encapsulamento
Especificadores de Acesso em C++Especificadores de Acesso em DetalhesOcultação de InformaçãoStruct vs ClassClasses Aninhadas e InternasRecapitulação - Sistema de Registros de Alunos8Polimorfismo
Polimorfismo de Compilação vs Tempo de ExecuçãoSobrecarga de FunçõesFunções Virtuais RevisitadasFunções Virtuais PurasClasses AbstratasDesign de Interfaces em C++Dynamic Casting e RTTIRecapitulação - Calculadora de Formas3Construtores e Destrutores
Construtor PadrãoConstrutor ParametrizadoConstrutor de CópiaConstrutor de MovimentaçãoListas de Inicialização do ConstrutorConstrutores DelegadosMergulho Profundo em DestrutoresRegra dos Três / Cinco / ZeroRecapitulação - Classe String6Sobrecarga de Operadores
Introdução à Sobrecarga de OperadoresSobrecarga de Operadores AritméticosSobrecarga de Operadores de ComparaçãoOperadores de StreamSobrecarga do Operador de AtribuiçãoSobrecarga dos Operadores [] e ()Operadores de Conversão de TipoRecapitulação - Classe Matrix9Templates
Templates de FunçãoTemplates de ClasseEspecialização de TemplatesTemplates VariádicosFundamentos de SFINAE e Type TraitsRecapitulação - Container Genérico