Newsgroup: it.comp.lang.c++
Titolo: conteggio new/delete

Per accertarmi di non avere problemi di allocazione, sto creando una 
piccola classe per monitorare il comportamento delle altre classi.
Per ora controllo solo il bilancio tra allocazioni e deallocazioni.
Il codice è semplice.
Noterete subito che non si compila poiché c'è un'ambiguità. Sarei 
curioso di sapere come affrontereste la cosa. Io devo ancora pensarci 
con calma, ma oggi è sabato e sono stanco.
Ogni classe X eredita la classe MemMon<X>. Il problema è che in questo 
modo si possono avere classi che contengono due MemMon (di tipo 
diverso). Quale new e delete chiamare? Come far sì che venga chiamato 
quello giusto? Soprattutto, ne esiste sempre uno giusto?
//------ codice semplificato ------
/* a.h */
#ifndef _INCLUDE_MEM_DEBUG_
#define _INCLUDE_MEM_DEBUG_
#include <iostream>
#include <new>
struct MemMonError {};
template <class CLASS>
class MemMon
{
private:
	static unsigned allocated;
public:
	static unsigned getAllocated() { return allocated; }
	void* operator new(std::size_t _Count)/* throw(std::bad_alloc)*/
	{
#		ifndef DO_NOT_PRINT_IN_NEW
				std::cout << "N";
#		endif
		void *v = malloc(_Count);
		if (v)
			++allocated;
		return v;
	}
	void operator delete(void* _Ptr) /*throw()*/
	{
		if (!allocated)
			throw MemMonError();
		--allocated;
		if (!_Ptr)
			throw MemMonError();
#		ifndef DO_NOT_PRINT_IN_NEW
				std::cout << "D";
#		endif
		free(_Ptr);
	}
};
#endif
-------
/* a.cpp */
#include "a.h"
template <class CLASS>
unsigned MemMon<CLASS>::allocated = 0;
struct A : public virtual MemMon<A>
{
	int a;
};
struct B : public A, public virtual MemMon<B>
{
	int b;
};
int main()
{
	B* b;
	b = new B;
	delete b;
	int n = B::getAllocated();
}
------
Kiuhnm

 Noterete subito che non si compila poiché c'č un'ambiguitą.
Se la fretta non m'inganna, questo piccolo esempio mostra che i 
modificatori d'accesso public, protected e private sono troppo limitativi.
In questo esempio il problema verrebbe risolto facendo sģ che new e 
delete fossero public, ma non ereditabili.
Allora sarebbe opportuno sostituire public/protected/private con 
public/heritable.
Es.
class A
{
public:
   int pub;
protected:
   int prot;
private:
   int pri;
};
verrebbe scritto come:
class A
{
   public heritable int pub;
   heritable int prot;
   int pri;
};
Tornando al problema iniziale, avremmo:
class MemMon
{
   public heritable new();
};
class A : public MemMon
{
};
class B : public heritable A, public MemMon
{
};
In questo modo, B non vedrebbe A::MemMon perché non ereditabile.
Invece in C++ sono costretto a fare qualcosa del genere:
struct B : public A, public virtual MemMon<B>
{
	using MemMon<B>::operator new;
	using MemMon<B>::operator delete;
	using MemMon<B>::getAllocated;
	int b;
};
Kiuhnm

 };
Ancora meglio:
class MemMon
{
   heritable@public new();
};
L'operatore new non è pubblico, ma ereditabile COME pubblico.
Non si può cioè accedere a MemMon::new, ma, definita la classe A come
class A : public MemMon
{
};
è possibile accedere ad A::MemMon::new poiché new viene ereditato come 
pubblico.
Naturalmente, se A fosse stata definita come
class A : MemMon
{
};
non sarebbe stato possibile accedere né ad A::MemMon né ad A::MemMon::new.
Ma tutto questo è un po' OT.
Kiuhnm