Hi,
I was implementing the Exampler / Prototype pattern just to brush up on C++.
Couldn't figure out how to do the cleanup at the end.
Problem is deleting all the prototypes from the map in base class at the end. I.e. deleting all stored pointers in Animal::examplesPtr
, which is a map <string, Animal*>
.
Code where the problem is (line 27-31 in Animal.cpp).
Full code for the whole project is attached.
Animal.h
#pragma once
#include "Common.h"
#include <map>
using std::map;
using std::pair;
using std::ostream;
class Animal {
friend ostream& operator<< (ostream& o, Animal& b);
public:
virtual ~Animal();
static Animal* createAnimal (const string& type);
virtual void speak() = 0;
static void dump() ;
protected:
Animal();
Animal(const int id, const string& type);
const int mIdInt;
const string mTypeStr;
// To be implemented by derived classes..
protected:
virtual string getType() = 0;
virtual int getId() = 0;
virtual Animal* createNewInstance() = 0;
private:
typedef map<string, Animal*>::value_type t_typeToAnimalPair;
typedef map<string, Animal*>::iterator t_examplesMapIterator;
typedef map<string, Animal*> t_examplesMap;
static t_examplesMap* examplesPtr;
static void print(t_typeToAnimalPair it);
};
Animal.cpp
#include "Animal.h"
#include <algorithm>
ostream& operator<< (ostream& o, Animal& b) {
return o << "[type=" << b.getType()
<< ", id=" << b.getId()
<< ", address=" << &b
<< ']';
}
// Not defined by size as the order of static var init
// isn't guaranteed, so the map might be used before it's init'd
Animal::t_examplesMap* Animal::examplesPtr ;
Animal::Animal (const int id, const string& type) : mIdInt(id), mTypeStr(type) {
cout << "Inside Animal::Animal()" << endl;
if (NULL == examplesPtr)
examplesPtr = new t_examplesMap();
if ( examplesPtr->find( type) == examplesPtr->end())
examplesPtr->insert (t_typeToAnimalPair(string (type), this));
}
Animal::~Animal() {
cout << "Inside Animal::~Animal()" << endl;
// following results in infinite loop at delete it->second()
// calls Animal::~Animal().
t_examplesMapIterator it = examplesPtr->begin();
for (; it != examplesPtr->end(); it++)
delete it->second;
examplesPtr->clear();
}
Animal* Animal::createAnimal (const string& type) {
t_examplesMapIterator it = examplesPtr->find (type);
if (examplesPtr->end() != it) {
return it->second->createNewInstance();
} else {
string err = "Type " + type + " is not supported";
throw err;
}
}
void Animal::print (t_typeToAnimalPair p) {
cout << "\t\t" << p.first << " = " << *(p.second) << endl;
}
void Animal::dump() {
cout << "Animal::dump() -- " << endl
<< "\texamples.size() = " << examplesPtr->size() << endl;
std::for_each (examplesPtr->begin(), examplesPtr->end(), print);
}