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.
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.
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).
I have several objects of a Polygon type that just define shapes and I want to store them in a vector that holds Polygons. Polygon has several general methods like getArea() and such, but it is a purely abstract class.
If I have a child of Polygon called Circle, with the method getRadius(), do I need to create a virtual method in Polygon to access that method if it is stored in a vector?
If I expand to more and more shapes, wouldn't creating all those virtual methods in the Polygon declaration (with the associating child method in the child's declaration) be redundant and a waste of space?
Is there another way to inform the compiler that the object I created (of child type) in the Polygon vector of the available child methods without using virtual methods? Or was that kind of the whole point of virtual methods?
I understand how to use virtual methods that the child and parent share, I'm just asking for situations where the parent does not have the method I want to access from the child.
The point of virtual methods is to allow methods which are implemented differently by different children to be called at runtime with the correct implementation.
If you have a method that is specific to one child class only, then the parent should not have a virtual method for it.
If you are trying to call methods which are specific to Circle then you should be using Circle* instead of Polygon*.
If the not-shared method does not make sense for the parent class, then you do not want to put it in the parent class at all. In fact, in that case, polymorphism does not apply, because you cannot have different runtime instances behaving differently on that method: that method just does not make sense to the instances of some child classes, while it does for some others. Therefore, you may want to create a new class, which (1) will become a child of the previously mentioned parent class, (2) will have a virtual method that is shared among the other classes, (3) will be extended by those classes.
In general, if you want to invoke a method specific for a particular class, you need to cast your object to that class or to one of its ancestor declaring that method (virtual or not).
I suppose you want to make a single getRadius call to a vector which will call individual polygons respectively. Then a base class obviously makes sense.
Just implement the individual GetRadius Method for all the childclasses and have one default virtual function to ensure consistency.
Since, you're saying, there are multiple shapes, it implies there are multiple classes aka multiple GetRadius implementations.
A virtual function will simplify your calling process.
Related to this, I would like to know if there are reasons to use pointers to a parent object (not talking about a parent class) instead of references.
Obviously, if the parent could be null, a reference will not work. But what if the parent object creates and destroys the child object in its lifetime so that the child object's pointer back to its parent will never be null? I think it sounds okay in this case, but I have not seen others do it and am still learning a lot about C++.
The specific case I am thinking of is a specialized dialog window that will only be created by a certain window class.
What are some problems (if any) with doing
class Child {
Child(Parent& parent) : parent_(parent) {}
Parent& parent_;
};
versus
class Child {
Child(Parent* parent) : parent_(parent) {}
Parent* parent_;
};
People will argue about it all day long but references are just limited pointers. Don't agonize about which to use.
The advantage of a pointer is you can copy childs, or create a child without a parent, to be given one later. If you need to do this, you have to use a pointer.
If not, use whichever makes you feel warmest inside. It just isn't worth worrying about.
If you make the pointer Parent *const parent_ it is effectively the same as a reference.
here are some differences between references and pointers :
References :
A reference must be initialized at creation time
Once initialized to point to an object, you cant change the reference to point to another object
Pointers :
A pointer does not need to be initialized, you can point to NULL
You can modify your pointer in order to point to another object
Consequences :
Thus depending on the relationship you want to have between child and parents, you will choose pointer or reference. Also prefer reference to pointer if you dont need pointer.
In other words, if child object have the same parent during its lifetime and parent exists at the creation of the child : use reference to point to parent.