vector storing inherited classes

Pages: 12
Hello everybody,
I was wondering if there is any way to store inherited classes in a vector object. I want to use only one vector, if possible, to store different classes that are inherited by a base class. I tryed the following code but it is lossing data that are stored in the inherited class but they are not declared in the base class.
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
#include <iostream>
#include <vector>
using namespace std;

class base{
public:
   virtual int show(){return 0;}
   virtual void store(int a){};
};
class inheri: public base{
   int test;
public:
   void store(int a){
      test = a;
   }
   int show(){
      return test;
   }
};
int main(){
   vector<base> viktoras;
   inheri taksh;
   taksh.store(4);
   viktoras.push_back(taksh);
   cout << viktoras[0].show();
   return 0;
}


Thanx in advance.
Last edited on
The way to do this would be with a vector of base pointers. That way, you can use dynamic_cast to cast those pointers back as an inheri before calling the show() function. Here's a modified main().


int main(){
vector<base*> viktoras;
inheri* taksh = new inheri();
taksh->store(4);
viktoras.push_back(taksh);
cout << (dynamic_cast <inheri*> (viktoras[0]))->show();
return 0;
}
Above solution is correct, but if you are using it in some project, then take care of deleting the memory allocated through these new operator. Other wise it will cause memory leak.
I'm also trying to do something similar. I also am trying to create multiple inherited classes. So my main function would look something like

int main(){
vector<base*> viktoras;
inheri* taksh = new inheri();
taksh->store(4);
viktoras.push_back(taksh);

if (dynamic_cast <inheri*> (viktoras[0])) {
cout << (dynamic_cast <inheri*> (viktoras[0]))->show();
} else if (dynamic_cast <inheri2*> (viktoras[0])) {
cout << (dynamic_cast <inheri2*> (viktoras[0]))->show();
}

// do something else
// call another subclass dependent method

if (dynamic_cast <inheri*> (viktoras[0])) {
(dynamic_cast <inheri*> (viktoras[0]))->store(4);
} else if (dynamic_cast <inheri2*> (viktoras[0])) {
(dynamic_cast <inheri2*> (viktoras[0]))->store(4);
}

return 0;
}

Where inheri2 is another subclass of "base".
As you can see, with every additional method and every additional subclass, this starts to get really messy. So in short, is there any way to make this cleaner???
Last edited on
Look at this thread :

http://www.devmaster.net/forums/archive/index.php/t-4054.html

It is quite helpful.

int main
Thanx guys, that helped alot.
Ok, I tryed this but i have a problem storing multiple instances of the same inherited class. The vector holds the place in memory a store the last inherited class, so I have an array full of pointers that point to the same position.
Is there any way to store the actual data in the vector?

I used this code:
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
#include <iostream>
#include <vector>
using namespace std;

class base{
public:
   virtual int show(){return 0;}
   virtual void store(int a){};
};
class inheri: public base{
   int test;
public:
   void store(int a){
      test = a;
   }
      int show(){
      return test;
   }
};
int main(){
   vector<base*> viktoras;
   inheri* taksh = new inheri();
   taksh->store(4);
   viktoras.push_back(taksh);
   delete taksh;
   taksh = new inheri();
   taksh->store(6);
   viktoras.push_back(taksh);
   //delete taksh;
   cout << (dynamic_cast <inheri*> (viktoras[0]))->show();
   return 0;
}
Your code putting the taksh instances into the vector is fine, apart from the delete on line 25. This will make the pointer you have just put in the vector point to nothing because you are deleting it. The push_back() is only taking a copy of the pointer, not the instance it is pointing to. You also have a problem with the cout. I suspect this code has been modified a bit while you try to find the problem, but in case it isn't;
You are only displaying the first one in position zero. You need something like the following

1
2
3
4
5
6

for (int i = 0; i < viktoras.size(); i++)
{
   cout << (dynamic_cast <inheri*> (viktoras[i]))->show();
}


Also don't forget to delete the pointers in the vector, after you have finished with them.

WinXp sp2 + VC++6.0 pass
The code had showed that just have 1 element!
Why have this result?
I think it have 2 element!

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

/********************************************************************
	created:	2008/07/03
	created:	3:7:2008   21:29
	filename: 	E:\CODING\CPP_Vector\CPP_Vector.cpp
	file path:	E:\CODING\CPP_Vector
	file base:	CPP_Vector
	file ext:	cpp
	author:		hecan
	
	purpose:
	///////////////===WinXp sp2 + VC++6.0  pass===/////////////////	
	the result:	
	vector only has 1 element!
*********************************************************************/

#include <iostream>
#include <vector>
using namespace std;

class base{
public:
	virtual int show(){return 0;}
	virtual void store(int a){};
};

class inheri: public base{
	int test;
public:
	void store(int a){
		test = a;
	}
	int show(){
		return test;
	}
};
int main(){
	vector<base*> viktoras;
	inheri* taksh = new inheri();
	taksh->store(4);
	viktoras.push_back(taksh);
	delete taksh;
	taksh = new inheri();
	taksh->store(6);
	viktoras.push_back(taksh);
	//delete taksh;
	viktoras.erase(viktoras.begin());

	cout << "The vector's size: " << viktoras.size() <<endl;
	cout << "The vector's element: " <<endl;
		for (vector<base*>::iterator vb_Iter = viktoras.begin(); vb_Iter != viktoras.end(); ++vb_Iter)
		{
 		cout <<  (*vb_Iter)->show() << endl;
		}

		//delete all the heap memory
		for (vector<base*>::iterator vb_Iter2 = viktoras.begin(); vb_Iter2 != viktoras.end(); ++vb_Iter2)
		{
			delete  (*vb_Iter2);
		}

// cout << (dynamic_cast <inheri*> (viktoras[1]))->show();
// 		cout << ( (viktoras[0]))->show();
	
//	delete taksh;
	return 0;
}
I know the reason!
This code is added by me!
viktoras.erase(viktoras.begin());


if I didn't erase the element, the viktoras's first element is a pointer which point a memory ,but the memory had been freed!So
cout << (*vb_Iter)->show() << endl;
is dangerous!

This will make the pointer you have just put in the vector point to nothing because you are deleting it.


Not point to nothing,It still point that original area,but that area had been freed!
I just used the (viktoras[0]))->show(); because i wanted to test the vector if it keeps the first results.

What I want to do is save several instances of inherited classes.
For exaple, to save 2 inheri type in the vector and the same time to keep the ability of storing other type of inherited classes also.
If I don't delete the pointer then I can't create a completly new instance of the same class...

(Inherited and Derived is the same thing, right? if not, i mean derived classes...)
Last edited on
What I want to do is save several instances of inherited classes.

You can see the code :
base * and inherited * are all stored in the vector!

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
/********************************************************************
	created:	2008/07/03
	created:	3:7:2008   21:29
	filename: 	E:\CODING\CPP_Vector\CPP_Vector.cpp
	file path:	E:\CODING\CPP_Vector
	file base:	CPP_Vector
	file ext:	cpp
	author:		hecan
	
	purpose:
	///////////////===WinXp sp2 + VC++6.0  pass===/////////////////	
	the result:	
	vector only has 2 element!
*********************************************************************/

#include <iostream>
#include <vector>
using namespace std;

class base{
public:
	base(){}
	virtual int show(){return 0;}
	virtual void store(int a){};
};

class inheri: public base{
	int test;
public:
	void store(int a){
		test = a;
	}
	int show(){
		return test;
	}
};
int main(){
	vector<base*> viktoras;
	inheri* taksh = new inheri();
	taksh->store(4);
	viktoras.push_back(taksh);
	delete taksh;
	taksh = new inheri();
	taksh->store(6);
	viktoras.push_back(taksh);

	base *taksh2 = new base();
	viktoras.push_back(taksh2);
	//delete taksh;
	viktoras.erase(viktoras.begin());

	cout << "The vector's size: " << viktoras.size() <<endl;
	cout << "The vector's element: " <<endl;
		for (vector<base*>::iterator vb_Iter = viktoras.begin(); vb_Iter != viktoras.end(); ++vb_Iter)
		{
 		cout <<  (*vb_Iter)->show() << endl;
		}

		//delete all the heap memory
		for (vector<base*>::iterator vb_Iter2 = viktoras.begin(); vb_Iter2 != viktoras.end(); ++vb_Iter2)
		{
			delete  (*vb_Iter2);
		}

// cout << (dynamic_cast <inheri*> (viktoras[1]))->show();
// 		cout << ( (viktoras[0]))->show();
	
//	delete taksh;
	return 0;
}
base * and inherited * are all stored in the vector!

Yes, I can see that both base and inherited are stored, but you are losing the first value (taksh->store(4);)... You don't have the inheri with the value of 4 any more.
I want to store uknown number of instances of the inheri class...
And the same time be able to store a base class also...
Okay, Okay...
From what I gather, lines 42 and 50 were introduces a while ago to show how to properly delete/remove items from the vector. Delete these two lines and you'll get you first item back.

This also leads me to believe that line 62 is not safe alone. Not sure.

The real question is how do you want to populate the vector.
Here is one way to achieve populating the vector based on keyboard input.

vector<base*> viktoras;
int num;
cin >> num;
while(num != 0) {
if(num = 1) {
inheri* taksh = new inheri();
viktoras.push_back(taksh2)
} else if(num = 2) {
base* taksh = new base();
viktoras.push_back(taksh2)
}
cin >> num;
}

Oh ya, and can someone tell me how to post with that neat looking text I see above.
Last edited on
Ok, i found it. I used viktor.push_back(new derived1()); to create new pointer every time i push a new object.

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
#include <iostream>
#include <vector>
using namespace std;

class base{
public:
   virtual void view()=0;
   virtual void store(int){};
   virtual void store(int, int){};
};

class derived1 : public base{
   int num;
public:
   void view(){
      cout << num << '\n';
   }
   void store(int i){
      num = i;
   }
};

class derived2 : public base{
   int num;
   int num2;
public:
   void view(){
      cout << num << ',' << num2 <<'\n';
   }
   void store(int i, int x){
      num = i;
      num2 = x;
   }
};

int main(){
   vector<base *> viktor;
   //push data
   viktor.push_back(new derived1());
   viktor[0]->store(4);
   viktor.push_back(new derived1());
   viktor[1]->store(6);
   viktor.push_back(new derived2());
   viktor[2]->store(3,1);
   viktor.push_back(new derived2());
   viktor[3]->store(7,9);
   //display
   for(unsigned i=0; i<viktor.size(); i++){
      viktor[i]->view();
   }
}


Thank you everybody for the help.
Last edited on

The memory had been leaked!
What do you mean by "The memory had been leaked!" ?
When you do a new or a malloc, you take memory off the heap. While that memory is allocated, you should always keep a pointer to the allocated region in scope. Once you have finished with it call delete or free. If you loose the pointer before it is released, that memory is completely lost for the duration of the programs execution, i.e. in software speak, it has leaked away; a memory leak.
Pages: 12