C++ moderno e alternative C

Il polimorfismo in C++ e le tabelle di puntatori a funzione in C

In questa lezione chiamerai la stessa operazione su diversi tipi di oggetti con le funzioni virtuali in C++ e i puntatori a funzione in C.

Introduzione

Il polimorfismo dinamico (dynamic polymorphism) permette al codice di chiamare un'operazione comune, come calcolare l'area, mentre ogni tipo di oggetto decide come eseguirla. C++ lo supporta direttamente con le funzioni virtuali (virtual function), mentre in C si può imitare con i puntatori a funzione.

Punti importanti

  • Capisci come si fa in C prima di imparare le astrazioni del C++.
  • Usa RAII e la semantica di valore (value semantics) per esprimere il possesso delle risorse.
  • Preferisci gli strumenti del C++ con sicurezza dei tipi a macro e conversioni di tipo.

Esempi di codice C e C++

C
Esegui →
main.c
#include <stdio.h>

typedef struct Shape Shape;
struct Shape {
    double value;
    double (*area)(const Shape *shape);
};

double square_area(const Shape *shape) {
    return shape->value * shape->value;
}

int main(void) {
    Shape square = {4.0, square_area};
    printf("area=%.1f\n", square.area(&square));
}
Risultato dell'esecuzione
area=16.0
C++
Esegui →
main.cpp
#include <iostream>

struct Shape {
    virtual double area() const = 0;
    virtual ~Shape() = default;
};

struct Square : Shape {
    double side;

    explicit Square(double value) : side(value) {}
    double area() const override { return side * side; }
};

int main() {
    Square square(4);
    const Shape& shape = square;
    std::cout << "area=" << shape.area() << '\n';
}
Risultato dell'esecuzione
area=16

Confronto tra C e C++

In C, struct Shape contiene un puntatore a funzione area, e ogni forma collega la propria funzione per l'area, come square_area. In C++ le funzioni virtuali creano automaticamente lo stesso meccanismo di scelta. La classe base dovrebbe avere anche un distruttore virtuale (virtual destructor), perché eliminare un oggetto tramite un puntatore alla classe base sia sicuro.

C

C usa convenzioni sui nomi, callback, macro e struct con il contesto.

C++

C++ offre astrazioni con un ambito chiaro, sicure rispetto ai tipi e che di solito non costano nulla in più in esecuzione.

Esercizi di approfondimento

Esegui entrambe le versioni e poi modifica il codice per osservare la differenza di sicurezza che offre ciascun linguaggio.

  • Scrivi prima il meccanismo in C e solo dopo usa la funzionalità equivalente del C++.
  • Sostituisci la liberazione manuale delle risorse con RAII.
  • Controlla se la funzionalità causa allocazioni di memoria o chiamate a funzioni virtuali.

Esercitati con una sfida

Usa ciò che questa lezione spiega per risolvere un problema reale. Ogni sfida gira nel browser, con test immediati e una revisione dell'IA.

Tutte le sfide