Lugruf Posted April 6, 2016 Share Posted April 6, 2016 Code: Output: I was testing some stuff relating inheritance and I came across the following problem. If I have a container of pointers to parents (a map in this case), I can store child objects in them, as a pointer or a reference to a parent can take a pointer or reference to any child deriving from that parent. However, when using the gettor, I get a pointer to a parent instead of a pointer to a child no matter the type of the object I'm retrieving. This means that I don't have access to the methods and data of the children that are not in the public interface of the parent. For example, the bar() function in Child_1 is completely unaccessible for me. I know that I could access the foo() functions of the children by making the foo() function of the parent virtual and then overriding it, but what I'm looking for is a way of accessing the public interface of the children that is not available in the parent class. I've thought about different solutions, such as a template gettor where I specify the type of the object I want to retrieve. Someting like template <typename T> T * get(std::string key) { return (T *) Pointers[key]; } And explicitly call the type: test.get<Child_1> ("Test 2")->bar(); The problem with this is that the chances of screwing everything up and the compiler not telling me are high. For example if I did: test.get<Child_1> ("Test 3")->bar(); // This would be accessing memory I don't own Do you have any idea of how could I do this? Ideally the gettor would check the object's type at runtime and return a pointer of the specific type, but I don't know if that's even possile. Quote Link to comment Share on other sites More sharing options...
jonatas Posted April 6, 2016 Share Posted April 6, 2016 I don't know much about C++, but you can do a few things. The first thing is to use the keyword virtual on the foo method of the Parent class. This way it'll call the method's implementation of the instatiated object and not the the one of the parent class. By using virtual you'll get something like that: Parent *p1 = new Parent; Parent *c1 = new Child_1; Parent *c2 = new Child_2; p1->foo(); // prints "I'm a parent" c1->foo(); // prints "I'm a Child 1" c2->foo(); // prints "I'm a Child 2" // Remember to delete the pointers you created afterwards Of course that this way you still can't call the bar method of the Child_1 class, you'll probably get a compiler error. To do so, you need to explicitly cast the pointer to a Child_1 type. Something like that. Parent *p1 = new Parent; Parent *c1 = new Child_1; p1->bar(); // compiler error c1->bar(); // compiler error Child_1 *cp1 = (Child_1*) p1; Child_1 *cc1 = (Child_1*) c1; cp1->bar(); // compiles, but the behavior is undefined cc1->bar(); // prints "This is defnitely a Child 1" I've never used anything to check the type of an object in C++. In java there's the instanceof operator, but, as pointed here, if you want to cast something in a polymorphic situation it's a sign that there's probably somthing wrong with the way you designed your code. Since it seems like you're only learning how things work, the same link shows that you can use a dynamic_cast, the documentation says that it returns the casted value or a null pointer, this way you can use somehing like that: Parent *p1 = new Child_1; Child_1 *c1; if(c1 = dynamic_cast<Child_1*>(p1)) { c1->bar(); } I hope I could help you and that I did not say anything wrong. By the way, I preferJava because it's easier and I also like the documentation better, but C and C++ teaches you how to be more conscious regarding the resources and how to manage memory better. If you can learn C++ well you'll easily dominate things like Java, C#, Python, etc. Quote Link to comment Share on other sites More sharing options...
Lugruf Posted April 7, 2016 Author Share Posted April 7, 2016 (edited) I don't know much about C++, but you can do a few things. The first thing is to use the keyword virtual on the foo method of the Parent class. This way it'll call the method's implementation of the instatiated object and not the the one of the parent class. By using virtual you'll get something like that: I know that. I already mention it in the explanation of the problem: "I know that I could access the foo() functions of the children by making the foo() function of the parent virtual and then overriding it, but what I'm looking for is a way of accessing the public interface of the children that is not available in the parent class." I've never used anything to check the type of an object in C++. In java there's the instanceof operator, but, as pointed here, if you want to cast something in a polymorphic situation it's a sign that there's probably somthing wrong with the way you designed your code. Since it seems like you're only learning how things work, the same link shows that you can use a dynamic_cast, the documentation says that it returns the casted value or a null pointer, this way you can use somehing like that: Parent *p1 = new Child_1; Child_1 *c1; if(c1 = dynamic_cast<Child_1*>(p1)) { c1->bar(); } I hope I could help you and that I did not say anything wrong.By the way, I preferJava because it's easier and I also like the documentation better, but C and C++ teaches you how to be more conscious regarding the resources and how to manage memory better. If you can learn C++ well you'll easily dominate things like Java, C#, Python, etc. I'm not sure if you understood the problem. The function that I want to change is the gettor, so that it automatically changes the type of the pointer. Doing the casts manually each time I need to access something from the container would be tedious and something I would want to avoid if possible. Still, thank you for your help. I will look for more information on dynamic casts and see if I can manage to do something with it. Edited April 7, 2016 by Lugruf Quote Link to comment Share on other sites More sharing options...
jonatas Posted April 7, 2016 Share Posted April 7, 2016 I'm not sure if you understood the problem. The function that I want to change is the gettor, so that it automatically changes the type of the pointer. Doing the casts manually each time I need to access something from the container would be tedious and something I would want to avoid if possible. Looks like you can do that using boost, but I'm not sure how to do it and it still doesn't seem safe. To be honest, even in languages like Java that you can do this through the use of generics, you'll still get either a compiler warning, a runtime exception if you access something wrong or both. Basically, you might be able to do what you want, but it is bad code and, even though manually casting each time is annoying, it is the safest option. Quote Link to comment Share on other sites More sharing options...
Lugruf Posted April 7, 2016 Author Share Posted April 7, 2016 I actually managed to do it. I can only have an object of each type in the container, but it's okay for what I wanted to do. I was looking for a way to build a component system for a game object, where all components would derive form a generic component class. And I managed to do it with a template variadic add function and a template gettor. It looks like this: And the output: Basically now I'm able to create any object into the map and initialize it with the variables it needs, and I can also access with a pointer to the child class instead of the parent class. The only drawback is that I'm limited to a single object of each type, but that's not really a problem as I mentioned before, because a game object should never have more than one component of the same type. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.