Setting value from Derivered class, while accesing same value from base class - c++

I am getting an issue for retrieving BaseClass correct enum value.
class BaseClass
{
public:
enum EntityId {
EN_NONE = 0,
EN_PLAYER = 1,
EN_PLATFORM,
EN_GROUND,
EN_OBSTACLE,
EN_OTHER
};
void setEntityId(EntityId id) { _Entityid = id; }
EntityId getEntityId() { return _Entityid; }
protected:
EntityId _Entityid;
};
and
class DeriveredClassA : public SomeClass, public BaseClass {....};
class DeriveredClassB : public SomeClass, public BaseClass {....};
The initialization goes like this
DeriveredClassA->setEntityId(BaseClass::EntityId::EN_PLAYER);
DeriveredClassB->setEntityId(BaseClass::EntityId::EN_OBSTACLE);
Which is placed into a different vector list correspoinding to that enum.
However, I am forced to use void* to do static_casts cats...
Like this:
BaseClass* EA = static_cast<BaseClass*>(bodyUserDataA); //bodyUserDataA and bodyUserDataB are both void*
BaseClass* EB = static_cast<BaseClass*>(bodyUserDataB);
And I am trying to retrieve using EA->getEntityId() and EB->getEntityId() so I could check which one is EN_PLAYER, which one is EN_GROUND and etc. So then I could up-class from base into derivered class and do other stuff with it.
Tried using with virtual, however somehow I am receiving 2 copies of _EntityID, which can be either the same or DIFFERENT between my Derivered and BaseClass of that one object.
Moreover, I can't cast right away into DeriveredClass, since the code checking would be huge, due to many different types of DeriveredClass'es (DeriveredClassA, DeriveredClassB, DeriveredClassC, DeriveredClassD) with their corresponding vector list.
My question is that How I need setup correctly both Base and Derivered class, so that I could access _EntityID from Baseclass which is the same of that DeriveredClass? My main problem might is that I used incorectly virtual functions, so I left on default to understand my issue.
P.S. This is mainly my c++ issue, other tags are added due to I am using game engine and physics engine for this case.

I believe that you want your code to look more like this:
class Entity
{
public:
enum Type {
EN_NONE = 0,
EN_PLAYER = 1,
EN_PLATFORM,
EN_GROUND,
EN_OBSTACLE,
EN_OTHER
};
Type getType() { return _type; }
protected:
Entity(Type type): _type(type) {}
private:
const Type _type;
};
Then your derived classes and usage of this base would be more like:
class PlayerEntity: public Entity, public SomeClass
{
public:
PlayerEntity(std::string name): Entity(EN_PLAYER), _name(name) {}
std::string getName() const { return _name; }
private:
std::string _name;
};
class PlatformEntity: public Entity, public SomeClass
{
public:
PlatformEntity(): Entity(EN_PLATFORM) {}
};
Initialization is then done like:
int main()
{
PlatformEntity platform;
std::vector<PlatformEntity> platforms(platform);
std::vector<PlayerEntity> players;
players.emplace_back("Bob");
players.emplace_back("Alice");
players.emplace_back("Ook");
}
Access from user-data could then look like this:
// bodyUserDataA and bodyUserDataB are both void*
Entity* const EA = static_cast<Entity*>(bodyUserDataA);
Entity* const EB = static_cast<Entity*>(bodyUserDataB);
switch (EA->getType())
{
case Entity::EN_PLAYER:
{
PlayerEntity* player = static_cast<PlayerEntity*>(EA);
std::cout << "Found player: " << player->getName();
break;
}
case Entity::EN_OTHER:
...
default:
break;
}

Related

How to refer to instances of a class universally without type codes?

I was making a text based RPG in which I have an abstract Item class. From this Item class, I have the classes Weapon, Potion, Key, and Armor. The main character class, Protagonist uses these items and has a function doItemEffect(Item*). How do I implement doItemEffect(Item*) in a way that I refer to all items in universally? To better phrase my problem, if I wasn't clear, here is an example that uses a quite ugly solution.
class Protagonist
{
public:
void doItemEffect(Item* it)
{
switch(it->getType()) //<-- The type is an enum class
{
case ItemType::WEAPON:
attackOpponent(it.getAttackPower()); //If it is a weapon it would have this function
break;
case ItemType::POTION:
heal(it.getHealPower()); //If it is a weapon it would have this function
break;
case ItemType::KEY:
//..Code..
break;
case ItemType::ARMOR:
//More Code...
break;
}
};
And an example of two of the classes Potion and Weapon (The type of the class is a private variable stored in Item with a mutator method setType()):
class Potion : public Item
{
int healPower;
public:
Potion(std::string name, std::string description) : Item(name, description)
{
setType(ItemType::POTION);
}
//Code
};
Weapon:
class Weapon : public Item
{
int attackPower;
public:
Weapon(std::string name, std::string description) : Item(name, description)
{
setType(ItemType::WEAPON);
}
//Code
};
As you can see, this code relies on an class code and a switch in the Protagonist class. Because of this, this doesn't seem very object oriented or polymorphic. Thus, is there a way I could get what subclass a type of Item is, without having to use class codes? Or is there any other solution? The other problem with this snippet above is also that whenever I refer to an item outside of its class, I have to use the same switch statement for each type of item.
Create a virtual function use() in your Item class. Override this function from your derived classes to trigger the various actions (attack, heal, etc.), so that all your subclassed items have an abstract interface to use/apply them.
You can either use RTTI (e.g. dynamic_cast<>()) as an alternative to a dedicated type field:
class Protagonist
{
public:
void doItemEffect(Item* it)
{
Potion *potion = dynamic_cast<Potion *>(item);
Weapon *weapon = dynamic_cast<Weapon *>(item);
if (potion != nullptr) {
heal(potion->getHealPower());
}
else if (weapon != nullptr) {
attackOpponent(weapon->getAttackPower());
}
or use polymorphism by adding a virtual effect() class member function in the abstract Item class:
class Item {
// ...
public:
virtual void effect(Protagonist *) = 0;
// ...
};
and overriding it in the derived classes:
class Potion : public Item
{
// ...
public:
void effect(Protagonist *) override;
};
which has the drawback that your Potion class needs to know that it can be used by a Protagonist. To remedy this, double dispatch is often used. The problem being that C++ does not support double dispatch as a language feature. It can be simulated using the visitor pattern as such:
class Weapon;
class Potion;
class DispatchReceiver {
public:
virtual void effect(Weapon *) = 0;
virtual void effect(Potion *) = 0;
};
class Item {
// ...
public:
virtual void effect(DispatchReceiver *) = 0;
// ...
};
class Potion : public Item {
// ...
virtual void effect(DispatchReceiver *dr) override
{
dr->effect(this);
}
// ...
};
class Weapon : public Item {
// ...
public:
virtual void effect(DispatchReceiver *dr) override
{
dr->effect(this);
}
// ...
};
class Protagonist : public DispatchReceiver {
// ...
public:
void effect(Weapon *weapon) override
{
attackOpponent(weapon->getAttackPower());
}
void effect(Potion *potion) override
{
heal(potion->getHealPower());
}
void doItemEffect(Item* it)
{
it->effect(this);
}
};
Have a list of item types
template<class...Types>
struct type_list_t{};
using Items=type_list_t<Potion, Weapon, etc>;
this replaces your enum. You can write get index of type, and get type from (compile time) index. You can even write what I call a magic switch, mapping runtime (bounded) index to a compile time type via continuation passing style.
Next add a visit method to Item. It takes a index into the type list and then static casts this to the type of the child, then invokes a passed-in callback with the result of the cast.
Write function overloads that look like this:
void use_item( Protagonist*, Potion* );
void use_item( Protagonist*, Weapon* );
Then dispatch to it using visit in Protagonist.
Now you can simplify this by using a pre written variant.
template<class Base, class...Ts>
struct poly_variant:boost::variant<Ts...>{
using boost::variant<Ts...>::variant;
Base& base();
Base const& base() const;
};
now you can visit in Protagonist. A variant of this can be used if you want to make the storage be a pointer (or a smart pointer).
Write base() via apply visitor.

What is best way to know type of sender object?

I have hierarchy of classes:
class A
{
};
class B : public A
{
};
class C : public B
{
};
class D : public A
{
};
and I have some function, which performs notification:
void notify(A* sender, const NotificationType notification)
{
}
My problem is how to find out exact type of sender object. I want to find elegant way to solve this problem. I don't like to use dynamic cast for these purposes. Possible way is to define enum within class A like:
enum ClassType
{
CLASS_A,
CLASS_B,
CLASS_C,
CLASS_D
};
and defining virtual method:
virtual ClassType get_type(void) const;
But this approach has bad scalability. Another way to keep this information in NotificationType, but it has bad scalability too.
P.S. I just want to use similar code:
I want to use similar code:
void notify(A* sender, const NotificationType notification)
{
if (sender is object of A)
new GuiA();
else if (sender is object of B)
new GuiB();
else if (sender is object of C)
new GuiC();
else
new GuiD();
}
To create a matching GUI object based on the concrete type of sender, you could pass a factory to some kind of factory method in A.
class A
{
public:
virtual Agui* createGui(GuiFactory& fac) = 0;
};
class GuiFactory
{
public:
virtual Agui* forB(B&) = 0;
virtual Agui* forC(B&) = 0;
virtual Agui* forD(D&) = 0;
};
class B : public A
{
public:
Agui* createGui(GuiFactory& fac)
{
return fac.forB(*this);
}
};
void notify(A* sender, const NotificationType notification)
{
// Use A interface...
// Get the concrete GuiFactory from somewhere, and use it
auto gui = sender->createGui(win32GuiFactory);
}
If you want know type to persist your hierarchy, conside to use boost::TypeIndex (http://www.boost.org/doc/libs/develop/doc/html/boost_typeindex.html).
If you want know type to process different types in different manners, conside to use Visitor insted of type identifier or make abstract interface with virtual functions covers your needs.
EDITED
Your goal is to create different UI object for different types. You can use the following model to reach your goal:
class UIObject {...};
class UIObjectFactory {...};
class A {
public:
virtual std::unique_ptr<UIObject> Create(UIObjectFactory& factory) = 0;
};
void OnNotify(A* sender) {
auto ptr = sender->Create(GetUIFactory());
...
}
and defining virtual method:
virtual ClassType get_type(void) const;
The easiest way to achieve this and get rid of scalability issue is to implement your get_type() member function in each class A, B, C, ... this way:
typedef uintptr_t ClassType;
virtual ClassType get_type() const
{
static int dummy;
return reinterpret_cast<ClassType>(&dummy);
}
A static variable dummy will be created for each class you add this member function, so that the return value identifies uniquely the class.

c++ can't return a inherited class object

I'm having a trouble with polymorphism, here is the thing. I'm working with rapidjson, after I have the JSON String and convert it, I need a method to send an object of SUPERCLASS InternalMsg, but I need to send inherited class objects.
Example
class InternalMsg{
public:
virtual ~InternalMsg() {};
};
class Event: InternalMsg{
public:
Event(){};
char* type;
char* info;
};
class ScanResult : public InternalMsg{
public:
int id_region;
int result;
};
This are the classes, this is the method, like I say, I'm working with rapidjson:
InternalMsg* JsonPackage::toObject(){
Document doc;
doc.Parse<0>(this->jsonString);
if(doc["class"] == "Event"){
Event* result = new Event;
result->type= (char*)doc["type"].GetString();
result->info = (char*)doc["info"].GetString();
return result;
}else{
std::cout << "No object found" << "\n";
}
return NULL;
}
The method is incomplete and in the line of return have a fail.
I try making a cast but when I use typeid().name() I have InternalMsg but not the inherited class name.
Thanks a lot.
You are using private inheritance, because the default for class is private:
class Event: InternalMsg {
This means Event is-not-an InternalMsg, and the conversion from Event* to InternalMsg* cannot take place.
You should use public inheritance:
class Event: public InternalMsg {
or, since all your members are public anyway, use the fact that the default for struct is public:
struct Event: InternalMsg {

How can I store in a derived class information obtained during initialization of a base class?

I have the situation that, as a side-effect of coming up with data to initialize a base class, a derived class calculates a piece of information that must later be available through its interface. The following gives an idea of the problem, using a boolean as the information wanted:
class base {
public:
base(some_initialization_data);
// ...
};
class derived : public base {
public:
derived()
: base(calc_init_data())
{
}
bool condition_x_occurred() const
{
// How to get at the information obtained
// during the call to calc_init_data()?
}
private:
static some_initialization_data calc_init_data()
{
// This piece of information will later be needed:
const bool condition_x_occurred = /* ... */;
return some_initialization_data(condition_x_occurred);
}
};
The problem with this is that the important piece of information is calculated during the initialization of the base class, before the derived class' own data members are initialized. I must thus not write to the derived class' data elements yet. While I am sure I can get away with a boolean not yet officially created on any platform I have come across in the last 20 years, I would want to avoid invoking undefined behavior.
Note that the information in question has nothing to do at all with the base class, so storing it in the base class is no option. Also, the information can not be stored in a static data member. I have a few ideas about how to refactor the code so that I can do this, but the ones I could come up with all seem quite intrusive for such a small issue. So I wonder if one of you can come up with something simple?
Note: Since we're on an embedded platform, we're stuck with GCC 4.1.2. So strictly C++03 (including TR1), but no C++11.
in C++11, you may do something like:
class derived : public base {
public:
derived() : derived(calc_init_data()) {}
bool condition_x_occurred() const { return my_condition_x_occurred; }
private:
derived(const std::pair<bool, some_initialization_data>& p) :
base(p.second), my_condition_x_occurred(p.first)
{}
static std::pair<bool, some_initialization_data> calc_init_data()
{
// This piece of information will later be needed:
const bool condition_x_occurred = /* ... */;
return std::make_pair(condition_x_occurred, some_initialization_data(condition_x_occurred));
}
private:
bool my_condition_x_occurred;
};
In C++03, you may change your derived class to something like:
class derived : public base {
public:
static derived make_derived() { return derived(calc_init_data()); }
bool condition_x_occurred() const { return my_condition_x_occurred; }
private:
derived(const std::pair<bool, some_initialization_data>& p) :
base(p.second), my_condition_x_occurred(p.first)
{}
static std::pair<bool, some_initialization_data> calc_init_data()
{
// This piece of information will later be needed:
const bool condition_x_occurred = /* ... */;
return std::make_pair(condition_x_occurred, some_initialization_data(condition_x_occurred));
}
private:
bool my_condition_x_occurred;
};
If available on your compiler you can use a delegating constructor:
struct derived_init
{
bool data;
some_initialization_data calc()
{
data = true;
return some_initialization_data();
}
};
class derived : public base {
public:
derived()
: derived(derived_init{})
{ }
bool condition_x_occurred() const
{
return init_data.data;
}
private:
derived(derived_init init)
: base(init.calc()), init_data(init)
{ }
derived_init init_data;
};
With C++03 you could use a default argument:
class derived : public base {
public:
derived(derived_init init = derived_init{})
: base(init.calc()), init_data(init)
{
}
private:
derived_init init_data;
};

boost factory with different products' return value

I use boost factory to create products, what I want to do is to call different products for its DoSomething(), but the problem is that I want that every product's return value is different, and all of them are structs. I want ProductA->DoSomething(), then its return value will be structA, for ProductB->DoSomething(), its return value will be strucB. And all of structures drive from base struct, is it possible? Thanks for your solution, really appreciate!
You can declare base struct ReturnType which will define base methods and variables. Then you can create products without any problem for you.
struct ReturnType
{
virtual std::string getName(){}
};
struct MarsType : ReturnType
{
std::string specialMethod()
{
return "MARS";
}
};
struct SnikersType : ReturnType
{
std::string specialMethod2()
{
return "SNIKERS";
}
};
class Product
{
public:
virtual ReturnType* doSomething()=0;
};
class SnikersProduct : public Product
{
public:
ReturnType* doSomething()
{
return static_cast<ReturnType*>(&value);
}
private:
SnikersType value;
};
class MarsProduct : public Product
{
public:
ReturnType* doSomething()
{
return static_cast<ReturnType*>(&value);
}
private:
MarsType value;
};
class Creator
{
public:
virtual Product* createProduct()=0;
};
class SnikersCreator : public Creator
{
public:
Product* createProduct()
{
return new SnikersProduct();
}
};
class MarsCreator : public Creator
{
public:
Product* createProduct()
{
return new MarsProduct();
}
};
int main()
{
std::vector<Creator*> creators;
creators.push_back(new MarsCreator());
creators.push_back(new SnikersCreator());
Product* mars = creators[0]->createProduct();
Product* snikers = creators[1]->createProduct();
std::cout<<"mars product returns "<<dynamic_cast<MarsType*>(mars->doSomething())->specialMethod()<<std::endl;
std::cout<<"snikers product returns "<<dynamic_cast<SnikersType*>(mars->doSomething())->specialMethod2()<<std::endl;
return 0;
}
Output is :
mars product returns MARS
snikers product returns SNIKERS
No problem at all thanks to return type covariance. This is a C++ feature and means that a virtual function implemented in a derived class can return a pointer (or reference) to the same class as the function implemented (or declared, if pure virtual) in the base class or a pointer (or reference) to a class derived from that. This means that your code is correct C++.
You say that your code compiles correctly, as it should because of return type covariance, as explained in the previous paragraph. You also say that you get errors at runtime, but I'm afraid we cannot help you with that unless you specify what are those errors you are getting.