Distruttore della classe non chiamato da delete

Ciao a tutti, oggi mentre testavo il codice di una lista dinamica sono incappato in un problema riguardante il distruttore, e dopo alcuni tentativi mi sono accorto che se eseguo il casting di una classe alla sua interfaccia e poi utilizzo delete non viene chiamato il distruttore.

Posto il codice semplificate che evidenzia il problema

Codice dell'interfaccia

class ITest
{
public:
    virtual void Foo() = 0;
};

Codice della classe che implementa l'interfaccia

class TestClass : public ITest
{
public:
    TestClass()
    {
        Serial.println("Constructor called");
    }

    ~TestClass()
    {
        Serial.println("Destructor called");
    }

    void Foo()
    {
        Serial.println("Foo called");
    }
};

main

void setup() {
    Serial.begin(9600);
}


void loop() {

    Serial.println("- Test class not casted");

    TestClass* class1 = new TestClass();
    class1->Foo();
    delete class1;

    Serial.println();


    Serial.println("- Test class casted to ITest interface");

    ITest* class2 = new TestClass();
    class2->Foo();
    delete class2;

    delay(20000);
}

Output

- Test class not casted
Constructor called
Foo called
Destructor called

- Test class casted to ITest interface
Constructor called
Foo called

Vorrei sapere, sono io che ho sbagliato a progettare il software, e' un qualche tipo di bug e se si c'e' una soluzione? Ogni consiglio o correzione e' ben accetta

Io qui ho semplificato il codice per rendere evidente il problema ma nel mio progetto l'interfaccia si chiama IList e le classi che la implementano si chiamano LinkedList e List, quindi come avrete capito mi farebbe davvero comodo poter utilizzare le interfacce ma se il distruttore non funziona non posso deallocare la memoria dinamica che utilizzo nelle rispettive implementazioni.

Ringrazio in anticipo per il tempo e per l'eventuale aiuto.

Ogni volta che leggo certe cose debbo necessariamente ricordarvi che ...

... NON siete su un PC dove c'è un sistema operativo ed un "garbage collector", siete su una piccola MCU con solo 2KBytes di SRAM, dove dovete fare tutto voi e dove usare l'allocazione e riallocazione dinamica della memoria, porta quasi sempre ... [u]a grossi problemi[/u] e sicuri mal di testa !!! :confused:

Uomo avvisato mezzo salvato ... :grin:

Guglielmo

Prima di tutto reitero quanto detto da gpb: fare allocazione dinamica su Arduino è poco sensato e crea più grattacapi di quanti ne risolve, per cui sei fortemente invitato a ripensare il tuo programma facendo a meno di new, delete, malloc() e free(). Tieni conto che su un PC ha senso perché ci sono diversi programmi in esecuzione allo stesso momento, che devono convivere e quindi non possono impossessarsi brutalmente di tutte le risorse disponibili, ma qui sei su un microcontrollore dove c'è un solo programma, per cui non ha senso allocare un po' di memoria alla volta, tanto vale allocare subito un vettore grande quanto serve, intanto se la memoria non la usa lui, chi altri lo fa?

Per il resto il tuo problema credo sia dovuto al fatto che il distruttore della tua classe non è virtual. Senza farsi troppe pippe mentali, la regola pratica è che se una classe ha almeno un membro virtual, allora anche il suo distruttore deve esserlo.

La correzione al mio problema è molto semplice

class ITest
{
public:
    virtual ~ITest() {} // questa riga risolve il problema

    virtual void Foo() = 0;
};

Ho postato la soluzione nel caso qualcuno incappi nello stesso problema.

m3nax: La correzione al mio problema è molto semplice Ho postato la soluzione nel caso qualcuno incappi nello stesso problema.

Ovvero quello che ha detto @sukko nel post precedente. E ti credo che risolvi solo con quel virtual !! Con virtual Foo()=0; crei una pure virtual function e quindi la classe è abstract.