Re: Calling a non-virtual member function for a NULL instance
Matt Curtis wrote:
A container filled with Cell * can have most initialised to
NULL, which would allow calls to std::accumulate (for
example) to work without having to create cells, and
keeps the logic for empty cells in Cell.
But that's so easy! :-)
The work around is to make Cell a proxy class that holds a (possibly
NULL) pointer to a CellContent object that does the real work. The
proxy has a non-virtual function which tests whether the internal
pointer is null and either dispatches the call to the pointed-to object
or returns the default value.
#include <vector>
#include <numeric>
#include <iostream>
// handy utility
template < class T >
struct Destroyer {
Destroyer( T& container ): mContainer( container ) {}
~Destroyer()
{
for (typename T::iterator i = mContainer.begin();
i != mContainer.end();
++i) {
i->Destroy();
}
}
T& mContainer;
};
// base class for real cell content
class CellContent {
public:
virtual double GetValue() { return 2.5; }
};
// proxy class for storage in container
class Cell {
public:
Cell(): pData(0) {}
Cell( CellContent* p ): pData(p) {}
double GetValue() const {
return pData ? (pData->GetValue()) : 0.0;
}
void Destroy() { delete pData; }
private:
CellContent* pData;
};
struct AddUp {
double operator() (double d, const Cell& c) const
{
return d + c.GetValue();
}
};
int main()
{
std::vector<Cell> cells (100);
Destroyer< std::vector<Cell> > x (cells);
cells[10] = Cell( new CellContent );
cells[20] = Cell( new CellContent );
double d = std::accumulate( cells.begin(), cells.end(), 0.0, AddUp()
);
std::cout << d << std::endl;
}
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]