Code: Alles auswählen
class FooBase
{
public:
FooBase(void);
virtual ~FooBase(void);
private:
virtual void init(void);
virtual void cleanup(void);
int* mpBaseBar;
};
Code: Alles auswählen
class Foo: public FooBase
{
public:
Foo(void);
~Foo(void);
private:
void init(void);
void cleanup(void);
int* mpBar;
};
Code: Alles auswählen
FooBase::FooBase(void)
{
init();
}
FooBase::~FooBase(void)
{
cleanup();
}
void FooBase::init(void)
{
mpBasebar = new int;
}
void FooBase::cleanup(void)
{
delete mpBaseBar;
}
Code: Alles auswählen
Foo::Foo(void)
{
}
Foo::~Foo(void)
{
}
void Foo::init(void)
{
FooBase::init();
mpBar = new int;
}
void Foo::cleanup(void)
{
delete mpBar;
FooBase::cleanup();
}
Code: Alles auswählen
Foo myFoo; // leak!
Bloß, was ist die beste Praxis, damit umzugehen?
Macht man es wie folgt, ...
Code: Alles auswählen
Foo::Foo(void)
{
init();
}
Foo::~Foo(void)
{
cleanup();
}
void Foo::init(void)
{
mpBar = new int;
}
void Foo::cleanup(void)
{
delete mpBar;
}
Bleib also:
Code: Alles auswählen
Foo::Foo(void)
{
init();
}
Foo::~Foo(void)
{
cleanup();
}
void Foo::init(void)
{
FooBase::init();
mpBar = new int;
}
void Foo::cleanup(void)
{
delete mpBar;
FooBase::cleanup();
}
Analog gilt das Gesagte für die Desturkotren und die Häufigkeit der cleanup()-Aufrufe.
Fazit:
Die einzige Lösung scheint diese zu sein:
Code: Alles auswählen
class FooBase
{
public:
FooBase(void);
virtual ~FooBase(void);
private:
virtual void init(void);
virtual void cleanup(void);
int* mpBaseBar;
};
Code: Alles auswählen
class Foo: public FooBase
{
public:
Foo(void);
~Foo(void);
private:
void init(bool calledFromConstructor=false);
void cleanup(bool calledFromDestructor=false);
int* mpBar;
};
Code: Alles auswählen
FooBase::FooBase(void)
{
init();
}
FooBase::~FooBase(void)
{
cleanup();
}
void FooBase::init(void)
{
mpBasebar = new int;
}
void FooBase::cleanup(void)
{
delete mpBaseBar;
}
Code: Alles auswählen
Foo::Foo(void)
{
init();
}
Foo::~Foo(void)
{
cleanup();
}
void Foo::init(bool calledFromConstructor)
{
if(!calledFromConstructor)
FooBase::init();
mpBar = new int;
}
void Foo::cleanup(bool calledFromDestructor)
{
delete mpBar;
if(!calledFromDestructor)
FooBase::cleanup();
}
PS: Eigentlich müsste init() natürlich selbst noch cleanup() aufrufen, wen man es von außerhalb des Konstruktors aufrufen können soll, ohne jedes mal vorher explizit cleanup() aufzurufen, aber da das nicht zur Kernproblematik gehört, ahbe ichs aus dem vereinfachten Beispielcode mal draußen gelassen.