Container to store Different Object Types

I was wandering if I could get the opinion of someone who might know which is the best container from the STL to use that meets the following requirements:

1. It needs to be able to store objects of different types but all derived from the same base class. An example would be Item->Weapon->Club where Item is the base class which is being store in the container. In this case the container would not have issues with different types of weapons OR items (Such as potion) being added.

2. I need to be able to know the type of a given element during run time. For example it would need to know that element 1 stored a club whereas element 2 stored a bow.

I am also interested in ways around point number two. I know that I could add the functions in the base class so as to make it a common interface but it becomes hard when you have multiple inheritance as far as I can see. Would a linked list be okay to do this with? I have been trying to do it with a linked list but am having some issues.
I would use a vector of pointers-to-Item.

The Wiki page http://en.wikipedia.org/wiki/Run-time_type_information gives an example of determing what kind of object the pointers-to-base actually point to, although I'd be tempted to outright store that information in the object.

Read this: http://devmaster.net/forums/topic/3065-c-store-objects-of-different-type-in-the-same-vector-of-other-container/
Last edited on
I would use std::vector<std::unique_ptr<Item>> or boost::ptr_vector<Item>
According to what you have described you would have a abstract base class and a number of different classes that inherit from this abstract base class. You then create a container for this abstract class which can then conatin any type derived from your base class. When you iterate through your container you determine at runtime what each instance in the container is.

As for which type of container you need, is determined on what you are doing with it, if you just need a conatiner a vector will suffice, or if you need to access a specific instance from the container then a map might be suitable; a map stores instances with a unique key and you access the instance from the may via the key.

Hopefully the following code will show you what I am describing. [I am using a vector as a container of my different types]:

header file:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
// Item.h

#include <vector>

class CItem
{
public:
	CItem();
	virtual ~CItem();

	virtual void Foo() = 0;

protected:

};

class CWeapon : public CItem
{
public:
	CWeapon();
	virtual ~CWeapon();

	virtual void Foo();

protected:

};

class CClub : public CWeapon
{
public:
	CClub();
	virtual ~CClub();

protected:

};


class CPotion : public CItem
{
public:
	CPotion();
	virtual ~CPotion();

	virtual void Foo();

protected:

};

class CApp
{
public:
	CApp();
	virtual ~CApp();

	void run();

private:
	typedef std::vector<CItem*> VITEM;

	VITEM m_vec;
};


source file:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108

#include <stdio.h>
#include "Item.h"

using namespace std;

CItem::CItem()
{
}

CItem::~CItem()
{
}

CWeapon::CWeapon()
	: CItem()
{
}

CWeapon::~CWeapon()
{
}

void CWeapon::Foo()
{
}

CClub::CClub()
	: CWeapon()
{
}

CClub::~CClub()
{
}

CPotion::CPotion()
	: CItem()
{
}

CPotion::~CPotion()
{
}

void CPotion::Foo()
{
}

CApp::CApp()
{
}

CApp::~CApp()
{
	for (VITEM::iterator p = m_vec.begin(); p != m_vec.end(); ++p)
	{
		delete *p;
		*p = NULL;
	}
}

void CApp::run()
{
	// create some instances of various types and add to vector:
	for (int n = 0; n < 10; ++n)
	{
		if (n % 2)
			m_vec.push_back(new CWeapon());
		else
		{
			if (n == 3)
				m_vec.push_back(new CClub());
			else
				m_vec.push_back(new CPotion());
		}
	}

	// iterate through vector and determine 
	// which type of object we are dealing with:
	for (VITEM::iterator p = m_vec.begin(); p != m_vec.end(); ++p)
	{
		CWeapon* pWeapon = dynamic_cast<CWeapon*>(*p);
		CClub* pClub = dynamic_cast<CClub*>(*p);
		CPotion* pPotion = dynamic_cast<CPotion*>(*p);

		if (pWeapon)
		{
			// do stuff with weapon...
		}
		else if (pClub)
		{
			// do stuff with club...
		}
		else if (pPotion)
		{
			// do stuff with potion...
		}
	}
}

int main()
{
	CApp app;
	app.run();

	return 0;
}
The Wiki page http://en.wikipedia.org/wiki/Run-time_type_information gives an example of determing what kind of object the pointers-to-base actually point to, although I'd be tempted to outright store that information in the object.


Is that a type of Reflection?
Topic archived. No new replies allowed.