Reputation: 311
So I'm currently working on a little summer project here -- a text-based RPG (I know -- how original!). Anyways, I've run into an issue. I want to have an inventory class for my character, which contains an array of pointers to different items. The issue is that these items will be of many different class types in themselves (weapon, quest, misc., etc.). So I'm wondering if there's a way that I can make a pointer that can switch between types? Or is my thinking completely wrong? Thanks. --Simon Ward
Upvotes: 0
Views: 602
Reputation: 2343
I know that you can solve your problem by using Object Oriented Programming
as 3 answers of Kenny Castro
, don bright
and cfillion
. However, void pointer
also is a solution. I know it is not a good idea but it also can solved your problem and I want introduce it for you. My demo code as follow:
#include<iostream>
using namespace std;
//assume you just have 3 item type
class A
{
public:
void func(){
cout<<"I am A object\n";
}
};
class B
{
public:
void func(){
cout<<"I am B object\n";
}
};
class C
{
public:
void func(){
cout<<"I am C object\n";
}
};
int main()
{
//assume that you have 5 items of three types
void* items[5];
char type[5]; //if items[i] is A object then type[i] = 'A'
//if items[i] is B object then type[i] = 'B'
//if items[i] is C object then type[i] = 'C'
//When you insert item into array, let's mark 'A', 'B', or 'C' for each item
items[0]=new A, type[0]='A';
items[1]=new B, type[1]='B';
items[2]=new C; type[2]='C';
items[3]=new B, type[3]='B';
items[4]=new A, type[4]='A';
for(int i=0;i<5;i++)
{
if(type[i]=='A'){
((A*)items[i])->func();
}
if(type[i]=='B'){
((B*)items[i])->func();
}
if(type[i]=='C'){
((C*)items[i])->func();
}
}
return 0;
}
OUTPUT:
I am A object
I am B object
I am C object
I am B object
I am A object
Upvotes: 1
Reputation: 1211
You could have a array (or std::vector) of type classX, now derive all carryable items from classX. See also Vector that can have 3 different data types C++ . Here is an extremely simplified example:
#include <string>
#include <vector>
#include <iostream>
class Carryable {
public:
virtual std::string info()=0;
};
class Potion: public Carryable {
public:
std::string name;
int mana;
std::string info() { return "potion - name["+name+\
"] mana["+std::to_string(mana) + "]"; };
};
class Book: public Carryable {
public:
std::string title;
std::string author;
std::string info() { return "book - title["+title+"] author["+author+"]"; };
};
main() {
std::vector<Carryable*> inventory;
Potion p;
p.name="Dragon breath";
p.mana=40;
inventory.push_back( &p );
Book b;
b.title="Wisdom of Chu";
b.author="Wen Chu";
inventory.push_back( &b );
for (int i=0;i<inventory.size();i++) {
std::cout << "inventory item " << i << ":";
std::cout << inventory[i]->info() << "\n";
}
}
output:
don@oysters:~/proj/src$ ./a.out
inventory item 0:potion - name[Dragon breath] mana[40]
inventory item 1:book - title[Wisdom of Chu] author[Wen Chu]
Upvotes: 1
Reputation: 121
Inheritance should work well for this. All you have to do is create one base class(parent class), that, for example a type(what type of class it is supposed to be-Weapon, quest, misc). Every itemType class will inherit from this parent class, and when you store all these items, you store them with the objectType as the parent class and then when you're reading an item, you look at it's type, cast it to the appropriate class type and then do what you need to with it.
class parentItem
{
public:
parentItem(string) : type(string) {};
string type; //Doesn't have to be a string, could be an enum or anything you want
}
class weapon : public parentItem
{
weapon() : parentItem("Weapon"){};
weaponInfo wInfo;
int damageDeals;
}
Then somewhere else in your code when you're accessing one of these from the inventory
parentItem item = player.getWeapon() // Just generic code, just grabbing the object
Weapon* sword;
if(parentItem.type = "Weapon")
{
sword = (Weapon*)item
}
sword->attack(); //or whatever you want to do with it
TLDR: Use inheritance on every item class so that they can all be considered 1 type and then cast them to the appropriate type when you need to access the information of the child class
Upvotes: 1
Reputation: 1398
If all your item classes inherit from a common ancestor (eg. an Item
class) you will be able to have a vector of Item *
. This can be a good time to use polymorphism as well:
#include <iostream>
#include <vector>
class Item {
public:
virtual const char *name() const = 0;
virtual void use() = 0;
};
class Knife : public Item {
public:
const char *name() const override { return "Knife"; }
void use() override { std::cout << "Using the knife" << std::endl; }
};
class Laser : public Item {
public:
const char *name() const override { return "Laser"; }
void use() override { std::cout << "Using the laser" << std::endl; }
};
int main() {
std::vector<std::unique_ptr<Item>> v;
v.emplace_back(std::make_unique<Knife>());
v.emplace_back(std::make_unique<Laser>());
for(const std::unique_ptr<Item> &i : v) {
std::cout << "Name: " << i->name() << std::endl;
i->use();
}
return 0;
}
Output:
$ c++ --std=c++14 m.cpp
Name: Knife
Using the knife
Name: Laser
Using the laser
Upvotes: 1