There is a parent class, and there are two child class extends the parent class: child1,child2, I see the children as parent class, like this:
function(Parent *c){
c->someMethod();
}
but child has a method which child2 doesn't have. I try to add a if statement to judge whether the class is child1 like this:
function(Parent *c){
if(c->getType() == 'child1'){
c->someMethod();
}
}
but there comes the error:'class Parent' has no member named 'someMethod' so, how to deal with it?
Since you are working with pointer to Parent, you can only call methods, which Parent type have.
So, the first solution is to put all necessary methods in Parent class and override them in children classes. This is far more preferable than next one.
Another possible solution is to dynamic_cast Parent pointer to necessary child pointer, if you are sure, that it's correct one and call method on child pointer. This is sign of bad design, and I'd recommend to stick to first solution.
Try dynamic_casting it to the correct type. If it is not possible, the cast should return a nullptr (or NULL).
Related
I've read here that, in a situation where some parent object uniquely owns several children, and each child needs to be able to access its parent, a weak pointer should be used as the back-pointer instead of a shared pointer so as to avoid a dependency cycle.
I have two questions:
What are the advantages of giving a weak pointer to the parent as opposed to a simple reference?
In the code below, how should I pass each child a weak pointer to its parent? I know you can inherit from std::enable_shared_from_this to get a shared pointer from this. Is there an equivalent for weak pointers? Or something else?
#include <memory>
#include <vector>
class Parent;
class Child {
public:
void set_parent(std::weak_ptr<Parent> parent) {
parent_ = parent;
}
std::weak_ptr<Parent> parent_;
};
class Parent {
void add_child(std::unique_ptr<Child> child) {
// child->set_parent(???);
children_.push_back(std::move(child));
}
std::vector<std::unique_ptr<Child>> children_;
};
weak_ptrs come from shared_ptrs. If your parent nodes "uniquely own" the children, then the children cannot have weak_ptrs to their parents, as this would require that a shared_ptr to them exist somewhere.
Note that the example you cite does not state anything about "unique ownership" of the relationship between the items.
Furthermore, so long as the parents never relinquish ownership of the children to code outside of the system, there's no reason to not just have a regular pointer to the parent (it needs to be a pointer because a reference cannot be changed). The pointer will always be valid (from outside of the system), since a parent must exist in order for the child to exist. That's what unique ownership means, after all.
You have said that a parent always uniquely owns a child but you have not specified a few things:
Is it valid to copy a child object?
Is it valid to move a child object?
If you answered yes to either of those then you must consider what happens if a child is copied or moved between parents as your child class wont by default prevent it. So my advice would be to either explicitly delete copy and move constructors and assignment operators OR if you want that ability then the responsibility is on YOU to make sure that if and when a child is copied and or moved that its parent pointer points to the correct parent and to prevent it pointing to an invalid / deleted parent.
If you go down the route of explicitly disabling copy and move semantics then in that circumstance i can't think of anything off the top of my head that would prevent you from using a reference to the parent instead.
Finally if you did actually want weak pointers in the children pointing to their parents then you could consider having your parent class extend from : enable_shared_from_this. I think the typical usecase for this is when you don't know if you will outlive another object but in the case where it is still a valid object then you would like to ensure it stays alive while you perform some operations on it.
Please note if you take that approach the parent object MUST be stored inside a shared_ptr. See shared_from_this. If not then you are in undefined behaviour territory and lets just all agree that is bad.
Edit: i forgot to mention if you can use C++17 you can directly get the weak_ptr from the parent to pass to the child: weak_from_this
In C++, I have Parent class. Child1, Child2, etc. inherit from it. Classes Child1, Child2, etc. share some methods of the parent and have their own methods.
I declare a vector to be able to add any child of Parent.
vector<Parent*> v = {new Child1(), new Child2(),...};
Depending on a child, I want to define different behaviour for a method of BClass::someMethod(Child1* child), BClass::someMethod(Child2* child)... Something like Visitor pattern. The problem is that I must pass an element of v vector into BClass::someMethod(...) and the compiler says, for example for method BClass::someMethod(Child1* c1) when v[0] is passed:
Argument of type Parent* is incompatible with parameter of type Child1*
Could you please tell me how to overcome the issue?
OOP solution is to add a virtual member function to Parent, implement the different behaviour in overridden member functions of children, and change the argument of BClass::someMethod to a Parent pointer (or reference), and call the virtual function in there - or get rid of BClass::someMethod entirely, and use the virtual function directly in case BClass::someMethod no longer has other functionality.
P.S. Storing dynamic allocations in bare pointers is not a good design. Smart pointers are recommended instead.
Consider a simple picture below.
Here Child inherit's its properties from both, Parent 1 and Parent 2, and Also the properties directly from the Grand Parent.
Let each be seperate class.
* Its obvious that, to avoid the conflict of child inheriting the properties of parent 1 and parent 2, we make a base class "virtual" .
From, where ever I've learnt I was instructed that in mainfunction, In child class, I could get the properties of parent or grandparent.
I get confused when, I try to think what happens with
Compiler and Memory side internally.
Let display() be the member function of all Grandparent and parent1 and parent2. Now the virtual base class takes necessary steps, to avoid ambiguity in the child which actually has two duplicate sets of parent1 and parent2, yes also the grandparent.
Now, I want to make myself clear that
If the display() of the grandparent is accessed from the child using pointer and addresses internally. child won't be having the any duplicate sets. So, there won't araise any ambiguity therefore why else are we going for virtual funtions?
In other case, What I'm thinking above is wrong, and consider that display() of grandparent is actually or I assume to be copied into the child,and the same should happen with the parent1 and parent2. (Please, don't say that base child will be having access or containing public and protected members of grandparent, parent1 and parent2 , I'm sorry, the reason is that, this is the answer I found on Internet and it doesn't clarify me, when I think how I happens) As a result, child should be having same member function in the same class of child, this should definitely give problems because child couldn't have same member functions as even constructors differ in arguments.
Any other cases are possible, please explain.
I made my maximum effort to detail my doubt.
If possible, help me to understand how exactly the virtual classes and inheritance concepts work.
Thank you.
--
A derived class is composed of everything that the base class is PLUS your extra bits. No copying takes place because a class is just like a design. It's the object where stuff actually exists. When you instantiate the derived class (create an object of it) it will contain members of the derived and base class as one.
Your class is like a blueprint - the design for a house. I could design a house with 1 bedroom, 1 bathroom and a kitchen. This blueprint is like your class. I can't pee in the bathroom yet: it's just a design on paper. I can't make a sandwich in kitchen. Now I can choose to have the house built - this is then an object. Now I can take a pee. It's quite a relief, I had to wait ages. In fact I can make as many copies of this house as I like. Making copies is instantiating more objects.
But one day I think to myself I'd like a bigger house based on this one so I make a new design that I can simply add to the old design extending the house. This is inheritance. My new design has a lounge added on and another toilet (I need to pee a lot, ok?). When I instantiate this version of my design I'll get a house which contains a bedroom from the 1st design, and bathroom, and kitchen as well as my lounge.
Sounds to me like you need to get a good book on object oriented programming. It won't be as amazing as my explanation there, no doubt, and probably won't talk about toilets as much as one would normally like, however it will explain much more than this. Good luck.
An object of a derived type contains within it a subobject of the base type. When you call a non-virtual, non-static member function of the base class, then that function is effectively invoked on that base subobject.
(Note that it is possible to have multiple base subobjects of the same type when you use multiple inheritance.)
Virtual functions behave somewhat differently: a virtual call always requests a (usually dynamic) search for the most-derived object of which the invoked object is a base subobject, and then call the last overrider of the function. But that's essentially unrelated to the point of the question. For example, when you have struct A { virtual void f(); }; struct B : A {}; and then call B().f(), that call is still performed on the A-subobject – the virtual dispatch only starts there.
So I have this class (the parent) that creates a dialog box and fills it with controls. Within that class is another class (the child) that creates a timer that links/passes a function call to an event system to update the contents of some of the controls at regular intervals. The problem comes from the timer update function needing to know the objects it needs to update.
I would like to simply pass the pointer of the base class to the child some how in a way that it's all self contained. But I can't figure out a way to make that happen. Anyone have any ideas?
I've searched for answers but all I got was accessing variables from inside the base class from within the child class. That would work but it seems unnecessary to fire an event for every individual control... (I guess I could create all the controls in an structure but that seems unnecessary)
the nested classes look a bit like this:
class CreateDialog{
class timer{
}
}
you can try to declare a static member variable in the parent class and set it to the pointer of parent within the constructor of parent class.
I have a parent class and child class (inherited from parent).
In the child class, I have a member function named function_blah();
I used vector<parent*> A to store 5 parent instances, 3 child instances. So the total number of elements in the vector is 8.
I can easily access to member functions of element A[0] to A[4], which are parent instances.
But whenever I try to have access to member functions of element A[5] to A[7], the compiler complains that class parent has no member named 'function_blah'
The way I access to elements is using index. e.x A[i] with i = 0..7. Is it correct? if not, how?
You need to downcast the pointer to the child class in order to use child functions on it.
When you're accessing a child object using a parent*, you are effectively telling the compiler, "treat this object as a parent". Since function_blah() only exists on the child, the compiler doesn't know what to do.
You can ameliorate this by downcasting using the dynamic_cast operator:
child* c = dynamic_cast<child*>(A[6]);
c->function_blah();
This will perform a runtime-checked, type-safe cast from the parent* to a child* where you can call function_blah().
This solution only works if you know that the object you're pulling out is definitely a child and not a parent. If there's uncertainty, what you need to do instead is use inheritance and create a virtual method on the parent which you then overload on the child.
You're storing parent*, which has no function_blah method. You need to either make function_blah a virtual method of parent, or use dynamic_cast to downcast to a child*.
Is member _blah() declared virtual in parent? Or is it even declared in parent? Because if not, then you'll never be able to access _blah() through a parent pointer. And yes, you'll also have to downcast, but only if you know exactly that you're expecting a child type.