Newsgroup: it.comp.lang.c++
Titolo: Operatori Virtuali

Perché l'operatore delete non può essere virtuale?
Tecnicamente segue dal fatto che è sempre static, ma perché complicare 
così la vita dei progammatori di C++?
Ci deve essere un motivo profondo per una scelta del genere.
Qualcuno la conosce?
Per es. il seguente codice (pur presentando altri errori concettuali e 
non), funziona correttamente grazie al distruttore virtuale.
 >>>>>
class B
{
public:
   virtual ~B();
   void operator delete  ( void*, size_t ) throw();
   void operator delete[]( void*, size_t ) throw();
   void f( void*, size_t ) throw();
};
class D : public B
{
public:
   void operator delete  ( void* ) throw();
   void operator delete[]( void* ) throw();
};
B* pb1 = new D;
delete pb1;
// Questo invece è indefinito:
//B* pb2 = new D[10];
//delete[] pb2;
<<<<<
Kiuhnm

 //delete[] pb2;
Si. Ma non per il motivo che pensi tu.
Anche se spesso ce ne si dimentica, c'è una differenza fra un puntatore 
ad un oggetto e un puntatore al primo oggetto di un array.
Il motivo per cui il "delete[] pb2" è sbagliato è sostanzialmente lo 
stesso per cui sarebbe sbagliato "pb2++" o in generale dereferenziare il 
puntatore come vettore, per esempio "pb2[3].qualchecosa".
E' vero che hai un puntatore ad un oggetto e che questo è un puntatore 
valido. Ma pur essendo il puntatore al primo oggetto di un array, non è 
valido come puntatore ad un oggetto dell'array (ovvero è vero che 
l'oggetto puntato pb2 fa parte di un array, ma attraverso pb2 puoi 
accedere a quell'oggetto e basta, non all'array).

 accedere a quell'oggetto e basta, non all'array).
Il discorso è molto più semplice: non si può modificare il comportamento 
dei tipi built-in.
Il massimo che si può fare è creare degli iteratori o usare qualcosa del 
genere:
 >>>>>>>>>>>>
class C
{
	int a;
public:
	virtual C* getNext() { return this+1; }
};
class D : public C
{
	int a;
public:
	virtual D* getNext() { return this+1; }
};
int main()
{
	D* d = new D[10];
	C* c = static_cast<C*>(d);
	C* r = new C[10];
	c = c->getNext();
	d = d->getNext();
	r = r->getNext();
}
<<<<<<<<<<<<
Kiuhnm

 /statici/ quindi non possono essere virtual.
Non è un problema. E non può che essere così: se non fossero statici 
(ovvero, in senso astratto metodi della classe e non delle istanze di 
questa) dovrebbero avere "this" come parametro (nascosto) e avere 
accesso ai membri (dati) senza indicare esplicitamente a quale istanza 
dell'oggeto ci si riferisce. Il che non ha senso.
struct A {
   int i;
   void method()
   {
     i=0; // refers to A::i for *this instance
   }
   void* operator new( size_t )
   {
     i=0; // what i?
   }
   void operator delete( void* )
   {
     i=0; // what i?
   }
};

 dell'oggeto ci si riferisce. Il che non ha senso.
Direi che il punto fondamentale e' questo: gli operatori new e delete
non possono essere virtuali perche' per definizione richiedono
l'esistenza di un oggetto del tipo dinamico corrispondente, metre
quando essi eseguono tale oggetto non esiste. Questa non e' solo
teoria: la virtual table di un oggetto viene resettata nel caso della
distruzione a quella relativa alla classe base al termine
dell'esecuzione del distruttore della classe figlia: al momento di
invocare operator delete() non esiste piu' la virtual table necessaria
a risolvere la chiamata virtuale.
Ciao,
Nicola

   }
Il membro i della classe all'indirizzo passato come parametro, 
ovviamente (se la delete fosse diversa).
Kiuhnm

 ovviamente (se la delete fosse diversa).
Sembra facile. Ma non lo è. L'indirizzo passato al delete può non essere 
l'indirizzo che sarebbe passato ad un membro se la classe fosse ancora 
valida (multiple inheritance).
Inoltre ... come fai con operator delete[] ?

 Inoltre ... come fai con operator delete[] ?
In qualche modo si farebbe, ma bisognerebbe rivoluzionare tutto il C++ a 
partire dalle vtable. Come motivazione mi basta :)
Kiuhnm