By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
455,906 Members | 1,384 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 455,906 IT Pros & Developers. It's quick & easy.

simple question about containers

P: n/a
I was wondering if there is a container (i.e. a vector) that can hold
data structures of differing sizes. I was thinking of something along
the lines of a container of classes. Think of a backpack you can take
items from and put items into of different sizes.

The reason I want to know is I am about to try my hands at learning
classes and need to do it in a way I can grasp - ala gaming concepts
(see inventory example above.)

Thanks in advance.
May 24 '07 #1
Share this Question
Share on Google+
8 Replies


P: n/a
Devon Null wrote:
I was wondering if there is a container (i.e. a vector) that can hold
data structures of differing sizes. I was thinking of something along
the lines of a container of classes. Think of a backpack you can take
items from and put items into of different sizes.

The reason I want to know is I am about to try my hands at learning
classes and need to do it in a way I can grasp - ala gaming concepts
(see inventory example above.)
Hold smart pointers to your 'data structures of differing sizes'
inside the container (e.g. vector) and the problem disappears.

HTH,
- J.
May 24 '07 #2

P: n/a
Devon Null <th*************@gmail.comwrote:
I was wondering if there is a container (i.e. a vector) that can hold
data structures of differing sizes. I was thinking of something along
the lines of a container of classes. Think of a backpack you can take
items from and put items into of different sizes.
Not directly: the standard containers must have homogeneous contents.
However, one technique around this is if all the items derive from a
common base class, then you can store base-pointers in the container, at
which point the base-pointers can point to the derived objects.
However, this introduce lifetime management issues. Smart pointers can
help in that situation (but not std::auto_ptr, which does not fulfill
the container requirements). Some libraries also have their own version
of a pointer_vector or whatever.

--
Marcus Kwok
Replace 'invalid' with 'net' to reply
May 24 '07 #3

P: n/a
On May 24, 12:30 pm, Devon Null <theronnights...@gmail.comwrote:
I was wondering if there is a container (i.e. a vector) that can hold
data structures of differing sizes. I was thinking of something along
the lines of a container of classes. Think of a backpack you can take
items from and put items into of different sizes.

The reason I want to know is I am about to try my hands at learning
classes and need to do it in a way I can grasp - ala gaming concepts
(see inventory example above.)

Thanks in advance.

The backpack isn't storing the specifications of each item.
It simply stores objects, not classes.
It can also store base pointers to derived entities (which is what you
are looking for).
Assuming you have some form of inheritance hierarchy:

class Item {
virtual ~Item() = 0;
};

Item::~Item() { }

class Weapon : public Item { };

class Potion : public Item { };

int main()
{
// Item item; // error, Item is abstract
Weapon weapon;
Potion potion;
std::vector< Base* inventory;
inventory.push_back( &weapon );
inventory.push_back( &potion );
}

I'ld suggest keeping the base class abstract.
Types Weapon and Potion have their own specific attributes and their
own specific member functions.

Once you are comfortable with such a scenario, do look into smart
pointers (ie: boost:shared_ptr).
Otherwise, you'll need to manage the lifetime of those Items.
May 24 '07 #4

P: n/a
On May 24, 12:30 pm, Devon Null <theronnights...@gmail.comwrote:
I was wondering if there is a container (i.e. a vector) that can hold
data structures of differing sizes. I was thinking of something along
the lines of a container of classes. Think of a backpack you can take
items from and put items into of different sizes.

The reason I want to know is I am about to try my hands at learning
classes and need to do it in a way I can grasp - ala gaming concepts
(see inventory example above.)

Thanks in advance.

The backpack isn't storing the specifications of each item.
It simply stores objects, not classes.
It can also store base pointers to derived entities (which is what you
are looking for).
Assuming you have some form of inheritance hierarchy:

class Item {
virtual ~Item() = 0;

};

Item::~Item() { }

class Weapon : public Item { };

class Potion : public Item { };

int main()
{
// Item item; // error, Item is abstract
Weapon weapon;
Potion potion;
std::vector< Item* inventory;
inventory.push_back( &weapon );
inventory.push_back( &potion );

}

I'ld suggest keeping the base class abstract.
Types Weapon and Potion have their own specific attributes and their
own specific member functions.

Once you are comfortable with such a scenario, do look into smart
pointers (ie: boost:shared_ptr).
Otherwise, you'll need to manage the lifetime of those Items.
May 24 '07 #5

P: n/a
Salt_Peter wrote:
On May 24, 12:30 pm, Devon Null <theronnights...@gmail.comwrote:
>I was wondering if there is a container (i.e. a vector) that can hold
data structures of differing sizes. I was thinking of something along
the lines of a container of classes. Think of a backpack you can take
items from and put items into of different sizes.

The reason I want to know is I am about to try my hands at learning
classes and need to do it in a way I can grasp - ala gaming concepts
(see inventory example above.)

Thanks in advance.


The backpack isn't storing the specifications of each item.
It simply stores objects, not classes.
It can also store base pointers to derived entities (which is what you
are looking for).
Assuming you have some form of inheritance hierarchy:

class Item {
virtual ~Item() = 0;
};

Item::~Item() { }

class Weapon : public Item { };

class Potion : public Item { };

int main()
{
// Item item; // error, Item is abstract
Weapon weapon;
Potion potion;
std::vector< Base* inventory;
inventory.push_back( &weapon );
inventory.push_back( &potion );
}

I'ld suggest keeping the base class abstract.
Types Weapon and Potion have their own specific attributes and their
own specific member functions.

Once you are comfortable with such a scenario, do look into smart
pointers (ie: boost:shared_ptr).
Otherwise, you'll need to manage the lifetime of those Items.

Took me a second but I think I see what is going on here with the base
class. I can see where that could be a nightmare in maintenance.I
grabbed a couple of .h files from http://ootips.org/yonat/4dev/ that
should help.

Another question - say I was to use this example, would my class
declarations go inside the braces in the statement

class Weapon : public Item { /*in here?*/ }; ?

Like I said, I am actually just about to jump into classes. I also
assume that I would do that for any class inheriting the public parts of
class Item (i.e. any items).
May 24 '07 #6

P: n/a
On May 24, 1:48 pm, Devon Null <theronnights...@xgmailx.comwrote:
Salt_Peter wrote:
On May 24, 12:30 pm, Devon Null <theronnights...@gmail.comwrote:
I was wondering if there is a container (i.e. a vector) that can hold
data structures of differing sizes. I was thinking of something along
the lines of a container of classes. Think of a backpack you can take
items from and put items into of different sizes.
The reason I want to know is I am about to try my hands at learning
classes and need to do it in a way I can grasp - ala gaming concepts
(see inventory example above.)
Thanks in advance.
The backpack isn't storing the specifications of each item.
It simply stores objects, not classes.
It can also store base pointers to derived entities (which is what you
are looking for).
Assuming you have some form of inheritance hierarchy:
class Item {
virtual ~Item() = 0;
};
Item::~Item() { }
class Weapon : public Item { };
class Potion : public Item { };
int main()
{
// Item item; // error, Item is abstract
Weapon weapon;
Potion potion;
std::vector< Base* inventory;
inventory.push_back( &weapon );
inventory.push_back( &potion );
}
I'ld suggest keeping the base class abstract.
Types Weapon and Potion have their own specific attributes and their
own specific member functions.
Once you are comfortable with such a scenario, do look into smart
pointers (ie: boost:shared_ptr).
Otherwise, you'll need to manage the lifetime of those Items.

Took me a second but I think I see what is going on here with the base
class. I can see where that could be a nightmare in maintenance.I
grabbed a couple of .h files fromhttp://ootips.org/yonat/4dev/that
should help.
Consider using boost's shared_ptr instead
>
Another question - say I was to use this example, would my class
declarations go inside the braces in the statement

class Weapon : public Item { /*in here?*/ }; ?
yes, keep in mind that different parts of your hierarchy will have
their own attributes and responsabilities. Example: an AssaultRifle
is_a type of Weapon which is_a type of Item.
>
Like I said, I am actually just about to jump into classes. I also
assume that I would do that for any class inheriting the public parts of
class Item (i.e. any items).
Not really. Consider that all items have a weight/mass. Item's
derivatives need not handle that aspect so you'ld keep weight in Item,
no virtual getweight() function needed. Weapon might itself become a
base class for concrete weapons (ie, rifle, laser, grenade, etc). All
weapons can fire() but each weapon fires in its own way. A rifle might
have an ammo count. And so on. See if the code below clarifies some
issues, i'm completely ignoring the fact that an Item needs to be
loaded/equipped.

Note how lifetimes are greatly simplified by the use of
boost::shared_ptr.

#include <iostream>
#include <vector>
#include <string>
#include <boost/shared_ptr.hpp>

class Item {
double weight;
protected:
Item(double w = 0.0) : weight(w) { }
public:
~Item() { std::cout << "~Item()\n"; }
double getweight() const { return weight; }
virtual void use() = 0;
};

class Weapon : public Item
{
protected:
Weapon(double w = 0.0) : Item(w) { }
virtual void fire() = 0;
};

class AssaultRifle : public Weapon
{
int ammo;
public:
AssaultRifle(int a = 16) : Weapon(20.1), ammo(a)
{
std::cout << "AssaultRifle()\n";
}
~AssaultRifle() { std::cout << "~AssaultRifle()\n"; }
void use()
{
fire();
std::cout << "fired!, ammo left :" << ammo;
std::cout << std::endl;
}
private:
void fire() { --ammo; }
};

int main()
{
typedef boost::shared_ptr< Item SPtrItem;
std::vector< SPtrItem inventory;
inventory.push_back( SPtrItem( new AssaultRifle(32) ) );

std::cout << "inventory[0]'s weight is: ";
std::cout << inventory.at(0)->getweight();
std::cout << std::endl;

inventory.at(0)->use(); // universal Item user
}

/*
AssaultRifle()
inventory[0]'s weight is: 20.1
fired!, ammo left :31
~AssaultRifle()
~Item()
*/

May 24 '07 #7

P: n/a
On May 24, 6:30 pm, Devon Null <theronnights...@gmail.comwrote:
I was wondering if there is a container (i.e. a vector) that can hold
data structures of differing sizes. I was thinking of something along
the lines of a container of classes. Think of a backpack you can take
items from and put items into of different sizes.
The obvious answer is std::vector< boost::any >. Whether it is
the right answer will depend on your particular circumstances;
if you really need a container that 1) contains actual
objects (i.e. copies of what you insert), and 2) can contain
absolutely anything you throw at it, then this is probably the
only answer. Most of the time I've needed heterogenous
containers, however, the items in question have 1) been related
(and had a common base class), and 2) had identity (which means
that I don't want to copy them), so a container of pointers to
the base class was the answer.
The reason I want to know is I am about to try my hands at learning
classes and need to do it in a way I can grasp - ala gaming concepts
(see inventory example above.)
I'm not familiar enough with games programming to be sure, but I
suspect that the objects that you would put into a backpack
would have identity, so you don't want to deal with copies, only
the original. Also, I wouldn't be surprised if they had a
common base class: in the one game I'm fairly familiar with
(nethack), all objects, regardless of their category, have
weight, can be named, and listed, etc.---common functionality
which could reasonably be expected to be in a base class.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

May 25 '07 #8

P: n/a
Salt_Peter wrote:
On May 24, 1:48 pm, Devon Null <theronnights...@xgmailx.comwrote:
>Salt_Peter wrote:
>>On May 24, 12:30 pm, Devon Null <theronnights...@gmail.comwrote:
I was wondering if there is a container (i.e. a vector) that can hold
data structures of differing sizes. I was thinking of something along
the lines of a container of classes. Think of a backpack you can take
items from and put items into of different sizes.
The reason I want to know is I am about to try my hands at learning
classes and need to do it in a way I can grasp - ala gaming concepts
(see inventory example above.)
Thanks in advance.
The backpack isn't storing the specifications of each item.
It simply stores objects, not classes.
It can also store base pointers to derived entities (which is what you
are looking for).
Assuming you have some form of inheritance hierarchy:
class Item {
virtual ~Item() = 0;
};
Item::~Item() { }
class Weapon : public Item { };
class Potion : public Item { };
int main()
{
// Item item; // error, Item is abstract
Weapon weapon;
Potion potion;
std::vector< Base* inventory;
inventory.push_back( &weapon );
inventory.push_back( &potion );
}
I'ld suggest keeping the base class abstract.
Types Weapon and Potion have their own specific attributes and their
own specific member functions.
Once you are comfortable with such a scenario, do look into smart
pointers (ie: boost:shared_ptr).
Otherwise, you'll need to manage the lifetime of those Items.
Took me a second but I think I see what is going on here with the base
class. I can see where that could be a nightmare in maintenance.I
grabbed a couple of .h files fromhttp://ootips.org/yonat/4dev/that
should help.

Consider using boost's shared_ptr instead
>Another question - say I was to use this example, would my class
declarations go inside the braces in the statement

class Weapon : public Item { /*in here?*/ }; ?

yes, keep in mind that different parts of your hierarchy will have
their own attributes and responsabilities. Example: an AssaultRifle
is_a type of Weapon which is_a type of Item.
>Like I said, I am actually just about to jump into classes. I also
assume that I would do that for any class inheriting the public parts of
class Item (i.e. any items).

Not really. Consider that all items have a weight/mass. Item's
derivatives need not handle that aspect so you'ld keep weight in Item,
no virtual getweight() function needed. Weapon might itself become a
base class for concrete weapons (ie, rifle, laser, grenade, etc). All
weapons can fire() but each weapon fires in its own way. A rifle might
have an ammo count. And so on. See if the code below clarifies some
issues, i'm completely ignoring the fact that an Item needs to be
loaded/equipped.

Note how lifetimes are greatly simplified by the use of
boost::shared_ptr.

#include <iostream>
#include <vector>
#include <string>
#include <boost/shared_ptr.hpp>

class Item {
double weight;
protected:
Item(double w = 0.0) : weight(w) { }
public:
~Item() { std::cout << "~Item()\n"; }
double getweight() const { return weight; }
virtual void use() = 0;
};

class Weapon : public Item
{
protected:
Weapon(double w = 0.0) : Item(w) { }
virtual void fire() = 0;
};

class AssaultRifle : public Weapon
{
int ammo;
public:
AssaultRifle(int a = 16) : Weapon(20.1), ammo(a)
{
std::cout << "AssaultRifle()\n";
}
~AssaultRifle() { std::cout << "~AssaultRifle()\n"; }
void use()
{
fire();
std::cout << "fired!, ammo left :" << ammo;
std::cout << std::endl;
}
private:
void fire() { --ammo; }
};

int main()
{
typedef boost::shared_ptr< Item SPtrItem;
std::vector< SPtrItem inventory;
inventory.push_back( SPtrItem( new AssaultRifle(32) ) );

std::cout << "inventory[0]'s weight is: ";
std::cout << inventory.at(0)->getweight();
std::cout << std::endl;

inventory.at(0)->use(); // universal Item user
}

/*
AssaultRifle()
inventory[0]'s weight is: 20.1
fired!, ammo left :31
~AssaultRifle()
~Item()
*/
That's gonna take me a minute to sort out. I'll have to definitely
study that. Thanks for the example. It gives me something concrete to
see and understand just how it works. I haven't gotten to inheritance in
the book I am reading yet - Beginning C++ Through Game Programming SE -
but this will go miles in helping me to understand.
May 25 '07 #9

This discussion thread is closed

Replies have been disabled for this discussion.