Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
CODE PROJECT For Those Who Code
  • Home
  • Articles
  • FAQ
Community
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Polymorphic pointer points to what?

Polymorphic pointer points to what?

Scheduled Pinned Locked Moved C / C++ / MFC
game-devgraphicsquestionlearning
21 Posts 7 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • G G_urr_A

    I'm programming a little game, an Asteroids clone. I need to do some collision detection. In order to determine what should happen when two objects collide, I need to know which types of objects they are. I've got a few different classes, one for the player ship, one for asteroids and another for the bullets that the player can shoot. All of these are children of a base class containing some generic physics code. I've got a vector of *base_class which keeps track of all objects, meaning that regardless of whether the object is of class ship or class asteroid or whatever, it is stored and accessed through a vector of *base_class. What I need to do now is to go through this vector and find objects of certain types, i.e. find all asteroids. I could of course just add another member variable and set it accordingly, but I was wondering if there is a way to determine what type of object the pointer is pointing at. Does anyone have any suggestions?

    D Offline
    D Offline
    David Crow
    wrote on last edited by
    #6

    G_urr_A wrote:

    I was wondering if there is a way to determine what type of object the pointer is pointing at.

    Is the typeid operator of any help?


    "The largest fire starts but with the smallest spark." - David Crow

    1 Reply Last reply
    0
    • C Cedric Moonen

      I took a look at the doc. Ok that's fine but some actions need to be performed depending on the type of object. So, you need to compare the result from typeid to something. What will be this something ? Probably getting the class name from the clas info and compare it to a string:

      if (strcmp(typeid(MyClass).name(),"CPlayerShip"))
      {
      // Perform action on player ship
      }

      I don't see really a major advantage on using a technique in which you manage the type of your class yourself (see my previous post). And honnestly, I found that ugly ;P (but that's personal). Any comment ? (I just explain my point of vue, I would like to have your :) ).


      Cédric Moonen Software developer
      Charting control

      M Offline
      M Offline
      markkuk
      wrote on last edited by
      #7

      You should compare the type_info objects returned by typeid, not the class names.

      if ( typeid(myObj) == typeid(CPlayerShip)) {
      // act on a player ship object
      }

      The major advantage over managing the type of class by yourself is that you don't have to manage the class information by yourself ;P

      C 1 Reply Last reply
      0
      • M markkuk

        You should compare the type_info objects returned by typeid, not the class names.

        if ( typeid(myObj) == typeid(CPlayerShip)) {
        // act on a player ship object
        }

        The major advantage over managing the type of class by yourself is that you don't have to manage the class information by yourself ;P

        C Offline
        C Offline
        Cedric Moonen
        wrote on last edited by
        #8

        Ok, I didn't read carefully enough the doc ;). I didn't saw that you could pass the class to the typeid (typeid(CPlayerShip)). In that case that make sense. But I suppose there is also a drawback in enabling RTTI. Do you have any idea about that ?


        Cédric Moonen Software developer
        Charting control

        1 Reply Last reply
        0
        • C Cedric Moonen

          I would suggest what you said in your post: add a variable in the base_class that specify which kind of object it is. To secure the code (so in order to always specify a value for that variable), you can force it through the constructor: remove the default ctor and let only a constructor that supply the type. Then, in the constructor of your derived classes, in their constructor, simply call the base constructor with the appropriate type. You can also enable Run-time type information but I don't have a lot of experience with that.


          Cédric Moonen Software developer
          Charting control -- modified at 7:21 Wednesday 17th May, 2006

          S Offline
          S Offline
          Stephen Hewitt
          wrote on last edited by
          #9

          All of these solutions based on switching on a type field in the base class are contrary to object oriented principles. If you use inheritance and virtual function properly you shouldn't need such switching. Excessive switching on a type field violates The Open Closed Principle. See here[^] for a good but short article on general object oriented priniciples and The Open Closed Principle. Steve

          C 1 Reply Last reply
          0
          • S Stephen Hewitt

            All of these solutions based on switching on a type field in the base class are contrary to object oriented principles. If you use inheritance and virtual function properly you shouldn't need such switching. Excessive switching on a type field violates The Open Closed Principle. See here[^] for a good but short article on general object oriented priniciples and The Open Closed Principle. Steve

            C Offline
            C Offline
            Cedric Moonen
            wrote on last edited by
            #10

            What do you mean by switching ? Here, there is no casting involved: suppose you have a ResolveCollision function (and you pass the object with which it collides as parameter) that is virtual in the base class, and each child class overrides this method. In these particular functions, you need to know at least what is the type of the other object you are colliding with (because the actions to be taken will be different depending of the type of the other object). What suggestion do you have for a better design ? I'm curious now :).


            Cédric Moonen Software developer
            Charting control

            S 1 Reply Last reply
            0
            • G G_urr_A

              I'm programming a little game, an Asteroids clone. I need to do some collision detection. In order to determine what should happen when two objects collide, I need to know which types of objects they are. I've got a few different classes, one for the player ship, one for asteroids and another for the bullets that the player can shoot. All of these are children of a base class containing some generic physics code. I've got a vector of *base_class which keeps track of all objects, meaning that regardless of whether the object is of class ship or class asteroid or whatever, it is stored and accessed through a vector of *base_class. What I need to do now is to go through this vector and find objects of certain types, i.e. find all asteroids. I could of course just add another member variable and set it accordingly, but I was wondering if there is a way to determine what type of object the pointer is pointing at. Does anyone have any suggestions?

              S Offline
              S Offline
              SimonSays
              wrote on last edited by
              #11

              Well, as earlier posters have pointed out, dynamic_cast and typeid can be used to extract the information you want. However, to me at least, when you need to do this (and presumably frequently for an astroids game) you might start asking if you have the best possible design. I kind of liked the suggestion of the eariler poster about adding a function like "virtual bool ResolveColision (baseClass *)". Otherwise you could have a huge ugly mess of collision resolution between any 2 possible object types. If you happen to just need to be able to get set of all asteroids in the game, why not keep around an extra container just for astroids (and one for ships, missles, etc). Then you can iterate through any specific object without messing with all the other object types you are not interested in.

              G 1 Reply Last reply
              0
              • S SimonSays

                Well, as earlier posters have pointed out, dynamic_cast and typeid can be used to extract the information you want. However, to me at least, when you need to do this (and presumably frequently for an astroids game) you might start asking if you have the best possible design. I kind of liked the suggestion of the eariler poster about adding a function like "virtual bool ResolveColision (baseClass *)". Otherwise you could have a huge ugly mess of collision resolution between any 2 possible object types. If you happen to just need to be able to get set of all asteroids in the game, why not keep around an extra container just for astroids (and one for ships, missles, etc). Then you can iterate through any specific object without messing with all the other object types you are not interested in.

                G Offline
                G Offline
                G_urr_A
                wrote on last edited by
                #12

                I've ended up using typeid now. And of course I'm using the best possible design. Not. It's grown slightly too messy for my tastes by now, and it'll probably get worse. The whole thing is a school project in which I have to cooperate with another guy. We've implemented support in some places for features that haven't been implemented, we did not think everything through before we started writing, and we don't really share a common concept of what OO is, so the code is quite messy. I'd love to rewrite the whole thing, but we're expected to present the stuff to our teacher this friday, and we're expected to understand all the code (he needs to understand "my parts"), and he's out of town, coming back thursday evening. So, a rewrite isn't an option right now. But, thanks a lot to everyone for the input! We got my problem solved, and I got some other good info on what not to do next time. Now I just need to finnish this stuff...

                G 1 Reply Last reply
                0
                • G G_urr_A

                  I've ended up using typeid now. And of course I'm using the best possible design. Not. It's grown slightly too messy for my tastes by now, and it'll probably get worse. The whole thing is a school project in which I have to cooperate with another guy. We've implemented support in some places for features that haven't been implemented, we did not think everything through before we started writing, and we don't really share a common concept of what OO is, so the code is quite messy. I'd love to rewrite the whole thing, but we're expected to present the stuff to our teacher this friday, and we're expected to understand all the code (he needs to understand "my parts"), and he's out of town, coming back thursday evening. So, a rewrite isn't an option right now. But, thanks a lot to everyone for the input! We got my problem solved, and I got some other good info on what not to do next time. Now I just need to finnish this stuff...

                  G Offline
                  G Offline
                  G_urr_A
                  wrote on last edited by
                  #13

                  Hmm.... Since I've already started a thread, I guess I might as well put it to good use... ;-) I've implemented an ugly hack now. In the code where I give bullets their position and speed, I first find the ship that fired them in ObjectList (which is the vector of *base_class that I've mentioned), then get some data from the ship object. The thing is, I need to access methods that are specific to the CShip class, but I've only got a pointer to base_class to handle it. What I do now is the following: CShip *temp; temp = (CShip*)(void*)ObjectList.at(i); I cast to void* and then to the data type I need. Anything but this explicit casting produces errors, since the compiler doesn't realize that I've checked (using typeid) that what I'm handling is really a CShip object. This solution is really ugly, IMO. There should be a good way to do this, but I can't figure it out (I'm kind of new to OO).

                  S 1 Reply Last reply
                  0
                  • G G_urr_A

                    Hmm.... Since I've already started a thread, I guess I might as well put it to good use... ;-) I've implemented an ugly hack now. In the code where I give bullets their position and speed, I first find the ship that fired them in ObjectList (which is the vector of *base_class that I've mentioned), then get some data from the ship object. The thing is, I need to access methods that are specific to the CShip class, but I've only got a pointer to base_class to handle it. What I do now is the following: CShip *temp; temp = (CShip*)(void*)ObjectList.at(i); I cast to void* and then to the data type I need. Anything but this explicit casting produces errors, since the compiler doesn't realize that I've checked (using typeid) that what I'm handling is really a CShip object. This solution is really ugly, IMO. There should be a good way to do this, but I can't figure it out (I'm kind of new to OO).

                    S Offline
                    S Offline
                    Stephen Hewitt
                    wrote on last edited by
                    #14

                    If you must use this technique use dynamic_cast instead. This design is poor: using a downcast is rarely needed and you should use virtual function instead. Steve

                    1 Reply Last reply
                    0
                    • C Cedric Moonen

                      What do you mean by switching ? Here, there is no casting involved: suppose you have a ResolveCollision function (and you pass the object with which it collides as parameter) that is virtual in the base class, and each child class overrides this method. In these particular functions, you need to know at least what is the type of the other object you are colliding with (because the actions to be taken will be different depending of the type of the other object). What suggestion do you have for a better design ? I'm curious now :).


                      Cédric Moonen Software developer
                      Charting control

                      S Offline
                      S Offline
                      Stephen Hewitt
                      wrote on last edited by
                      #15

                      Cedric Moonen wrote:

                      add a variable in the base_class that specify which kind of object it is

                      This is what I was referring to in my comment. This article[^] can expliain why I think its probably a bad idea better then I can here. The section on The Open Closed Principle is about such designs and why they're a bad idea. Steve

                      C 1 Reply Last reply
                      0
                      • S Stephen Hewitt

                        Cedric Moonen wrote:

                        add a variable in the base_class that specify which kind of object it is

                        This is what I was referring to in my comment. This article[^] can expliain why I think its probably a bad idea better then I can here. The section on The Open Closed Principle is about such designs and why they're a bad idea. Steve

                        C Offline
                        C Offline
                        Cedric Moonen
                        wrote on last edited by
                        #16

                        Hi Stephen, thanks for the article, it was interesting. I totally agree with you on that point but here, a part of the problem is solved by using a virtual ResolveCollision function. Still, there is a need to know with which entity the current entity is colliding with. So, typically what you suggest is the use of RTTI (getting the typeid of the class) ? This will 'separate' the base class from the implementations (a enum in the base class is not required anymore). Is that what you were thinking about ? Thanks for your answer ;) PS: if I'm so interested, it's because I also develop a game in this style and I implemented in the way I described above. But I'm open to better suggestions :-D


                        Cédric Moonen Software developer
                        Charting control

                        S 1 Reply Last reply
                        0
                        • C Cedric Moonen

                          Hi Stephen, thanks for the article, it was interesting. I totally agree with you on that point but here, a part of the problem is solved by using a virtual ResolveCollision function. Still, there is a need to know with which entity the current entity is colliding with. So, typically what you suggest is the use of RTTI (getting the typeid of the class) ? This will 'separate' the base class from the implementations (a enum in the base class is not required anymore). Is that what you were thinking about ? Thanks for your answer ;) PS: if I'm so interested, it's because I also develop a game in this style and I implemented in the way I described above. But I'm open to better suggestions :-D


                          Cédric Moonen Software developer
                          Charting control

                          S Offline
                          S Offline
                          Stephen Hewitt
                          wrote on last edited by
                          #17

                          I would not use any type of RTTI. First I'd think about the game. For example with collision detection in asteroids the following should be noted:  - Asteroids don't collide with each other.  - Bullets don't collide with each other. These facts mean we don't have to check every pair of objects for collisions: we only need to test for the following collisions:  - Bullets with asteroids.  - Bullets with the enemy ships.  - Asteroids with asteroids.  - Your ship with asteroids.  - Your ship with bullets.  - Your ship with enemy ship. These distinctions should be reflected in our design to minimize the amount of work we need to do to detect collisions. I haven't thought it through, but I'd probably use multiple lists instead on one super list. Steve

                          C 1 Reply Last reply
                          0
                          • S Stephen Hewitt

                            I would not use any type of RTTI. First I'd think about the game. For example with collision detection in asteroids the following should be noted:  - Asteroids don't collide with each other.  - Bullets don't collide with each other. These facts mean we don't have to check every pair of objects for collisions: we only need to test for the following collisions:  - Bullets with asteroids.  - Bullets with the enemy ships.  - Asteroids with asteroids.  - Your ship with asteroids.  - Your ship with bullets.  - Your ship with enemy ship. These distinctions should be reflected in our design to minimize the amount of work we need to do to detect collisions. I haven't thought it through, but I'd probably use multiple lists instead on one super list. Steve

                            C Offline
                            C Offline
                            Cedric Moonen
                            wrote on last edited by
                            #18

                            Stephen Hewitt wrote:

                            I haven't thought it through, but I'd probably use multiple lists instead on one super list.

                            Mmmhh, I see a big restriction in that way of thinking: what happens if you want to add a new entity type, say 'bonus' (that gives you lives or new weapon) ? Then, you got a problem in your design because you have to manage a new list which can result in a lot of changes in the existing code... Right now, what we are doing is that we have a factory that can create specific entities. The different entities register themselves in the factory at the program startup (in fact they register their name and a function that create one instance of the entity, so no need to modify the factoty when new entities are added, it's just map names to a creation function). So, if you want to create a new entity type, you just have to create the new class (and the creation function) and register it in the factory at startup and that's done ! No modifications in the rest of the code. You will tel me: 'Ok, but to be used, these new entites needs to be created so you need to know if they exist or not'. In fact this step is not 'directly' required because the creation of the levels of the game is made through an editor. The editor retrieves the available entities from the factory and allow the end user to place them in the level (so, there also, there is no need to know these entities). With your design, I see a flaw when you want to add new entity types that were not planned.

                            Stephen Hewitt wrote:

                            These distinctions should be reflected in our design to minimize the amount of work we need to do to detect collisions.

                            It's perfectly doable with the method I exposed you: in the ResolveCollision of each entity type, it's up to you to take action on one or several 'collisions type' PS: I don't want to prove you're wrong, but this is an interesting debate and I'm interested in your opinion.


                            Cédric Moonen Software developer
                            Charting control

                            S 1 Reply Last reply
                            0
                            • C Cedric Moonen

                              Stephen Hewitt wrote:

                              I haven't thought it through, but I'd probably use multiple lists instead on one super list.

                              Mmmhh, I see a big restriction in that way of thinking: what happens if you want to add a new entity type, say 'bonus' (that gives you lives or new weapon) ? Then, you got a problem in your design because you have to manage a new list which can result in a lot of changes in the existing code... Right now, what we are doing is that we have a factory that can create specific entities. The different entities register themselves in the factory at the program startup (in fact they register their name and a function that create one instance of the entity, so no need to modify the factoty when new entities are added, it's just map names to a creation function). So, if you want to create a new entity type, you just have to create the new class (and the creation function) and register it in the factory at startup and that's done ! No modifications in the rest of the code. You will tel me: 'Ok, but to be used, these new entites needs to be created so you need to know if they exist or not'. In fact this step is not 'directly' required because the creation of the levels of the game is made through an editor. The editor retrieves the available entities from the factory and allow the end user to place them in the level (so, there also, there is no need to know these entities). With your design, I see a flaw when you want to add new entity types that were not planned.

                              Stephen Hewitt wrote:

                              These distinctions should be reflected in our design to minimize the amount of work we need to do to detect collisions.

                              It's perfectly doable with the method I exposed you: in the ResolveCollision of each entity type, it's up to you to take action on one or several 'collisions type' PS: I don't want to prove you're wrong, but this is an interesting debate and I'm interested in your opinion.


                              Cédric Moonen Software developer
                              Charting control

                              S Offline
                              S Offline
                              Stephen Hewitt
                              wrote on last edited by
                              #19

                              We'll stick with asteroids as that's the original topic. My original comment was against switching on object type, be it by using typeid, dynamic_cast or an enum in a base class. I don't think I need to go over this further given that the article I posted a link to explains it better than I could. Now let’s get to the collision detection. As I pointed out you need not check for collisions between every pair of object as; for example, bullets can't collide with each other. If you've got n objects there are (n*(n-1))/2 = (n^2-n)/2 pairs to test: so it's probably a good idea to limit the size on n since the growth is quadratic. I admit in a game of asteroids, with today’s computers, you probably need not worry. I would probably use multiple lists as not every aspect of an objects behavior need be determined by it: some aspects can be controlled by its environment. For example, which container it's listed in. This need not be a limitation as you control which objects are added to which lists. I don't want to get into too much of a debate however, as a lot of this is all theoretical. To really get into it we would need a concrete example to work with and spend some time analyzing it and then contrast different implementation strategies; that's a lot of work to win an argument. Steve

                              C 1 Reply Last reply
                              0
                              • S Stephen Hewitt

                                We'll stick with asteroids as that's the original topic. My original comment was against switching on object type, be it by using typeid, dynamic_cast or an enum in a base class. I don't think I need to go over this further given that the article I posted a link to explains it better than I could. Now let’s get to the collision detection. As I pointed out you need not check for collisions between every pair of object as; for example, bullets can't collide with each other. If you've got n objects there are (n*(n-1))/2 = (n^2-n)/2 pairs to test: so it's probably a good idea to limit the size on n since the growth is quadratic. I admit in a game of asteroids, with today’s computers, you probably need not worry. I would probably use multiple lists as not every aspect of an objects behavior need be determined by it: some aspects can be controlled by its environment. For example, which container it's listed in. This need not be a limitation as you control which objects are added to which lists. I don't want to get into too much of a debate however, as a lot of this is all theoretical. To really get into it we would need a concrete example to work with and spend some time analyzing it and then contrast different implementation strategies; that's a lot of work to win an argument. Steve

                                C Offline
                                C Offline
                                Cedric Moonen
                                wrote on last edited by
                                #20

                                Stephen Hewitt wrote:

                                I don't think I need to go over this further given that the article I posted a link to explains it better than I could.

                                Yes sure,I agree. Thanks for article though.

                                Stephen Hewitt wrote:

                                If you've got n objects there are (n*(n-1))/2 = (n^2-n)/2 pairs to test: so it's probably a good idea to limit the size on n since the growth is quadratic.

                                I solved this in another way: there are only three "teams": players (ship and bullets), ennemies (ships and bullets) and neutral (bonus, and other things that doesn't have any impact on the game). So, basically this reduce a lot the pairs of collisions. And anyway these 'Resolving collisions' are done in the derived classes themselves (so, you can neglected certain pairs).

                                Stephen Hewitt wrote:

                                I don't want to get into too much of a debate however, as a lot of this is all theoretical

                                Yes sure. But anyway thanks for exposing your point of vue :). I find this always interesting to see how other programmers solve design 'problems' (that's what I'm doing here also, just showing you how I do that, absolutely not saying that it's the best solution :rolleyes:). But I agree with you, we won't dig into more details as it requires a concrete example and some time to spend on it.


                                Cédric Moonen Software developer
                                Charting control

                                S 1 Reply Last reply
                                0
                                • C Cedric Moonen

                                  Stephen Hewitt wrote:

                                  I don't think I need to go over this further given that the article I posted a link to explains it better than I could.

                                  Yes sure,I agree. Thanks for article though.

                                  Stephen Hewitt wrote:

                                  If you've got n objects there are (n*(n-1))/2 = (n^2-n)/2 pairs to test: so it's probably a good idea to limit the size on n since the growth is quadratic.

                                  I solved this in another way: there are only three "teams": players (ship and bullets), ennemies (ships and bullets) and neutral (bonus, and other things that doesn't have any impact on the game). So, basically this reduce a lot the pairs of collisions. And anyway these 'Resolving collisions' are done in the derived classes themselves (so, you can neglected certain pairs).

                                  Stephen Hewitt wrote:

                                  I don't want to get into too much of a debate however, as a lot of this is all theoretical

                                  Yes sure. But anyway thanks for exposing your point of vue :). I find this always interesting to see how other programmers solve design 'problems' (that's what I'm doing here also, just showing you how I do that, absolutely not saying that it's the best solution :rolleyes:). But I agree with you, we won't dig into more details as it requires a concrete example and some time to spend on it.


                                  Cédric Moonen Software developer
                                  Charting control

                                  S Offline
                                  S Offline
                                  Stephen Hewitt
                                  wrote on last edited by
                                  #21

                                  Cedric Moonen wrote:

                                  I solved this in another way: there are only three "teams": players (ship and bullets), ennemies (ships and bullets) and neutral (bonus, and other things that doesn't have any impact on the game).

                                  If you make a list of objects in each "team" you’re left with a similar architecture to what I was suggesting. Having a list for the members of each of the team means you can visit the members of a team without visiting every object in the "world". Steve

                                  1 Reply Last reply
                                  0
                                  Reply
                                  • Reply as topic
                                  Log in to reply
                                  • Oldest to Newest
                                  • Newest to Oldest
                                  • Most Votes


                                  • Login

                                  • Don't have an account? Register

                                  • Login or register to search.
                                  • First post
                                    Last post
                                  0
                                  • Categories
                                  • Recent
                                  • Tags
                                  • Popular
                                  • World
                                  • Users
                                  • Groups