of OOP and C++

Started by
15 comments, last by CTar 17 years, 11 months ago
Hi, recently, i was making examples for myself about "oop in c++". my little code is below: CObject class:

class CObject{
      private:
              int value;
      public:
             CObject(int val);
             ~CObject();
             int getvalue();
};

CObject::CObject(int val){
                     cout << "CObject created! (" << val << ")" << endl;
                     value = val;
                     }
CObject::~CObject(){
                    cout << "CObject deleted! (" << value << ")" << endl;
                    }
int CObject::getvalue(){
    return value;
}

CObjectManager class:

class CObjectManager{
      private:
              vector<CObject> objlist;
      public:
             CObjectManager();
             ~CObjectManager();
             void update();
             void addObject(CObject obj);
             CObject getobject(int index);
};

void CObjectManager::update(){
                       for (int r; r<objlist.size(); r++){
                           cout << "Object" << r << "'s value is: " << objlist[r].getvalue() << endl;
                           }
                       }
                       
CObjectManager::CObjectManager(){
     cout << "CObjectManager created!" << endl;
     }

CObjectManager::~CObjectManager(){
     cout << "CObjectManager deleted!" << endl;
     }
     
void CObjectManager::addObject(CObject obj){
     objlist.push_back(obj);
     cout << "CObject added! (" << obj.getvalue() << ")" << endl;
     }
     
CObject CObjectManager::getobject(int index){
        return objlist[index];
}

and main() note that it is a console app:

int main(int argc, char *argv[])
{
    CObjectManager *man = new CObjectManager;
    CObject        *obj = new CObject(17);
    CObject        *obj2 = new CObject(21);
    
    man->addObject(*obj);    
    man->addObject(*obj2);
    //obj2 = &man->getobject(0);
    cout << obj->getvalue() << endl;
    man->update();
    
    system("PAUSE");
    return EXIT_SUCCESS;
}

Output: CObjectManager created! CObject created! (17) CObject created! (21) CObject added! (17) CObject deleted! (17) CObject deleted! (17) CObject added! (21) CObject deleted! (21) 17 Object0's value is: 17 Object1's value is: 21 Press any key to continue . . . But when i comment this line
cout << obj->getvalue() << endl;
so,
//cout << obj->getvalue() << endl;
Output: CObjectManager created! CObject created! (17) CObject created! (21) CObject added! (17) CObject deleted! (17) CObject deleted! (17) CObject added! (21) CObject deleted! (21) Press any key to continue . . . 1- Why, man->update() didn't generate any line? 2- CObject created! (17), CObject deleted! (17) CObject deleted! (17) So, c++ runs ~CObject for more then a time? Thanks.
Advertisement
I'm not sure about the first question, why it is not printing with the line commented. I'm sure there is more to it than that.

But for the 2nd one using an STL container, multiple objects are created and passed around using them.

It is really making a copy of the object.

I can see that you have posted too many times, most likely by accident since GDNet is pretty unstable currently, you can remove the extra posts by pressing edit and then deleting it.

Quote:Original post by by
1- Why, man->update() didn't generate any line?

You never set r to anything so it gets some random (well almost) value, most likely bigger than objlist.size() and therefore it never enters the loop. You should do like this:
for (int r = 0; r<objlist.size(); r++){                           cout << "Object" << r << "'s value is: " << objlist[r].getvalue() << endl;                           }

Also you should read about iterators which is a better way to iterate through a container. It will also work with lists and might provide a performance improvement with some containers.

Quote:2-
CObject created! (17),
CObject deleted! (17)
CObject deleted! (17)

So, c++ runs ~CObject for more then a time?

Well, yes, but it also creates another CObject. If you want a surprise, try changing your main to:
int main(int argc, char *argv[]){    CObjectManager *man = new CObjectManager;    CObject        *obj = new CObject(17);    CObject        *obj2 = new CObject(21);    cout << "1" << endl;        man->addObject(*obj);      cout << "2" << endl;      man->addObject(*obj2);    cout << "3" << endl;    //obj2 = &man->getobject(0);    cout << obj->getvalue() << endl;    man->update();        system("PAUSE");    return EXIT_SUCCESS;}


When you copy an object you will invoke it's copy constructor, which in this case is created by the compiler for you. Your CObject actually have a constructor which looks like this:
CObject::CObject(const CObject& copy){value = copy.value;                     }

So at the moment you invoke addObject a new CObject object is created, when you exit the function it's destroyed, so here you will get an extra call to the destructor. If you want to understand this better try adding the following method to CObject
CObject::CObject(const CObject& copy){value = copy.getvalue()*10; // Multiply by 10 to get a new valuecout << "CObject copied original=" << copy.getvalue() << " new=" << value<< std::endl;                     }

I think you will understand your code much better if you try to do that. Another thing you should note is that std::vector makes a copy of your CObject, this is the reason for the second call to the destructor. The two objects you originally created (obj and obj2) will never be destroyed because you never calls delete on them. So right before system("PAUSE") you should insert the following:
delete man;delete obj;delete obj2;
Thank you all, sometimes -like now- i love gdnet much more :)

Unfortunately, my questions not ended :)

Not about actually main topic but i dont know: has c/c++ got garbage collector?
for(int r = 0; r<5000; r++)
{
double r1;
}


---

what must i do for vector to don't copy objects, just point them ?
Quote:Original post by by
Thank you all, sometimes -like now- i love gdnet much more :)

Unfortunately, my questions not ended :)

Not about actually main topic but i dont know: has c/c++ got garbage collector?
for(int r = 0; r<5000; r++)
{
double r1;
}

I don't know what the loop has to do with anything... C and C++ doesn't have any garbage collector, all objects on the stack are destroyed automatically though. Imagine the following function:
void func(){  int * o1 = new o1;  int * o2 = o1;  int o3;  int o4 = o3;  int * o5 = &o3}

This code have one problem, o1. o1 is allocated on the heap. o2 is just a pointer. o3 and o4 is allocated on the stack and therefore automatically destroyed. o5 is also a pointer. So o5 and o2 doesn't need to be destroyed either because they just points to some memory. o1 needs to be destroyed though, because it have asked for heap-memory and need to tell that it's done. Therefore the function should look like this:
void func(){  int * o1 = new o1;  int * o2 = o1;  int o3;  int o4 = o3;  int * o5 = &o3  delete o1;}



---

Quote:what must i do for vector to don't copy objects, just point them ?


You need to use a vector of pointers, so CObjectManager should look like this:
class CObjectManager{      private:// Now container of pointers              vector<CObject*> objlist;      public:             CObjectManager();             ~CObjectManager();             void update();// Take by reference to avoid copy, yet get identical behavior// Note that it would be better to use const-reference, but because// CObject is not const-correct we can't do this without ugly const_casts.             void addObject(CObject& obj);             CObject getobject(int index);};void CObjectManager::update(){// Use -> instead since we are dealing with pointers, we could also use// (*objlist[r]).getvalue()                       for (int r = 0; r<objlist.size(); r++){                           cout << "Object" << r << "'s value is: " << objlist[r]->getvalue() << endl;                           }                       }                       CObjectManager::CObjectManager(){     cout << "CObjectManager created!" << endl;     }CObjectManager::~CObjectManager(){     cout << "CObjectManager deleted!" << endl;     }     // Notice the change in the function signaturevoid CObjectManager::addObject(CObject& obj){// Take address of the object     objlist.push_back(&obj);     cout << "CObject added! (" << obj.getvalue() << ")" << endl;     }     CObject CObjectManager::getobject(int index){// Dereference the pointer, this will make a copy.        return (*objlist[index]);}


All changes have been marked with a comment.

[Edited by - CTar on May 29, 2006 12:27:03 PM]
Quote:Original post by by
Thank you all, sometimes -like now- i love gdnet much more :)

Unfortunately, my questions not ended :)

Not about actually main topic but i dont know: has c/c++ got garbage collector?
for(int r = 0; r<5000; r++)
{
double r1;
}


---

what must i do for vector to don't copy objects, just point them ?



First, C and C++ have no inherent garbage collector. In general, YOU are responsible for memory allocations AND deallocations.

Second, I recommend you change your vector to store POINTERS to CObjects. That way, you can allocate CObjects, add them to your CObjectManager's vector, and not worry about the vector making a copy of the object. However, and this is very, very, very important... You MUST make sure you deallocate each CObject you create on the heap yourself. For example, in your CObjectManager's destructor, you could loop over your (via a for loop, or even better, via an iterator) objlist, and call delete on each item in the list.

Hope this helps!
Quote:Original post by by
Thank you all, sometimes -like now- i love gdnet much more :)

Unfortunately, my questions not ended :)

Not about actually main topic but i dont know: has c/c++ got garbage collector?
for(int r = 0; r<5000; r++)
{
double r1;
}


---

what must i do for vector to don't copy objects, just point them ?



First, C and C++ have no inherent garbage collector. In general, YOU are responsible for memory allocations AND deallocations.

Second, I recommend you change your vector to store POINTERS to CObjects. That way, you can allocate CObjects, add them to your CObjectManager's vector, and not worry about the vector making a copy of the object. However, and this is very, very, very important... You MUST make sure you deallocate each CObject you create on the heap yourself. For example, in your CObjectManager's destructor, you could loop over your (via a for loop, or even better, via an iterator) objlist, and call delete on each item in the list.

Hope this helps!
Wow! The servers are really messed up right now... Sorry for the double post!
my code now looks like this:

int main(int argc, char *argv[]){    CObjectManager *man = new CObjectManager;    CObject        *obj = new CObject(17);    CObject        *obj2 = new CObject(21);    cout << 0 << endl;    man->addObject(*obj);        cout << 1 << endl;    man->addObject(*obj2);    cout << 2 << endl;    man->update();    cout << 3 << endl;    delete obj;    delete obj2;    cout << 4 << endl;    system("PAUSE");    return EXIT_SUCCESS;}


changed vector line:
vector<CObject*> objlist;


another change:
void CObjectManager::update(){                       for (int r=0; r<objlist.size(); r++){                           cout << "Object" << r << "'s value is: " << objlist[r]->getvalue() << endl;                           }                       }


output:
CObjectManager created!
CObject created! (17)
CObject created! (21)
0
CObject added! (17)
CObject deleted! (17)
1
CObject added! (21)
CObject deleted! (21)
2
Object0's value is: 21
Object1's value is: 21
3
CObject deleted! (17)
CObject deleted! (21)
4
Press any key to continue . . .

as you can see two "21"s. i am not good with pointers so please forgive if i am doing something stupid :)
man->addObject(*obj);
cout addObject(*obj2);

you are still passing by value, pass by reference instead.

man->addObject(obj);
cout addObject(obj2);

This topic is closed to new replies.

Advertisement