Di seguito sono riportati due frammenti (pronti per la compilazione) del codice. Nel primo frammento in cui sto usando solo la dichiarazione anticipata per una struct mentre si elimina il puntatore a questa struct da un dtor di classe Base per una classe Guest non viene invocato.
Nel secondo frammento quando invece di inoltro di dichiarazione utilizzo la definizione completa di questa classe Guest utilizzando delete in Base funziona come previsto.
Perché? Perché fa la differenza? La dichiarazione anticipata non è forse solo una nota per un compilatore che dice che la definizione di questa classe/struct è altrove?
Sono molto sorpreso che non funzioni in modo intuitivo.La dichiarazione di inoltro non funziona appena
//First just forward dclr
#include "stdafx.h"
#include <iostream>
using std::cout;
struct Guest;
struct Base
{
Guest* ptr_;
Base(Guest* ptr):ptr_(ptr)
{
cout << "Base\n";
}
~Base()
{
cout << "~Base\n";
delete ptr_;
}
};
struct Guest
{
Guest()
{
cout << "Guest\n";
throw std::exception();
}
Guest(int)
{
cout << "Guest(int)\n";
}
~Guest()
{
cout << "~Guest\n";
}
};
struct MyClass : Base
{
Guest g;
MyClass(Guest* g):Base(g)
{
cout << "MyClass\n";
}
~MyClass()
{
cout << "~MyClass\n";
}
};
int _tmain(int argc, _TCHAR* argv[])
{
try
{
Guest* g = new Guest(1);
MyClass mc(g);
}
catch(const std::exception& e)
{
std::cerr << e.what();
}
return 0;
}
// In secondo luogo - piena def
#include "stdafx.h"
#include <iostream>
using std::cout;
struct Guest
{
Guest()
{
cout << "Guest\n";
throw std::exception();
}
Guest(int)
{
cout << "Guest(int)\n";
}
~Guest()
{
cout << "~Guest\n";
}
};
struct Base
{
Guest* ptr_;
Base(Guest* ptr):ptr_(ptr)
{
cout << "Base\n";
}
~Base()
{
cout << "~Base\n";
delete ptr_;
}
};
struct MyClass : Base
{
Guest g;
MyClass(Guest* g):Base(g)
{
cout << "MyClass\n";
}
~MyClass()
{
cout << "~MyClass\n";
}
};
int _tmain(int argc, _TCHAR* argv[])
{
try
{
Guest* g = new Guest(1);
MyClass mc(g);
}
catch(const std::exception& e)
{
std::cerr << e.what();
}
return 0;
}
È consigliabile rendere virtuali i costruttori della classe base in entrambi i casi. –
@ Space_C0wb0y: Gentile, non è possibile creare un costruttore virtual in C++ :) –
@Armen: Words ... smoke and mirrors. Era così chiaro nella mia mente. (Per chi si meraviglia, dovrebbe essere * distruttori *) –