Correttezza const
Fa parte della sezione Programmazione orientata agli oggetti del percorso C di Coddy. Lezione 8 di 61.
Quando scrivi funzioni che agiscono come metodi, alcune dovrebbero modificare l'oggetto (come player_take_damage), mentre altre dovrebbero solo leggere i dati senza cambiare nulla. La parola chiave const ti permette di imporre questa distinzione a livello di compilatore.
Contrassegnando un parametro puntatore con const, prometti che la funzione non modificherà i dati a cui punta. Se provi accidentalmente a modificare un membro, il compilatore genererà un errore:
typedef struct {
int x;
int y;
} Point;
// Questa funzione può solo LEGGERE il punto
void point_print(const Point *self) {
printf("(%d, %d)\n", self->x, self->y);
// self->x = 10; // ERROR: impossibile modificare tramite un puntatore const
}
// Questa funzione può MODIFICARE il punto
void point_move(Point *self, int dx, int dy) {
self->x += dx;
self->y += dy;
}
Il parametro const Point *self comunica sia al compilatore sia agli altri programmatori che point_print è un «getter» o un'operazione di sola lettura. Questo si chiama correttezza const: usare const ovunque non sia necessaria una modifica.
Questa pratica individua i bug in anticipo. Se scrivi una funzione di visualizzazione e modifichi accidentalmente un campo, il compilatore si ferma immediatamente, anziché lasciar entrare il bug nel tuo programma.
Sfida
FacileCostruiamo un modulo Temperature che memorizza un valore di temperatura e fornisce sia operazioni di sola lettura sia operazioni che modificano i dati. Questo ti aiuterà a esercitarti nell'uso dei puntatori const per distinguere chiaramente tra le funzioni che si limitano a leggere i dati e quelle che li modificano.
Creerai tre file:
temperature.h: dichiara una structTemperaturecon un solo membrodouble celsius. Dichiara anche tre funzioni:temp_display: accetta un puntatoreconsta Temperature e stampa la temperatura corrente (sola lettura)temp_adjust: accetta un puntatore normale a Temperature e una quantità double, quindi aggiunge la quantità a celsius (modifica i dati)temp_to_fahrenheit: accetta un puntatoreconsta Temperature e restituisce il valore convertito in Fahrenheit (sola lettura)
TEMPERATURE_H.temperature.c: implementa tutte e tre le funzioni. La funzionetemp_displaydeve stampare nel formatoCurrent: {celsius}C. La funzionetemp_to_fahrenheitdeve restituirecelsius * 9.0 / 5.0 + 32.0. Ricorda che le funzioni che usano puntatoriconstnon possono modificare i dati della struct.main.c: crea una Temperature, esegui le operazioni e mostra i risultati.
Riceverai due input: il valore iniziale in gradi Celsius (come double) e la quantità di variazione (come double).
Nel file principale:
- Inizializza una
Temperaturecon il valore iniziale in gradi Celsius - Chiama
temp_displayper mostrare la temperatura iniziale - Chiama
temp_adjustper modificare la temperatura della quantità indicata - Chiama di nuovo
temp_displayper mostrare la temperatura aggiornata - Stampa la conversione in Fahrenheit usando
temp_to_fahrenheit
Stampa i risultati in questo formato:
Current: {celsius}C
Current: {celsius}C
Fahrenheit: {fahrenheit}FUsa %.1f per tutti i valori di temperatura, in modo da visualizzare una cifra decimale.
Per esempio, con un valore iniziale di 20.0 e una variazione di 5.0, l'output sarebbe:
Current: 20.0C
Current: 25.0C
Fahrenheit: 77.0FProvalo tu
#include <stdio.h>
#include "temperature.h"
int main() {
double initial_celsius, adjustment;
scanf("%lf", &initial_celsius);
scanf("%lf", &adjustment);
// TODO: Crea una struct Temperature e inizializzala con initial_celsius
// TODO: Chiama temp_display per mostrare la temperatura iniziale
// TODO: Chiama temp_adjust per modificare la temperatura della quantità indicata da adjustment
// TODO: Chiama di nuovo temp_display per mostrare la temperatura aggiornata
// TODO: Stampa la conversione in Fahrenheit usando temp_to_fahrenheit
// Formato: "Fahrenheit: %.1fF\n"
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
1Basi di programmazione modulare
File di intestazioneGuardie di inclusioneFile sorgenteFunzioni staticheRipasso: calcolatrice modulare4Incapsulamento
Il concetto di puntatori opachiDefinire struct opacheGetter e setterLa convalida nei setterRiepilogo: scatola segreta2Oggetti e metodi
Le struct come oggettiIl puntatore 'Self'Correttezza constPuntatore o valoreMetodi di supportoRiepilogo: gestore di punti5Progetto: Conto bancario semplice
Configurazione del progettoImplementazione del conto8Polimorfismo
Puntatori a funzione nelle structSimulare i metodiIl concetto di interfacciaImplementare le interfacceIterazione polimorficaRiepilogo: Greeter11Pattern di progettazione in C
Pattern SingletonPattern FactoryPattern IteratorRiepilogo: Factory di Logger3Ciclo di vita degli oggetti
Pattern del costruttorePattern del distruttoreInizializzazione sullo stackCopia profondaRiepilogo: wrapper di stringhe6Ereditarietà tramite composizione
Incorporamento delle structLa regola del primo membroAccesso ai membri della classe baseUpcastingRiepilogo: gerarchia di forme9Progetto: Disegnatore di forme
Panoramica del progettoImplementazione del cerchioImplementazione del rettangoloUtilizzo polimorficoContenitore di formeEsercitati da solo: Compilatore C online