Membri di istanza e statici
Fa parte della sezione Programmazione orientata agli oggetti del percorso C++ di Coddy. Lezione 27 di 104.
Finora, ogni variabile membro che hai creato appartiene a un oggetto specifico. Quando crei due oggetti Player, ciascuno ha il proprio name e health. Questi sono chiamati membri di istanza: esistono separatamente per ogni istanza della classe.
Ma cosa succede se hai bisogno di dati condivisi tra tutti gli oggetti? Per esempio, per tenere traccia del numero totale di giocatori.
È qui che entrano in gioco i membri statici. Un membro statico appartiene alla classe stessa, non a un oggetto specifico.
class Player {
std::string name; // Membro di istanza - ogni giocatore ha il proprio
int health; // Membro di istanza
static int playerCount; // Membro statico - condiviso da TUTTI i giocatori
public:
Player(std::string n) : name(n), health(100) {
playerCount++; // Incrementa quando viene creato un giocatore
}
~Player() {
playerCount--; // Decrementa quando viene distrutto un giocatore
}
};La differenza fondamentale: i membri di istanza si accedono tramite un oggetto, mentre i membri statici si possono accedere tramite il nome della classe stessa. Pensa ai membri di istanza come a «uno per oggetto» e ai membri statici come a «uno per classe».
| Membri di istanza | Membri statici |
|---|---|
| Unici per ogni oggetto | Condivisi tra tutti gli oggetti |
| Creati quando viene creato l'oggetto | Esistono prima che venga creato qualsiasi oggetto |
Accessibili tramite l'oggetto: player.health | Accessibili tramite la classe: Player::playerCount |
I membri statici sono utili per contatori, valori di configurazione o qualsiasi dato che appartenga logicamente alla classe anziché ai singoli oggetti.
Sfida
FacileCreiamo un sistema di inventario dei prodotti che tenga traccia sia dei dettagli dei singoli prodotti sia delle statistiche complessive dell'inventario, usando membri di istanza e statici.
Creerai due file per organizzare il codice:
Product.h: definisci una classeProductche gestisca i singoli prodotti e tenga anche traccia dei dati dell'intero inventario. La classe dovrebbe avere:- Membri di istanza:
name(stringa) eprice(double): unici per ogni prodotto - Un membro statico
totalProductsche conta quanti prodotti esistono attualmente - Un membro statico
totalValueche tiene traccia del prezzo complessivo di tutti i prodotti - Un costruttore che accetta un nome e un prezzo, inizializza i membri di istanza e aggiorna entrambi i contatori statici (incrementa il conteggio, aggiunge il prezzo al valore totale)
- Un distruttore che aggiorna i contatori statici quando un prodotto viene rimosso (decrementa il conteggio, sottrae il prezzo dal valore totale)
- Un metodo
getInfo()che restituisce una stringa nel formato:"<name>: $<price>" - Un metodo statico
getInventoryStats()che restituisce una stringa:"Products: <count>, Total Value: $<value>"
- Membri di istanza:
main.cpp: mostra come i membri statici siano condivisi tra tutti gli oggetti, mentre i membri di istanza restano unici. Leggi dall'input i nomi e i prezzi di due prodotti (name1, price1, name2, price2: ciascuno su una riga separata), poi:- Stampa le statistiche iniziali dell'inventario usando il nome della classe:
Product::getInventoryStats() - Crea un blocco di ambito con parentesi graffe e al suo interno crea un
Productcon il primo nome e il primo prezzo. Stampa le sue informazioni e le statistiche aggiornate dell'inventario. - Dopo la fine del blocco (il primo prodotto viene distrutto), stampa
"After first scope:"seguito dalle statistiche dell'inventario - Crea un altro
Productcon il secondo nome e il secondo prezzo. Stampa le sue informazioni e le statistiche dell'inventario. - Crea un terzo
Productcon il nome"Bonus"e il prezzo5.00. Stampa le statistiche finali dell'inventario.
- Stampa le statistiche iniziali dell'inventario usando il nome della classe:
Ricorda di definire i membri statici fuori dalla classe nel file header (dopo la definizione della classe). Formatta i prezzi con due cifre decimali usando std::fixed e std::setprecision(2) da <iomanip>.
Includi il file header in main.cpp usando #include "Product.h".
Provalo tu
#include <iostream>
#include <string>
#include "Product.h"
using namespace std;
int main() {
// Lee la entrada
string name1;
double price1;
string name2;
double price2;
getline(cin, name1);
cin >> price1;
cin.ignore();
getline(cin, name2);
cin >> price2;
// TODO: Imprime las estadísticas iniciales del inventario usando Product::getInventoryStats()
// TODO: Crea un bloque de ámbito con llaves
// Dentro del bloque:
// - Crea un Product con name1 y price1
// - Imprime su información usando getInfo()
// - Imprime las estadísticas actuales del inventario
// TODO: Después de que termine el bloque, imprime "After first scope:"
// Luego imprime las estadísticas del inventario
// TODO: Crea otro Product con name2 y price2
// Imprime su información y las estadísticas del inventario
// TODO: Crea un tercer Product con el nombre "Bonus" y el precio 5.00
// Stampa le statistiche finali dell'inventario
return 0;
}
Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Programmazione orientata agli oggetti
1Fondamenti della programmazione orientata agli oggetti
File esterniBuild e compilazione in C++File header e file sorgenteNamespace e ambitoIntroduzione alla programmazione orientata agli oggetti in C++Classi e oggetti a confrontoIl puntatore 'this'Metodi (funzioni membro)Attributi (membri dati)Fondamenti di costruttori e distruttoriRiepilogo - Calcolatrice semplice4Proprietà delle classi
Membri di istanza e staticiGetter e setterFunzioni membro constParola chiave mutableMetodi e variabili staticiFunzioni e classi friendRiepilogo - Gestore di conti bancari7Ereditarietà
Ereditarietà di baseLivelli di accesso nell’ereditarietàOrdine di chiamata di costruttori e distruttoriRidefinizione dei metodiFunzioni virtuali e VTableEreditarietà multiplaEreditarietà virtualeRiepilogo - Gerarchia dei dipendenti2Gestione della memoria
Memoria Stack vs HeapPuntatori e riferimentiMemoria dinamica (new/delete)Puntatori intelligenti in C++RAII in C++Riepilogo - Gestore di array dinamico5Incapsulamento
Specificatori di accesso in C++Specificatori di accesso in dettaglioOccultamento delle informazioniStruct vs classClassi annidate e interneRiepilogo - Sistema di registrazione degli studenti8Polimorfismo
Polimorfismo a compile time e a runtimeOverload delle funzioniFunzioni virtuali: ripassoFunzioni virtuali pureClassi astratteProgettazione delle interfacce in C++Dynamic casting e RTTIRipasso: calcolatrice di forme11Concetti avanzati di OOP
Composizione vs ereditarietàMixin tramite CRTPIdiom PimplType ErasureEnum class e tipizzazione forteGestione delle eccezioni in OOPGerarchie personalizzate di eccezioni14Pattern di progettazione - Parte 2
Pattern CommandPattern AdapterPattern DecoratorPattern Template MethodPattern StatePattern CompositeRAII come pattern3Costruttori e distruttori
Costruttore predefinitoCostruttore con parametriCostruttore di copiaCostruttore di spostamentoListe di inizializzazione dei costruttoriCostruttori delegantiApprofondimento sui distruttoriRegola del Tre / Cinque / ZeroRipasso - classe String6Sovraccarico degli operatori
Introduzione al sovraccarico degli operatoriSovraccarico degli operatori aritmeticiSovraccarico degli operatori di confrontoOperatori di flussoSovraccarico dell'operatore di assegnazioneSovraccarico degli operatori [] e ()Operatori di conversione di tipoRipasso - Classe Matrix9Template
Template di funzioneTemplate di classeSpecializzazione dei templateTemplate variadiciBasi di SFINAE e dei trait di tipoRiepilogo - Contenitore genericoEsercitati da solo: Compilatore C++ online