How to speak to a inherit class from another inherit class - c++

Here to show you what I mean exactly it hard to describe without code:
class Object
{
// attributes..
};
class Attribute
{
public:
void myfunc();
};
class Character: public Object, public Attribute
{
};
void main()
{
Object* ch = new Character;
// How can I call the myfunc() from Attribute
// tried static_cast<Attribute*>(ch);
}
I only just have a Object Class pointer and i doesn't know
if it is a Character Object or another object which inherit from the
Attribute class, what i know is that the class inherit from Attribute Class.

Cross casting can only be done by dynamic_cast.
Object * o = new Character;
Attribute * a = dynamic_cast<Attribute*>(o);
if (!a) throw_a_fit();
a->myfunc();
However, for this to work you must have polymorphic base classes (they must have at least one virtual function).

If you know that you have an object of the correct type, you can cast explicitly:
Object * ch = /* something that's a Character */
static_cast<Attribute *>(static_cast<Character *>(ch))->myfunc();
Obviously this will not be correct if the type of the most-derived object pointed to by ch is not a subtype of Attribute.
If your class hierarchy is polymorphic (i.e. has at least one virtual function in each base class that you care about), then you can use dynamic_cast directly at runtime and check if it succeeded, but that is a comparatively expensive operation. By contrast, the static cast does not incur any runtime cost at all.

Related

Trying to cast base class pointer to a interface that derived class object implements

I am experimenting a little bit with inheritance in C++ and I stepped on a case that I don't quite understand. When I try to compile the code I get:
error: cannot ‘dynamic_cast’ ‘base’ (of type ‘class Base*’) to type
‘class SomeInterface*’ (source type is not polymorphic)
I assume that it is not a proper way of casting, because SomeInterface is not related to Base, but is there a way to make it work? Maybe there something I can add to the class to make static_cast possible? Or is it just a bad architecture and I should rearrange my code to not introduce cases like this one? I'd appreciate any comments or resources I could read to understand this behaviour and possibly learn how to make it work.
class Base
{
};
class SomeInterface
{
public:
void call_me() { }
};
class Derived : public Base, public SomeInterface
{
};
void try_call_me(Base* base)
{
// line below causes an error
SomeInterface* some_interface_instance = dynamic_cast<SomeInterface*>(base);
some_interface_instance->call_me();
}
int main()
{
Derived derived_instance;
Base* base_instance = &derived_instance;
try_call_me(base_instance);
return 0;
}
dynamic_cast requires (except for up-casts) that the base class type used in the argument is polymorphic.
A class in C++ is called polymorphic if it has at least one virtual function. So you need to add one to your Base, for example the destructor:
struct Base
{
virtual ~Base() = default;
};
Polymorphic classes store additional information that is required for dynamic_cast to work at runtime.
However, that is a costly operation to do. Reconsider why try_call_me is expecting a pointer to Base instead of SomeInterface if that is really what it needs.
If you keep it as it is, you also need to add error checking to the dynamic_cast. It will return a null pointer if base doesn't refer to an object whose most-derived object contain a SomeInterface base class subobject that could be side-casted to:
SomeInterface* some_interface_instance = dynamic_cast<SomeInterface*>(base);
if(!some_interface_instance) {
// didn't pass a suitable pointer, error!
// fail here, otherwise there will be undefined behavior!
} else {
some_interface_instance->call_me();
}
(If you use references instead of pointers, dynamic_cast will throw an exception instead of producing a null pointer value.)

Is there a way to dynamically change an object to another type?

Let's say I have a class A that inherits from its parent class B, and there is another class C that also inherits from class B. Is there a way to change this pointer of class A to class C at run time?
class A : public B {
A::someFunction() {
//can I change this pointer to class C here?
}
}
class C : public B {
...
}
You cant and you shouldn't. The reason is pretty simple. Take a look at this code,
class Base {
public:
Base() {}
virtual void SayHello() {}
};
class A_Derived : public Base {
public:
A_Derived() {}
virtual void SayHello() override { ... }
void SayAllo() { ... }
};
class B_Derived : public Base {
public:
B_Derived() {}
virtual void SayHello() override { ... }
void SayBello() { ... }
};
Now when is we assign the A_Derived class pointer to B_Derived, the compiler will allow to call the SayBello method. This is because for the compiler, its a B_Derived class pointer, it doesn't know about the actual pointer data is pointing at a data block of A_Derived (because inheritance is not compile time, its runtime). So what happens when you call SayBello using that pointer? Its gonna be undefined behavior. You see the issue?
This is why you cant do it (logically and also using C++ style casting).
Is there a way to dynamically change an object to another type?
No. The type of an object cannot change through its lifetime.
Let's say I have a class A that inherits from its parent class B, and there is another class C that also inherits from class B. Is there a way to change this pointer of class A to class C at run time?
No.
At best, you could destroy the original object, and reuse its memory to create another object. Obviously the size and alignment of the memory must be sufficient for the new type. Any reference (which includes pointers such as this in a member function) to the old object will have been invalidated by the destruction of the original object. Reuse of storage is an advanced topic which I don't recommend to beginners.
There is no valid way to do this for one simple reason - in your class inheritance structure, an object of class A cannot be also an object of class C. In C++, two objects of different types can have the same address if and only if one of the objects is a subobject of the other, which is not your case. If you cast a pointer to A to a pointer to C, the pointer will still refer to an object of type A, and dereferencing the casted pointer would result in undefined behavior.
Most probably, what you want to do is to create an object of class C from an object of class A. You can use a converting constructor or a conversion operator to implement this.
Note that if what you really want is to reuse the storage allocated for the object of type A, you will still need to destroy the object A first and then construct the object C. You will have to save any relevant data from A before destroying it to be able to construct C with the data.

static_cast from base class pointer to derived class pointer is invalid

I am creating a simple test entity-component system. I have a base Component class with several derived classes. I then have several systems that apply some logic to these components.
// Component.h
// ------------
class Component
{
public:
Component();
~Component();
}
// ControlComponent.h
// -------------------
#include <string>
#include "Component.h"
class ControlComponent : public Component
{
public:
std::string input = ""; // store simple input instruction
ControlComponent();
~ControlComponent();
};
// ControlSystem.cpp
void ControlSystem::update(Entity* entity)
{
vector<Component*>* components = entity->getComponents();
for (Component* component : *components)
{
PositionComponent* pc = static_cast<PositionComponent*>(component);
ControlComponent* cc = static_cast<ControlComponent*>(component);
if (pc != nullptr && cc != nullptr)
{
std::cout << "Which direction would you like to go?" << std::endl;
std::string input;
std::cin >> input;
cc->input = input; // application breaks here
// Apply some logic...
}
}
}
When I static_cast from base Component* to either of the derived components (PositionComponent* or ControlComponent*) and when both results are not nullptr(i.e the cast was successful), I get invalid values, like cc->input not being able to read characters from string etc.
I wire up the components in my entity factory, like this:
void EntityFactory::wireUpPlayer(Entity* player)
{
player->addComponent(new HealthComponent());
player->addComponent(new ControlComponent());
player->addComponent(new PositionComponent());
}
And the implementation for addComponent is as follows:
void Entity::addComponent(Component* component)
{
m_components.push_back(component);
}
These components are shown to have valid memory addresses, so I'm not sure where the issue is coming from.
static_cast does not check validity at runtime; if the cast compiled, it assumes at runtime that the conversion is okay. If you aren't casting a null pointer, the result of a static_cast will not be a null pointer. To get a checked cast you need dynamic_cast and that, in turn, requires the pointer being converted to point to a polymorphic type, i.e., one that has at least one virtual function. That means changing Component to have at least one virtual function.
When I static_cast from base Component* to either of the derived components (PositionComponent* or ControlComponent*) and when both results are not nullptr(i.e the cast was successful)...
When casting from a base class to a derived class, static_cast is telling the compiler, "Trust me, I know what I'm doing." In other words, if it's even potentially legal, it will "succeed" and return non-nullptr. If, at runtime, it's not legal, you'll get undefined behavior, from trying to use an instance of one class as if it were of another class.
Use dynamic_cast instead.
As Pete Becker and Josh Kelley said, use dynamic_cast and I believe you also need to set at least one function as virtual. If you do not, the compiler will not record the inheritance and dynamic_cast will likely still return nullptr. When performing inheritance, I suggest making the class destructors virtual. This is also good practice when unmanaged resources need to be disposed of in the destructor of a derived class and you only have a pointer to the base class, the derived class destructor will only be called so long as the destructors are virtual. There was a post that explained it here: When to use virtual destructors?

How to find out what type of object a pointer points to in C++?

Let's say I have class SuperClass { public: int a; } and class SubClass : SuperClass { public: int b; } and I took a pointer to an instance of the SubClass SubClass *subPointer and addressed that pointer to a SuperClass pointer SuperClass *superPointer = subPointer. Now of course I can always cast the superPointer object to a pointer of SubClass because the only thing it stores is an adress. But how would I know if the object superPointer is pointing to an instance of SubClass or is just a SuperClass pointer?
You usually don't want to use typeid for this.
You usually want to use dynamic_cast instead:
if (SubClass *p = dynamic_cast<SubClass *>(SuperClassPtr))
// If we get here (the `if` succeeds) it was pointing to an object of
// the derived class and `p` is now pointing at that derived object.
A couple of notes though. First of all, you need at least one virtual function in the base class for this to work (but if it doesn't have a virtual function, why are you inheriting from it?)
Second, wanting this very often tends to indicate design problems with the code. In most cases, you want to define a virtual function in the base class, which you (if necessary) override in the derived class to do whatever's needed so you can just use a pointer to the base class throughout.
Finally, as it stands right now, most of the conversions will fail -- you've used the default (private) inheritance, which prevents the implicit conversion from derived * to base * that you'd normally expect to see happen (you probably want class SubClass : public SuperClass).
Use RTTI machanism. Like:
if(typeid(*superPointer) == typeid(SuperClass)) superPointer->dosomething();
if(typeid(*superPointer) == typeid(SubClass)) superPointer->dosomethingelse();

C++ Inheritance. Changing Object data Types

I am having trouble with forcing data type changes has on my own objects. I have a base class say A and two classes derived from A called B and C. I pass objects B and C to a function that checks which type of object it is (B or C). Here is some example code below and the question to my problem:
enum ClassType {"B", "C"};
class A {
protected:
m_Type;
public:
ClassType Type() { return m_Type}
...
...
};
class B : public A {
otherMemberFunctions();
}
class C : public A {
otherMemberFunctions();
}
void WhatType(vector<A*>* candidates){
vector<B*> b_candidates(0);
vector<C*> c_candidates(0);
for(int i = 0; i < candidates->size(); i++){
if(candidates->at(i)->Type() == B ){
B* b = (B*) candidates->at(i);
b_candidates(b);
}
//Same idea for Object C
}
}
I would then use WhatType(vector<A*>* candidates) as follows
vector<B*>* b_example
WhatType((vector<A*>*) b_exmaple)
When I have filled the new vector b_candidates in the function WhatType. Will I still have access to the member functions in the B object or will I only have the access to the member functions in the base class A?
I am confused to what happens with the object when I change the type of the object.
Here
WhatType((vector<A*>*) b_exmaple)
and here
B* b = (B*) candidates->at(i);
When you receive a pointer to a polymorphic object you have two types: the "static" type of the object, which, in your case, will be A *, and its "dynamic" or "real" type, that depends on what was actually assigned to it.
Casting your A * to B * forces the compiler to consider that pointer as a pointer to B; this is safe as long as you actually know that that pointer is actually a pointer to B, otherwise the compiler will start writing nonsensical code (invoking B methods on data of another type).
The checks you are trying to implement are a homegrown version of RTTI, which is a mechanism that allows you to know which is the "real type" of a pointer or a reference to a polymorphic class, and to perform that kind of casts safely. Check out typeid and dynamic_cast on your C++ manual for more info about it. (Incidentally, IIRC dynamic_cast is not only for safety in case the dynamic type is wrong, but it may perform also some extra magic on your pointer if you use it in complicated class hierarchies; so, avoid C-style casting for polymorphic classes)
By the way, in general it's considered "code smell" to have to manually check the "real type" of the pointer in order to cast it and use its methods: the OOP ideal would be being able to do the work only though virtual methods available in the base class.
Big warning: RTTI works only on polymorphic classes, i.e. classes that have at least one virtual method. On the other hand, if you are building a class hierarchy where objects are being passed around as pointers to the base class you'll almost surely want to have a virtual destructor, so that's no big deal.
Since you cast to B*, you will have access to B's members.
The actual type of the objects does not change, of course, but if you only have a pointer (or reference) to the base class you can not access fields specific to the sub-classes.
What you can do to access sub-class fields is to use dynamic_cast to cast it to the sub-class:
A *a = new B; // We cant reach the members of class B in a
B *b = dynamic_cast<B *>(a); // But now we have a proper pointer to B
Ok, so if you had an object of type B instantiated on the heap and held by a pointer of type A. you can only see type A's member functions, to access type B's member functions you have to static_cast<B*> which is what the ... "(B*)" ... is doing.
dynamic cast is better as it will return a null if the conversion is not possible. but of course it happens a run-time so there's a penalty.
As B and C are À derived, a vector<B *> and vector<C *> contains A base class objects. If you ensure to set your A::m_Type attribute in your constructor, you will no have problems:
enum ClassType {'B', 'C'}; // see I modified your definition
class A {
protected:
ClassType m_Type;
public:
ClassType Type() { return m_Type};
...
...
};
class B : public A {
public:
B() : m_Type('B') {}
....
};
Using this, you will check without problems your B and Cobjects. After that, as you are casting base objects to derived ones, you will have fully access to their public methods and attributes.