Sign in to follow this  

vectors and containers?

This topic is 4843 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Was wondering if someone could show me how to do this in C++ I have an abstract base class and n child classes.

class CBase { 
public:
  int i = 0;
  virtual void process() = 0;
  virtual void clean() = 0;
  virtual void add() = 0;
};

class CChild1 : public CBase {
 void process() {
  cout << "child 1" << endl;
 }

 void add() {
  i+=1;
 }

 void clean() {
  cout << "cleaning child 1" << endl;
 }
};

class CChild2 : public CBase {
 void process() {
  cout << "child 2" << endl;
 }
 
 void sum() {
  i+=2;
 }

 void clean() {
  cout << "cleaning child 2" << endl;
 } 
}






Each of these child classes would be created on the fly and managed by another class. Something like this,

class CManager {
public:
 std::vector <CBase*> refs;
 
 // basically want the add method to accept a class,
 // then instanciate that class and wack it into the vector
 CBase* push(CBase classIn) {
  // something or other here for this method.
 }

 void update {
  // iterate through vector and call each objects process...
  for (unsigned int n=0; n < refs.size(); n++)
   refs[n]->process();
 }

 void remove{
  // iterate through the vector and delete all objects...
  for (unsigned int n=0; n < refs.size(); n++)
   refs[n]->clean();

 CManager::~CManager() {
   remove();
 }
}

};





Somewhere else in code i would just like to have a global CManager instance. then i can just push children into this manager class something like this (if possible)

CManager* gManager = new CManager();

// returns a pointer to the object in vector
CBase* base1 = gManager->push(CChild1());
CBase* base2 = gManager->push(CChild2());

base1->sum();
base2->sum();

// .. and so on

and then.

gManager->update();





[Edited by - lubby on September 12, 2004 6:13:10 PM]

Share this post


Link to post
Share on other sites
You could use an Object Factory to create those objects. There are plenty of resources available on the topic, so I won't duplicate them here.

Otherwise, the simplest method is to just call new and pass the pointer to your push member function.

If you don't want to do that, you may create a templated member function:

class CManager
{
...

template<class T> void push()
{
this->push(new T);
}
};


And do gManager->push<CChild1>();


Note that your code is riddled with errors (copy-paste errors, lack of virtual destructor in CBase, 'delete' member function, non-friend accessing protected members ) ...

Share this post


Link to post
Share on other sites
Quote:
Original post by Fruny

Otherwise, the simplest method is to just call new and pass the pointer to your push member function. ...


Thanks for your input Fruny, i fixed some of the errors you mentioned, although this is not final code by any means.

Is this the most efficient way to do this? I have read some messages about STL performance issues, and would like to do this as cheaply as possible.

I dont want to call new and pass the pointer, i would like to keep all of the object creation / deletion inside the CManager class.

[Edited by - lubby on September 12, 2004 6:07:59 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by lubby
Thanks for your input Fruny. Could you tell me how i return a pointer to the object then contained in the vector? (when use the templated member function you described.


You shouldn't have to. The pointer is now "in the container", so you ought to access it via the container (e.g. refs.back()). Otherwise, I guess you can do


template<class T>
T* push()
{
T* ptr = new T;
refs.push_back(ptr);
return ptr;
}


Quote:
Is this the most efficient way to do this? I have read some messages about STL performance issues, and would like to do this as cheaply as possible.


Most people who complain about STL performance problems don't know what they are talking about. The few that do have valid complaints about the generic allocation routines should learn to write their own allocators.

If you want more information you will have to tell me precisely what "this" refers to in "Is this the most efficient way to do this?"

Quote:
I dont want to call new and pass the pointer, i would like to keep all of the object creation / deletion inside the CManager class.


Then you want an object factory. Look it up. There are plenty of examples both on gamedev.net and on the web at large. I consider the solution I gave you as a stopgap measure that should not be used in place of proper design - in fact, it really is not that different from actually creating a pointer externally and passing it to the CManager object, especially since you insisted (in your last question) that the pointer be available as a return value from push(). [rolleyes]

Share this post


Link to post
Share on other sites
The reason I want a pointer returned is that I will need random access to the inserted object outside of the container. ie.


CBase* foo = gManager->push<CChild1>();
CBase* bar = gManager->push<CChild3>();
// ... lala

foo->sum();
bar->sum();
foo->sum();
// and so on...



CManager would iterate through and call update when needed

When i say "Is this the most efficient way to do this?" I refer to the quickest way to create and instert the object into CManager's vector. It is likely the CManager::push() method will be called hundreds of time per second.

I will look into the object factory, thanks for your time so far, most helpfull :)

Share this post


Link to post
Share on other sites
Quote:
Original post by lubby
The reason I want a pointer returned is that I will need random access to the inserted object outside of the container.


std::vector does already provide random access.

Quote:
When i say "Is this the most efficient way to do this?" I refer to the quickest way to create and instert the object into CManager's vector. It is likely the CManager::push() method will be called hundreds of time per second.


True, but CManager::push() is not a STL function. std::vector::push_back is.

Share this post


Link to post
Share on other sites
Quote:

True, but CManager::push() is not a STL function. std::vector::push_back is.


I realise this, I used push in CManager for lack of a better name, to avoid confusion lets pretend its CManager::add() instead.

Some other class, CSomething would use the global CManager to add an object to the CManager::refs vector through CManager::add()

I want the pointer to the instance created within CManager::add() returned to the CSomething object.


CSomething::CBase* pTemp = gManager->add<CChild1>();



Then at another time in CSomething I can do the following,
(using the temp pointer to access to the inserted object.)


CSomething::pTemp->sum();



If I were not to return the pointer to the instanciated CChild() class I would not know which object I wanted to call sum on, from within CSomething(). I figure that the only way i can do this is by having a pointer to the inserted object.

At least this is how I envision the best way to have direct access to the newly inserted object. Please correct me if I am wrong, or there is a more efficient/obvious way to do so.

Note that I then call per frame gManager->update() to iterate through all inserted objects in the vector and call the update method, hence accessing them in CManager.

Share this post


Link to post
Share on other sites

This topic is 4843 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this