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().
Related
I receive a complicated object from a framework I can't really change:
Parent parent = framework.get();
I would like to add some attributes and methods to this parent:
class Child : public Parent {
public:
inline Child() {}
int extraVariable = 999;
int extraMethod() { return 666; }
};
Is there any way to 'cast' or copy an instantiated Parent into a Child class, other than manually copying all the attributes?
The python equivalent would be
class Child(Parent):
def extraMethod(self):
return 666
parent = framework.get()
parent.__class__ = Child
I realize C++ isn't python but I'm willing to hack it together (this is personal code, i.e. ugly is fine).
You could add a converting constructor, or two, to Child.
Example:
class Child : public Parent {
public:
// converting constructors
Child(const Parent& p) : Parent(p) {} // copy
Child(Parent&& p) : Parent(std::move(p)) {} // move
//...
}
Demo
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.
I have a subclass that knows what type of object to send the parent class, but I can't figure out how to create it so the parent can keep the object around without making an extra copy in the parent class constructor.
class Thing {
...some stuff...
};
class Parent {
private:
Thing & thing;
public:
Parent(Thing & in_thing):thing(in_thing);
};
class Child : public Parent {
public:
// Does my Thing object get created on the stack here and therefor I can't keep a reference or pointer to it in the parent class?
Child():Parent(Thing()){};
}
What's the right way to do this?
I don't know how to try this to see if it's OK because it could potentially work fine for some amount of time even if the memory isn't valid to use.
Instead of creating an object in stack memory, create one using heap memory. The parent can own the object.
class Parent {
private:
std::unique_ptr<Thing> thing;;
public:
Parent(Thing* in_thing): thing(in_thing);
};
and
class Child : public Parent {
public:
Child():Parent(new Thing()){};
}
Using a pointer also allows Child to create a sub-type of Thing. Some times you need that.
class ChildThing : public Thing { ... };
class Child : public Parent {
public:
Child():Parent(new ChildThing()){};
}
I have a global function within a namespace and this function is a helper function that will create objects and return them. However the return type is of the parent class, but the actual object returned is a subclass of the parent. It is then up to the user to cast it returned "parent" object to the appropriate subclass. I thought this is what polymorphism was about but I am not able to cast the returned object to a subclass. For example:
class Parent {...};
class ChildOne : public Parent {...};
class ChildTwo : public Parent {...};
Parent my_function(int x) {
if(x) {
return ChildOne();
}
else {
return ChildTwo();
}
};
int main() {
// The statement below is giving me an error (no matching function call...)
ChildOne my_child = (ChildOne)my_function(1);
}
No, you cannot cast the object returned by my_function to a subclass of Parent.
Since:
Parent my_function(int x) {
returns the object by value, it always returns an object of class Parent, and never a subclass. This is due to slicing.
For a discussion, see What is object slicing?
It is not possible as it is written in NPE's answer,
Since you asked in comment what you could do instead, this is how you can achieve (more or less) what you want in C++11.
#include <iostream>
#include <memory>
using namespace std;
class Parent {
public:
virtual ~Parent() { }
};
class ChildOne : public Parent {
public:
void say_hello() { cout << "Hello from ChildOne!" << endl; }
};
class ChildTwo : public Parent { };
unique_ptr<Parent> my_function(int x) {
if(x) {
return unique_ptr<Parent>{ new ChildOne() };
}
else {
return unique_ptr<Parent>{ new ChildTwo() };
}
}
int main() {
auto parent = my_function(1);
if (ChildOne* my_child = dynamic_cast<ChildOne*>(parent.get())) {
my_child->say_hello();
}
}
However, I would revise my code in such a way that the downcast (cast from parent to child) is not need. There are certain situations where it is needed or unavoidable but most of the time it is a sign of design flaw.
is it possible in c++ to call a child function from a parent function.
Let's take an example: The parent class defines in a function (parse) the general workflow. The workflow then calls different methods which represent part of the flow (parseElementA). These functions can be overwritten by the child class, if not the standart function, which is part of the parent shall be used.
My issue is: I create a child object and execute the workflow function (parse). When the overwritten function (parseElementA) is called within the workflow function it calls the function from the parent and not from the child.
What could i do so it calls the overwritten function in child.
class Parent {
public:
void parse() { parseElementA(); }
virtual void parseElementA() { printf("parent\n"); }
};
class Child : public Parent {
public:
void parseElementA() { printf("child\n"); }
};
Child child;
child.parse();
the output is parent. What can I do that it returns child.
Thank you very much for any advice.
After fixing compiler errors from your code, it works fine.
#include <cstdio>
class Parent {
public:
void parse() { parseElementA(); }
virtual void parseElementA() { printf("parent\n"); }
};
class Child : public Parent {
public:
void parseElementA() { printf("child\n"); }
};
int main() {
Child child;
child.parse();
return 0;
}