robert
robert

Reputation: 3726

Counter object as a class data member

I am reading Counting Objects in C++ from Scott Meyers: http://www.drdobbs.com/cpp/counting-objects-in-c/184403484. He defines a Counter class:

class Counter {  
public:          
    Counter() { ++count; }
    Counter(const Counter&) { ++count; }
    ~Counter() { --count; }
    static size_t howMany()
        { return count; }

private:
    static size_t count;
};
// This still goes in an
// implementation file
size_t Counter::count = 0;

The article says that one way to use this class is as a class data member:

class Widget {
public:
    .....  // all the usual public
           // Widget stuff
    static size_t howMany()
    { return Counter::howMany(); }
private:
    .....  // all the usual private
           // Widget stuff
    Counter c;
};

My question is related to the expression Counter c;. If we are using a static method of Counter, why is a Counter object inside Widget declared?

Upvotes: 3

Views: 3088

Answers (3)

R Sahu
R Sahu

Reputation: 206607

The real solution is a bit down the line in the article. The code you posted only serves the end goal as a means of illustration. That is not the real solution.

The real solution is to make Counter a class template.

template <typename T>
class Counter {
public:
    Counter() { ++count; }
    Counter(const Counter&) { ++count; }
    ~Counter() { --count; }

    static size_t howMany()
    { return count; }

private:
    static size_t count;
};

template <typename T>
size_t Counter<T>::count = 0; 

And then, use it as a parent class of classes for which you want to count the objects.

// inherit from Counter to count objects
class Widget: public Counter<Widget> {    
    .....
};

I am adding this as an extension. This does not appear in the article you linked to.

// inherit from Counter to count objects
class Foo: public Counter<Foo> {    
    .....
};

Now, both Widget and Foo have the functionality.

Upvotes: 1

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726609

The reason the Counter object works is that it does its job in its constructors and destructors. If you want Widget to use Counter for counting, you need to make sure that Widget's constructors call Counter's constructors, and also that Widget's destructor calls Counter's destructor.

You can achieve this by making Counter an instance member of Widget. Even though Widget never accesses Counter's methods explicitly, C++ makes sure of calling Counter's constructor and destructor implicitly, as long as Counter is a data member of the Widget class. Note that making Counter a static member of Widget would not have achieved the same goal, because constructor and destructor calls on the instance of Widget are not routed to its static data members.

Upvotes: 1

Andrzej Pronobis
Andrzej Pronobis

Reputation: 36096

It is there in order to increment the counter when a new instance of Widget is created.

When a Counter is a member of Widget, the constructor of Counter gets invoked whenever a Widget is created. This in turn, increments the value of the count variable of the Counter.

Upvotes: 1

Related Questions