Given:
class Foo {
private:
static int cntFoos;
//... stuff...
public:
Foo() { cntFoos++; }
~Foo() { cntFoos--; }
};
... where "stuff" may be any set of properties. (The idea is to have a counter of instances of that class)
Then:
Foo aFoo;
Foo twoFoo=aFoo;
Will invoke the automatic copy constructor, and thus I'd miss counting this one.
Is there a way to keep that counter reflecting the new instances created automatically? If I implement the explicit copy constructor, I will have to assign all the properties one by one. However, I want a shallow, memberwise copy. I don't need to perform a deep copy, so it seems like a lot of unnecessary work to implement an explicit copy constructor.
Since you want the default behavior for most members and only need special handling for one (static) member, why not encapsulate that special handling in its own class and make a member variable of that class? Like this:
template<typename T>
class InstanceCounter
{
public:
static int Count;
// Automatically invoked when a class containing it is created.
InstanceCounter() { Count++; }
// Automatically invoked when a class containing it is destroyed.
~InstanceCounter() { Count--; }
// Automatically invoked when a class containing it is copy-constructed.
InstanceCounter(const InstanceCounter& rhs) { Count++; }
// No need to override operator=
// Allow this counter to be used as an int.
operator int() const { return Count; }
};
template<typename T>
int InstanceCounter<T>::Count;
class Foo
{
public:
InstanceCounter<Foo> count;
};
Implementation notes:
InstanceCounter
a template so that different classes can easily have their own instance counts.InstanceCounter
.Alternatively, and probably better, using the CRTP idiom:
template<typename T>
class InstanceCounted
{
public:
static int InstanceCount;
// Automatically invoked when a class containing it is created.
InstanceCounted() { InstanceCount++; }
// Automatically invoked when a class containing it is destroyed.
~InstanceCounted() { InstanceCount--; }
// Automatically invoked when a class containing it is copy-constructed.
InstanceCounted(const InstanceCounted& rhs) { InstanceCount++; }
// No need to override operator=
};
template<typename T>
int InstanceCounted<T>::InstanceCount;
class Foo : public InstanceCounted<Foo>
{
// insert class contents here
};
// Now we can access Foo::InstanceCount.