Can someone please explain this pointer line to me?

I was making a vector inventory program and ran across an issue, since I needed to display the get function of a child class from the parent class (as you can see in the code). Thing is, I was able to assign a Weapon object (the child) to the vector of Item objects (the parent), but the members of Weapon are not accessible from the vector pointer of Item.

Thus, I looked up a way on how to do it and this line is what I got:

1
2
Weapon *weap=(Weapon *)items[i];
cout<<weap->getAttack()<<endl;


It works, but I don't understand that first line. I understand we are declaring a pointer to a Weapon object, but I don't understand what it is being equalized to. (Weapon *)items[i]; lost me.

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
class Item
{
	protected:
		string type;
		string name;
	public:
		Item()
		{ type=name="Empty"; }
		Item(string t,string n)
		{
			type=t;
			name=n;
		}

		string getType() const
		{ return type; }
		string getName() const
		{ return name; }
};

class Weapon:public Item
{
	protected:
		int attack;
	public:
		 Weapon()
		{ attack=0; }
		 Weapon(int a)
		{ attack=a; }
		 Weapon(string t, string n, int a):Item(t,n)
		 { attack=a; }

		void setAttack(int a)
		{ attack=a; }

		int getAttack()
		{ return attack; }
};

class Armor:public Item
{
	protected:
		int defense;
	public:
		Armor()
		{ defense=0; }
		Armor(int d)
		{ defense=d; }
		Armor(string t, string n, int d):Item(t,n)
		{ defense=d; }

		int getDef()
		{ return defense; }
};

int main()
{
	const int NUM=5;

	int itemCount=0;

	vector<Item *> items;

	items.push_back(new Weapon("Weapon","Broadsword",50));
	itemCount++;
 	items.push_back(new Armor("Armor","Platemail",200));
	itemCount++;

	for(int i=0;i<itemCount;i++)
	{
		cout<<items[i]->getName()<<endl;
		cout<<items[i]->getType()<<endl;
		if(items[i]->getType()=="Weapon")
		{
                        //This line here...
			Weapon *weap=(Weapon *)items[i];
			cout<<weap->getAttack()<<endl;
			cout<<endl; //Also how do I endl twice so that I don't have to do this?
		}
		else if(items[i]->getType()=="Armor")
		{
                        //And this one
			Armor *armor=(Armor *)items[i];
			cout<<armor->getDef()<<endl;
                        cout<<endl;
	}

	return 0;
}


I just want to know how it works, so that I can make better use of it in the future.
Last edited on
closed account (o3hC5Di1)
Hi there,

You are making use of polymorphism. This link explains it better than I could: http://www.cplusplus.com/doc/tutorial/polymorphism/

As for your issue, if you want to be able to call functions defined in a derived class through a bass class pointer, you need to declare them as virtual in your 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
class Item
{
	protected:
		string type;
		string name;
	public:
		Item()
		{ type=name="Empty"; }
		Item(string t,string n)
		{
			type=t;
			name=n;
		}

		virtual string getType() const
		{ return type; }
		virtual string getName() const
		{ return name; }
};

class my_item : public Item
{
    public:
        string getType() const
        { return Item::getType().append(" from derived class"); }
}
//Now you can call getType() from a pointer to Item pointing to a my_item object and it will call my_item::getType. 


Note that you can't call functions undefined in the base class from a base class pointer, so getDef(), getAttack() etc. will not work, because the are not implemented in the base class.

Hope that helps, please do let us know if you have any further questions.

All the best,
NwN
Last edited on
The vector contains pointers. You tell that a pointer is converted from one that points to an Item to one that points to a Weapon. You overrule the compiler here; it cannot ensure that the memory location really contains the data of a Weapon.

Overall, why cannot each Item have both attack and defense?


That is a C-style cast. C++ has different syntax.

You could do instead:
1
2
Weapon *weap =dynamic_cast<Weapon *>( items[i] );
if ( weap ) ...



1
2
3
4
5
cout << "\n\n";
// or
cout << endl << endl;
// or
cout << '\n' << endl;
Yeah the issue is that my real program (this is just to show the example) has much more variables. If i were to assign every single one to Item I would end up having potions with defense and attack variables, weapons with defense and heal, etc

I opted for derived functions.

Also, thank you both for the help, and that link is very helpful.

Edit: Thanks again NwN! That page completely resolved my issues, the suggestion to switch to virtual functions helped as well
Last edited on
Topic archived. No new replies allowed.