Access child member methods from function taking parent class - c++

A test function needs to take in any object of a class that is derived from Parent and access the Child implementation of Function(). To me, this would seem like something easy to do. I tried to do the following. it feels intuitively right, but it does not work. It still calls the Parent implementation of Function()
Class Parent
{
Public:
Parent();
~Parent();
virtual void Function() = 0;
};
Class Child : public Parent
{
Public:
Child();
~Child();
void Function(){
// Do something
};
};
void Test(Parent Object)
{
Object.Function();
};
int main()
{
Child Object;
Test(Child);
return 0;
}
How would one implement such a thing?
Am I missing something small? or is this solution far off what I am trying to achieve?
Thanks in advance.

To use virtual functions in C++ you must use a reference or a pointer. Try this
void Test(Parent& Object) // reference to Parent
{
Object.Function();
};
You should research object slicing to understand what goes wrong with your version, and why you must use a reference or a pointer.

Related

Can I somehow call the derived class method while looping through vector<shared_ptr<BaseClass>>?

I have the following problem:
class Component
{
public:
virtual void update(){};
};
class TestComponent : public Component
{
void update()override;
};
class GameObject
{
public :
void addComponent(Component& comp)
{
std::shared_ptr<Component> test = std::make_shared<Component>(comp);
components.push_back(test);
}
void GameObject::update()
{
for(auto comp : components)
{
//I want to call the derived update here without casting it to the derived class if possible
comp->update();
}
}
private:
std::vector<std::shared_ptr<Component>> components;
};
Somewhere else in my code:
GameObject go;
TestComponent comp;
go.addComponent(comp);
I would just assume that when I add an object to the vector of Components that I can simply call update on all of the vectors elements and it uses the overridden update of the object I passed into addComponent. So for my example above I expect the forloop to call the update of the TestComponent I added and not the baseclass update. But thats not whats happening so I assume I am missing something.
Or maybe my approach is just wrong in general. I am not really sure about my usage of a sharedpointer for this?
Any hints in the right direction would be appreciated.
There are no TestComponent objects in your vector. They are all Components.
void addComponent(Component& comp)
{
std::shared_ptr<Component> test = std::make_shared<Component>(comp);
components.push_back(test);
}
In this function, you create a new Component object that s a copy of the Component sub-object of the TestComponent object you passed in. This is known as object slicing.
You will need to either avoid copying the objects or implement some sort of cloneable interface.
To avoid copying the object, you can do something like this:
class GameObject
{
public:
void addComponent(std::shared_ptr<Component> comp)
{
components.push_back(comp);
}
// ...
};
int main() {
GameObject go;
std::shared_ptr<TestComponent> testComponent = std::make_shared<TestComponent>();
go.addComponent(testComponent);
}
In this case, main and go share ownership of a single TestComponent object. If you want to avoid that, you could implement a clonable interface so that objects know how to copy themselves:
class Component
{
public:
virtual void update(){};
virtual std::shared_ptr<Component> clone() const
{
return std::make_shared<Component>(*this);
}
};
class TestComponent : public Component
{
void update() override;
std::shared_ptr<Component> clone() const override
{
return std::make_shared<TestComponent>(*this);
}
};
class GameObject
{
public:
void addComponent(const Component& comp)
{
components.push_back(comp.clone());
}
// ...
};
int main()
{
GameObject go;
TestComponent comp;
go.addComponent(comp);
}
In this case, you still make a copy, but every class has to override the clone method.
As for the question about shared_ptr: std::shared_ptr is a smart pointer that shares ownership of an object between multiple owners. An object owned by one or more std::shared_ptrs is only destroyed when all of the std::shared_ptr objects sharing ownership of it are destroyed. If you don't need this behavior, then std::unique_ptr exists and will be somewhat more performant. std::unique_ptr models unique ownership. Only one std::unique_ptr object can ever reference an object at a time, and the object is destroyed when that std::unique_ptr is destroyed.
Either type of smart pointer could be used in this situation:
Use std::shared_ptr if you want a GameObject to be able to share ownership of its components with other owners (perhaps other GameObjects).
Use std::unique_ptr if you want a GameObject to have exclusive ownership of its components. In this case the GameObject could still allow other objects to access its components, but the components' lifetimes would be tied to the lifetime of the GameObject
To make your code compile just add another method, rest are fine . Since update method is virtual and the base class is non-abstract, both can call update without any issue.
void TestComponent::addComponent(const TestComponent & tcomp)
{
std::shared_ptr<Component> test = std::make_shared<TestComponent >(tcomp);
components.push_back(test);
}
Edited: For adding any component, derived or base class, use this way:
void TestComponent::addComponent(std::shared_ptr<Component> comp)
{
components.push_back(comp);
}

Override virtual function with existing function

Let me first say this is a purely academic question, since what I want to do can be better accomplished with multiple layers of inheritance.
That said, I wonder if it's possible to override a virtual function with an existing function without writing a wrapper or adding any inheritance layers. Code:
int myfunc2() { return 2; }
class Parent {
public:
virtual int myfunc() { return 0; }
};
class Child1 : public Parent {
public:
int myfunc() override { return 1; }
};
class Child2 : public Parent {
public:
// There a way to do this?
// int myfunc() = myfunc2;
// instead of this?
int myfunc() { return myfunc2(); };
};
int main() {
Child2 baz;
return baz.myfunc();
}
I'd like to override myfunc in the definition of Child2 by simply "forwarding" the declaration to the existing declaration of myfunc2.
Is this, or something akin to it, possible?
Context: I've got a bunch of child classes, some of which have identical definitions of myfunc, some of which do not. A better solution is to create an intermediate child class that defines the common myfunc and have the pertinent children inherit from that instead.
// There a way to do this?
// int myfunc() = myfunc2;
// instead of this?
int myfunc() { return myfunc2(); };
No, there isn't.
There is a problem.
A non-static member function accepts one more implicit parameter: pointer to the object itself. While a stand-alone function does not have such a parameter, For example you may not use the keyword this or member access syntax inside the definition of a stand alone function.

How do I call a method in an owning object in c++?

What is the syntax for calling a method in an owning object from an owned object in c++?
Parent class:
class Parent
{
private:
Child child;
public:
Parent()
{
addChild(child);
}
void MethodToBeCalled(int someArgument)
{
}
};
Child class:
class Child
{
private:
void myVoid()
{
//Call parent method somehow
}
public:
Child()
{
}
};
I tried to make my question as simple and generic as possible (to be of benefit to as many as possible). Let me know if I can make it even clearer.
Thank you!
Here's a example. I had to modify your code a bit to get it compile:
class Component {};
class Parent;
class Child : public Component
{
private:
inline void myVoid();
Parent &parent_ref;
public:
Child(Parent &pr) : parent_ref{pr} {}
};
class Parent : public Component {
private:
Child child;
public:
Parent() : child{*this}
{
// addChildComponent(child);
}
void MethodToBeCalled(int someArgument)
{
}
};
inline void Child::myVoid()
{
parent_ref.MethodToBeCalled(1);
}
If you are sure that your Child object is a member subobject of Parent class (as in your example), you can use the container_of trick (see Understanding container_of macro in the Linux kernel)
class Child
{
private:
void myVoid();
};
class Parent
{
public:
Child child;
void MethodToBeCalled(int someArgument)
{
}
};
void Child::myVoid()
{
container_of(this, Parent, child)->MethodToBeCalled(42);
}
Obviously, tricks like this immediately restrict the usability of your Child class to always being a member of Parent class (at least when you intend to call myVoid() method on it).
A much better idea would be to just pass a reference to parent object to child object.
In your case, you can't, because Child and Parent have nothing in common except that they both inherit Component. Child has to have a Parent object in order to call MethodToBeCalled().

call child static function from parent?

Suppose we have the following:
class Parent {
public:
virtual void run() {
for (int i = 0 ; i < bar.size() ; ++it)
cout << i << "\n" ;
};
protected:
static vector<int> foo() {return vector r({1,2,3,4,5});};
static vector<int> bar;
}
vector<int> Parent::bar = Parent::foo();
Now if I create a child class whose run function would be called externally, how can I redefine the foo function to return something else while still using the parent run function?
Edit: Sorry let me add some more information. Suppose the virtual function run() is a lot of code, all of which is essentially the same. The only difference in the parent and child classes is what values I want specified in the vector bar, so it would seem to be a little wasteful to redefine the virtual function in the child class. However, if you redefine Child::bar, and call Child::run(), the Parent::bar is used since it's defined in the parent class. Is there some way to have the line "vector Parent::bar = Parent::foo();" know in the Child class to use "Child::foo();"?
As usual. Override base virtual function in derived class.
class Parent {
public:
virtual bool run() {return bar;};
static bool foo() {return true;};
static bool bar;
};
class Child: public Parent
{
public:
static bool foo() { return false;};
};
You can then still use base version applying Base:: scope resolution:
int main() {
bool bc = Child::foo();
bool bp = Parent::foo();
std::cout << bc << bp;
return 0;
}
http://ideone.com/TdaNQ5
I am not sure what do you exactly want here. However, you can override the static function like this,
class Child: public Parent
{
public:
static bool foo() {return false;};
};
You really don't say much about your problem, therefore it is hard to distinguish what you need from what is potentially an XY problem.
One potential problem with your architecture is that you have a Parent and a Child classes that share a static variable bar yet you seem to initialize them differently for Parent and Child classes. However, there is only one bar that is shared both by Parent and Child objects, independently of who wrote to it last.
So, what do you expect when both a Parent and a Child objects are used simultaneously? The answer you look for depends on your answer on that one. In particular, if your answer is 'it is not designed to have Parent and Child objects operate simultaneously', then both classes should definitely not share a static variable.

How to properly use virtual member functions in c++

I am having a problem with the following code, the overriden virtual functions are not executing. Not sure i'm doing wrong here probably a silly mistake. Anyway this is a game project and I have an array of objects which looks like this (the core::array is an irrlicht array, similar to the vector array)
core::array<GameObject> gameTargets;
This is the GameObject and Zombie definition
class GameObject {
protected:
scene::ISceneNode* node;
public:
int ID;
int hitpoints;
GameObject() {
...
};
void setNode(scene::ISceneNode* inode) {
...
}
virtual void shot(int dmg) {
... [BREAKPOINT HERE]
}
scene::ISceneNode* getNode() {
return node;
}
};
class Zombie : public GameObject {
public:
static const enum Animation {
ZOMBIE_WALK,
ZOMBIE_HURT,
ZOMBIE_DIE,
ZOMBIE_TWITCH,
ZOMBIE_ATTACK,
ZOMBIE_IDLE
};
//We only want to accepted animated mesh nodes for this object
Zombie(int hp, scene::IAnimatedMeshSceneNode* inode) {
...
}
//Override the shot function
void shot(int dmg) {
... [BREAKPOINT HERE]
}
//Animate the zombie
void setAnimation(Animation anim) {
...
}
};
The member functions of the derived classes is never called, I am creating the objects like this
Zombie target(hp, (scene::IAnimatedMeshSceneNode*)node);
and calling the virtual function like this
for(int i = 0; (u32)i<level->gameTargets.size(); i++) {
if(selectedNode == level->gameTargets[i].getNode()) {
level->gameTargets[i].shot(b->damage);
}
}
where b is a pointer to a bullet with a int variable damage and gameTargets contains GameObject
I suspect that you're experiencing slicing because the gameTargets array contains values. I can't tell for sure because I don't know how the core::array template works. See What is object slicing? for a discussion about what slicing is.
To fix this problem, store either raw pointers as in
core::array<GameObject *> gameTargets;
Or use some sort of reference-counted pointer like
core::array<std::shared_ptr<GameObject>> gameTargets; // only available in C++11
array<GameObject> is a container of objects, not a container of pointers. Every object you add to it will be a GameObject and not one of the derived classes (if you add a derived class object, then it'll be "sliced").
Without knowing exactly what your core::array does, I suspect what you really intended to create is an array of std::unique_ptr<GameObject> (smart pointers) along the lines of
core::array< std::unique_ptr<GameObject> > gameTargets;
std::unique_ptr<GameObject> my_zombie(new Zombie);
gameTargets.push_back( my_zombie );
a quick solution would be to make those parent functions as pure virtual functions, as in:
virtual void shot(int dmg) { } = 0;
// edit
and use array of pointer as suggested by Frerich Raabe