0

I am working on a project that must allow all instances created to have a unique objID. All classes inherit from one base class that has a static variable that increments whenever any of the concrete classes constructor(s) are called. The counter keeps running until program is quit.

The problem I am having is when I use an array (any C++ containers), the objID registers more then one increment.

For example: In my main() I created a vector<ConcreteClassA> cc; and did a push_back(...) twice.

My Output was:

objID = 5, and count = 2

Expected Result:

objID = 2, and count = 2

I am not sure why my ObjID is registering more then once for each push_back(...). I have gone through and checked all locations to make sure my assign() is only called in constructors of my concrete classes.

Please advise.

//===========================================================================   
//Main.cpp

#include "ConcreteClassA.h";

#include <iostream>
#include <vector>
#using namespace std;

int main()
{
    vector<ConcreteClassA> c1;
    cc.push_back( ConcreteClassA() );
    cc.push_back( ConcreteClassA() );

    return 0;
}

    //objID is off for some reason....
    //Expected Results: count = 2, objID = 2
    //Output: count = 2, objID = 5

//===========================================================================
//IBase.h file
private: 
    static int objID;      //used to assign unique IDs
    static int count;      //track how many stances of all objs are active

protected:        
    const int assignID();  //return a new ID
    void decrementCount(); //decrement count, when an obj is removed
//===========================================================================

//IBase.cpp
int IBase::objID = 0;
int IBase::count= 0;

const int IBase::assignID()
{
    ++ this->count;
    ++ this->objID;

    return ( this->objID );
}

void IBase::decrementCount()
{
    -- this->count;
}

//===========================================================================
ConcreteClassA.h

ConcreteClassA();     //default constructor
ConcreteClassA(...);  //couple overloaded constructors
~ConcreteClassA();    //destructor

ConcreteClassA( const ConcreteClassA &cc );           //copy constructor
ConcreteClassA& operator=(const ConcreteClassA &cc);  //assignment operator

//more methods....

//===========================================================================
ConcreteClassA.cpp

//destructor makes sure instances tracking counter is decremented
ConcreteClassA::~ConcreteClassA()
{
    this->decrementCount();
}

//only constructors and assignemnt operators call assign() method
ConcreteClassA::ConcreteClassA()
{
    //some other initialization...
    this->assignID();
}
//All other methods implementation left out for sensitivity of real estate...
sehe
  • 374,641
  • 47
  • 450
  • 633
badboy11
  • 541
  • 1
  • 6
  • 19
  • Way to overdo using `this` to a fault! Static members do *not* depend on an instance :-) – Kerrek SB Feb 08 '12 at 20:06
  • Yes I am aware static variables don't depend on 'this'. I used for the posting to be clear, where the methods were coming from. Using 'this' should not impact outcome, the methods are instance methods. – badboy11 Feb 08 '12 at 21:44
  • If they only need to be unique among active objects during a single run, you can just use the address (`&instance` or `this`). Either way, if the numbers aren't readable enough, you can encode any 32-bit address (or counter) as two English words from `/usr/share/dict/words` (or any other word list with 2^16 entries). – rvalue Feb 08 '12 at 22:03

2 Answers2

2

You have to account for copies of the object. In C++ vector<T>::push_back() puts a copy of the object into the vector. The temp instances that you created in the function call are getting destroyed. That is why the "created" count is higher that the "active" count.

If you really want to be stingy about creating instances of the object, maybe you should store pointers in the vector. That way you have to explicitly create and destroy them.

Here's a nice post on something like that: https://stackoverflow.com/a/1361227/2174

Community
  • 1
  • 1
Dusty Campbell
  • 3,146
  • 31
  • 34
  • @badboy11 No. It has to do with how std::vector works. If you don't want to allow copies of the objects then hide the copy constructor and assignment operator by making them private. But then you're not going to be able to use std::vector. You need to decide how your object counting system will handle copies. – Dusty Campbell Feb 08 '12 at 21:55
  • Thank you sir for pointing me in the right direction. I have just started using Boost Library. I am liking it very. Could you point me to any location(s) with examples to learn from, Boost.org is not as intuitive to me at the moment. – badboy11 Feb 09 '12 at 06:30
  • Don't try to learn the whole thing. Just figure out the parts that can help you. And use [SO](http://stackoverflow.com/questions/379290/how-to-learn-boost) – Dusty Campbell Feb 09 '12 at 18:08
0
void IBase::decrementCount()
{
    -- this->count;
}

Woah, I haven't checked the operator precedence there, but I'd write

void IBase::decrementCount()
{
    -- (this->count);
}

without even thinking twice. (A good guideline is, that if you can have a doubt or would want to check, you should write it more clearly).

And, yes, that should just be

void IBase::decrementCount()
{
    --count;
}
sehe
  • 374,641
  • 47
  • 450
  • 633