4

I've created a class with some static datas. Something like this:

class Object
{
public:
    Object();
    Object( Point center, double area );
    Object( int cx, int cy, double area );
    ~Object();
    //and other public stuffs here...
private:
    Point center;
    double area;
    static double totalArea;
    static int objCounter;
    static double areaMean;
};

than in it's constructor and destructor I made:

Object::Object()
{
    this->setCenter( Point() );
    this->setArea( 0.0 );
    objCounter++;
    totalArea += 0;
    areaMean = totalArea / objCounter;
}
/*this is just the default constructor I 
have two others that increment real area, not 0*/ 

Object::~Object()
{
    //cout << "Destructor called!\n"; //put it just to test
    objCounter--;
    totalArea -= this->area;
    areaMean = totalArea / objCounter;
}

So my intention was to know how many Objects were created, it's total area and the mean area. I tested it with simple statements like:

Object first;
Object second;
cout << Object::getObjCounter() << "\n"; 
///I have the get method implement origanally

And everything it's ok. Object class count number of instaces correctly. I tested using simple arrays:

Object test[ 10 ];
cout << Object::getObjCounter() << "\n";

Amazing... it works, as it should; I tested with dynamic allocation:

Object *test = new Object[ 10 ];
cout << Object::getObjCounter() << "\n";
delete [] test;

Again... it works. But when i try:

vector< Object > test( 10, Object() );
cout << Object::getObjCounter() << "\n";

It gives me zero in the stdout... I put flags in constructor and destructor to see why it's happening. And it shows me that when I use the vector statement shown, constructor is called just on, than the destructor is called in sequence!!!! Why???? Doesn't make sense to me! Could anybody explain this to me? In addition, could anybody help me in using vector to achieve the same effect that I have with simple arrays, which means: has a bunch of objects inside something, and counting it correctly? The thing is I need vectors functionality like remove and add elements, and resizing, but I don't want to reinvent wheel. Thanks in advance.

Hugo Oshiro
  • 380
  • 4
  • 17
  • That vector constructor copy-constructs them. You shouldn't need the `Object()` argument, either. – chris Aug 23 '13 at 12:48
  • What is the point of doing `totalArea += 0;` in the default constructor? – Blastfurnace Aug 23 '13 at 14:52
  • Object() is just the default constructor, I just put totalArea+= 0 to have a similar code to effective constructor. – Hugo Oshiro Aug 27 '13 at 15:33
  • [Rule of Thee](http://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming)). Though with C++11 that should be expanded to the Rule of Five. – Cornstalks Aug 27 '13 at 16:18

2 Answers2

10

You need to define a copy constructor for your Object class. http://www.cplusplus.com/articles/y8hv0pDG/

slaterade
  • 454
  • 4
  • 8
  • 1
    Up voted, copy constructor is very important as the default automatically generated one for the class shown isn't going to update those statics. http://stackoverflow.com/questions/3378533/whats-all-the-fuss-about-c-copy-constructors – Drew MacInnis Aug 23 '13 at 13:01
  • Thank's It's worked like a charm! But I didn't understand why? Vectors create one object, made the others by copying it, and destroys the first one created.. Is it? – Hugo Oshiro Aug 27 '13 at 16:35
  • 1
    @HugoOshiro I think your `Object()` argument calls the ctor once and the dtor when it goes out of scope. The vector calls copy ctor on this temp object several times. – A.E. Drew Aug 27 '13 at 16:53
  • @HugoOshiro like Drew said, your statement `vector< Object > test( 10, Object() );` creates a temporary Object and the vector is free to COPY it into the container. The original object is destroyed on each copy. If you are using C++11, you can avoid the destructor and copy constructor calls with `std::move` – slaterade Aug 29 '13 at 02:31
4

sudopunk is exactly right, you need a copy constructor. However, it would also be good practice to follow the rule of three and define a copy assignment operator:

If you have either the destructor, copy constructor or copy assignment operator, you should explicitly declare all three of them.

Here's how you would define them:

Object& operator=(const Object& rhs);
Object(const Object&);

Note that copy constructors, copy assignment operators and destructors very important for any class that has members/resources that were allocated somewhere else - dynamically on the heap. Implicit copy constructors and assignment operators only do a memberwise copy of the objects.

Another optimization would be to apply move semantics but that's a different story and it's out of the scope of this thread.

Community
  • 1
  • 1
Oleksiy
  • 37,477
  • 22
  • 74
  • 122
  • 1
    If you don't want to use one of the three, you can declare it private. You don't have to provide an implementation for it in that case, you just tell the compiler that you don't want it to create it's own (wrong) version, and that nobody should ever call it. This hassle about having to correctly write four different functions (destructor included) for each class non-trivial class is one of the worst design faults of C++ in my eyes. – cmaster - reinstate monica Aug 27 '13 at 18:32