As was foretold, we've added advertisements to the forums! If you have questions, or if you encounter any bugs, please visit this thread: https://forums.penny-arcade.com/discussion/240191/forum-advertisement-faq-and-reports-thread/

Pointers and Classes, arg (C++)

2»

Posts

  • bowenbowen How you doin'? Registered User regular
    edited February 2010
    Arrays are basically pointers for dumbies.

    bowen on
    not a doctor, not a lawyer, examples I use may not be fully researched so don't take out of context plz, don't @ me
  • GanluanGanluan Registered User regular
    edited February 2010
    bowen wrote: »
    And this is one of the #1 reasons I hate C#.

    Because of default parameters? They are part of .Net 4.0. Not to mention the vast majority of the time overloading will accomplish the same result (and could easily work for his need as well).

    Ganluan on
  • bowenbowen How you doin'? Registered User regular
    edited February 2010
    Yeah I love C# but I hate not having them on my current Visual Studio. Not enough to develop on beta software though.

    bowen on
    not a doctor, not a lawyer, examples I use may not be fully researched so don't take out of context plz, don't @ me
  • GoetterdaemmerungGoetterdaemmerung Registered User regular
    edited February 2010
    No, I got it. What I meant was, PC and NPC are temporary containers, and data from the linked list will be copied into them as needed. Think of it this way, the linked list is PlayerName->John->Mark->Joe->Henry->William->Terry. PC contains the info of PlayerName. NPC1 contains the info of John. NPC2 contains the info of Mark, etc up through Henry. William and Terry are in the list, but not used at the moment. Henry is killed and he has no heirs, so William is promoted to take his place. His info is now copied into NPC4.
    Right so you have two options: you can actually *copy* the data from NPC[5] to NPC[4], overwriting Henry. Or, since NPC[] is a temporary container (not really, but I think you're trying to say that ultimately you do not want to be accessing them via the NPC variable), you can simply change Joe's 'next' pointer to point at William instead of Henry -- and if you added any other pointers to Henry, move those also to William.

    Consider this (I think more common) approach:
    Declare a *Player pointer (let's call it pcPlayer) that always points to the player character (the head of the list).
    Allocate the PC's Player using "new Player", then fill it with his player's property; point pcPlayer here.
    Allocate an NPC Player using "new player", then fill it however you want (using an RNG...); point pcPlayer->next here.
    Keep allocating NPC Players, adding to the end of the linked list as you go (keep a separate pointer to track the end of the linked list).
    Now you have a pointer pcPlayer to the start of your list, and a neat linked list holding your characters.

    If you want to keep a list of inactive/benched Players (William and Terry?), keep them in a separate list. If someone in the main list dies, and you want to replace them using a benched player, just remove them from the bench, and add them to the active list. Etc.

    Goetterdaemmerung on
  • Sir CarcassSir Carcass I have been shown the end of my world Round Rock, TXRegistered User regular
    edited February 2010
    I was actually wanting the list to have all of the characters past and present. The array is what will hold the current "players", but I'm thinking of having the list be where data is pulled from. And thinking about that, I may change my design slightly. Instead of a list with lists coming off of it, I may just have everyone in a list, and use another method for tracking family. This would avoid the headache of reorganizing the list when a new head of household surfaces. I could track it by storing IDs in the Player class, possibly. Maybe an int for spouse and an array of ints for children.

    Sir Carcass on
  • GoetterdaemmerungGoetterdaemmerung Registered User regular
    edited February 2010
    I was actually wanting the list to have all of the characters past and present. The array is what will hold the current "players", but I'm thinking of having the list be where data is pulled from. And thinking about that, I may change my design slightly. Instead of a list with lists coming off of it, I may just have everyone in a list, and use another method for tracking family. This would avoid the headache of reorganizing the list when a new head of household surfaces. I could track it by storing IDs in the Player class, possibly. Maybe an int for spouse and an array of ints for children.
    There should be no difference between storing an ID (i.e. array index) and a *Player pointer to the actual memory address of the Player.

    Goetterdaemmerung on
  • Sir CarcassSir Carcass I have been shown the end of my world Round Rock, TXRegistered User regular
    edited February 2010
    I was actually wanting the list to have all of the characters past and present. The array is what will hold the current "players", but I'm thinking of having the list be where data is pulled from. And thinking about that, I may change my design slightly. Instead of a list with lists coming off of it, I may just have everyone in a list, and use another method for tracking family. This would avoid the headache of reorganizing the list when a new head of household surfaces. I could track it by storing IDs in the Player class, possibly. Maybe an int for spouse and an array of ints for children.
    There should be no difference between storing an ID (i.e. array index) and a *Player pointer to the actual memory address of the Player.

    Yeah, that would actually be better, too, since I wouldn't have to search the list for it.

    Sir Carcass on
  • Sir CarcassSir Carcass I have been shown the end of my world Round Rock, TXRegistered User regular
    edited February 2010
    So what exactly is the difference between
    PC.getName()
    
    and
    PC->getName()
    

    Is -> used when you're dealing with a pointer?

    Sir Carcass on
  • CelestialBadgerCelestialBadger Registered User regular
    edited February 2010
    So what exactly is the difference between
    PC.getName()
    
    and
    PC->getName()
    

    Is -> used when you're dealing with a pointer?

    Yes.
    I always wanted to be a Vorlon...

    CelestialBadger on
  • SavantSavant Simply Barbaric Registered User regular
    edited February 2010
    So what exactly is the difference between
    PC.getName()
    
    and
    PC->getName()
    

    Is -> used when you're dealing with a pointer?

    Yes, you use -> when you are trying to access a member of a class that your pointer is pointing too. It's basically a shorthand for dereferencing the pointer then doing the member access. So, assuming that PC is a pointer to an object with a member function getName(), the following two expressions have the same results if there is no operator overloading going on:
    (*PC).getName()
    
    PC->getName()
    

    Savant on
  • Sir CarcassSir Carcass I have been shown the end of my world Round Rock, TXRegistered User regular
    edited February 2010
    So I think pointers are starting to stick. Earlier today I was trying to think of a way to get to a person's info through another person (ID of Spouse is now stored in Player class) and it finally dawned on me. Create a function that you pass an ID to and it searches the list and returns the pointer. I tried and it and sure enough it worked. I had earlier written a function to return the name of a spouse based on the husband's ID, so I was able to delete that and just use the pointer function to get the name directly. I also now have the main list of people, a PC instance that points to the first item in the list, a size 4 array for NPCs that also contain pointers, and a separate 4 person list (for keeping track of current intelligence).

    To quote a (more than likely) great man, "It only ends once. Everything else is just progress."

    Sir Carcass on
  • ZekZek Registered User regular
    edited February 2010
    I think you're confused about arrays vs. linked lists - they are both just structures for holding data. You can store pointers in an array just as easily as you can in a linked list, although the syntax is a little confusing:

    Player *people[5] = {ptr1, ptr2, ptr3, ptr4, pt5};

    That declares an array of five pointers. So to retrieve the first player in the array you simply type *people[0]. people[0] for the pointer, * to dereference it. You're not actually storing the data "in" anything, just references to it.

    Zek on
  • ZekZek Registered User regular
    edited February 2010
    Also it doesn't really make sense to store the list logic inside the Player class itself - traditionally a linked list is its own class representing one node, like so:
    class ListNode {
      public:
        Player value;
        ListNode *next;
    }
    

    The list nodes reference eachother to form the list structure, and each node has a player as its value. Not only is this much more flexible but it also means that you are using an actual list object in your code when you want a list, and not using the Player class for multiple purposes. To use the list you store a pointer to the head ListNode and iterate through that when you want to find something.

    Zek on
  • Sir CarcassSir Carcass I have been shown the end of my world Round Rock, TXRegistered User regular
    edited February 2010
    Zek wrote: »
    I think you're confused about arrays vs. linked lists - they are both just structures for holding data. You can store pointers in an array just as easily as you can in a linked list, although the syntax is a little confusing:

    Player *people[5] = {ptr1, ptr2, ptr3, ptr4, pt5};

    That declares an array of five pointers. So to retrieve the first player in the array you simply type *people[0]. people[0] for the pointer, * to dereference it. You're not actually storing the data "in" anything, just references to it.

    Uh, yeah. That's what I said.

    And putting the list stuff in the class you want to link is kinda how I learned. I understand the utility of a node class, but this works for me since I only add it to classes I plan on linking.

    Sir Carcass on
  • ZekZek Registered User regular
    edited February 2010
    What I mean is that if you're using an array already the list node is redundant. You can just assign a new Player to one of the pointers in the array and you're set - it's stored in memory and you have a pointer to it. No need to actually store it the object itself in a class.

    And yeah it works but it doesn't really make sense - it's important to write clear and logical code, otherwise it'll start confusing even you when you try to wrap your head around it all, and you'll get more bugs and mistakes.

    Zek on
  • TejsTejs Registered User regular
    edited February 2010
    Also, depending on your usage levels, just resizing an array and copying the data might be simpler than implementing a linked list for your app if the player + npc list is not going to be changing often.

    Tejs on
  • PracticalProblemSolverPracticalProblemSolver Registered User regular
    edited February 2010
    And putting the list stuff in the class you want to link is kinda how I learned. I understand the utility of a node class, but this works for me since I only add it to classes I plan on linking.

    While it might be easier in the short term to do it your way, in the long run it will be easier to have done it the correct way from the beginning. For instance: you decide you want to put a player into two separate lists instead of a list and an array.

    PracticalProblemSolver on
  • Sir CarcassSir Carcass I have been shown the end of my world Round Rock, TXRegistered User regular
    edited February 2010
    And putting the list stuff in the class you want to link is kinda how I learned. I understand the utility of a node class, but this works for me since I only add it to classes I plan on linking.

    While it might be easier in the short term to do it your way, in the long run it will be easier to have done it the correct way from the beginning. For instance: you decide you want to put a player into two separate lists instead of a list and an array.

    Dude, the way I'm doing it isn't incorrect, it's just a different method of doing it. When I say that's how I was introduced to linked lists, it was in a college C++ course, not from fumbling around a website or something. Yes, we also learned how to write a Node class. And yes, that's a good example of needing to separate it, but I won't need 2 separate lists of the same players with what I'm doing. I appreciate the advice, but a little less condescension please.

    And I think maybe you guys are misunderstanding me. As of my latest design, I have one list (well, two, but I need two separate ones) with a head pointer, a single PC pointer to the first element in the list, and an NPC pointer array to the next four people in the list, at the beginning of the game. The array data will change as houses are killed off or replaced. I stopped copying data to two different places. I need to be able to reference NPC1, who is in column 1 in the opponent data screen, etc. Yeah, I guess I could have a 4 person list, but replacing NPC[2] with a pointer is much easier for me than reordering a list with a new member.

    Sir Carcass on
  • ZekZek Registered User regular
    edited February 2010
    I'm not trying to flame you or anything, but in programming there's a big difference between "it works" and "correct." To do something really weird like that you need a compelling reason and in this case there isn't one. A Player is a player, not a list, so it shouldn't have list logic(although it should contain a list of its family members). Object-oriented programming is all about conceptualizing things as distinct objects that serve their own functions and not bundling unrelated code together. For example if you make a function that returns the number of players in a list and it takes a Player as an argument, any normal human would just scratch their head and baffle over what it does.

    Zek on
  • GoetterdaemmerungGoetterdaemmerung Registered User regular
    edited February 2010
    There's also a lot to be said for learning *why* some things "work" but aren't "correct". While reading suggestions will always help, if this is the very first time he's done X, maybe he should do X and (maybe) realize later why X is bad and the suggestions were right.

    I think that works a lot better than simply following internet advice as some kind of axiom. The best we can do is tell him how to do what he wants, and suggest what we might do given the incomplete picture we have.

    Goetterdaemmerung on
  • Sir CarcassSir Carcass I have been shown the end of my world Round Rock, TXRegistered User regular
    edited February 2010
    Zek wrote: »
    For example if you make a function that returns the number of players in a list and it takes a Player as an argument, any normal human would just scratch their head and baffle over what it does.

    Maybe it's my "inexperience" talking, but to me, passing the head of a list to a function that returns the number of items in the list makes perfect sense.

    Sir Carcass on
  • ZekZek Registered User regular
    edited February 2010
    Zek wrote: »
    For example if you make a function that returns the number of players in a list and it takes a Player as an argument, any normal human would just scratch their head and baffle over what it does.

    Maybe it's my "inexperience" talking, but to me, passing the head of a list to a function that returns the number of items in the list makes perfect sense.

    That's just it, it's not the head of a list. It's a Player. Nobody would suspect that it also contains list functionality by looking at its name. The "next" pointer has no inherent meaning in the definition of a Player, it's something that belongs in outside logic.

    Zek on
  • GoetterdaemmerungGoetterdaemmerung Registered User regular
    edited February 2010
    I have to agree (think this got mentioned before though). It's good practice to keep unrelated ideas (the idea of a Player, and the idea of a list) separate.

    Goetterdaemmerung on
  • CelestialBadgerCelestialBadger Registered User regular
    edited February 2010
    Maybe it's my "inexperience" talking, but to me, passing the head of a list to a function that returns the number of items in the list makes perfect sense.

    I seem to recall seeing the same sort of thing in academic examples, too. But that's not generally how people actually do it in the real world, which in my experience is more similar to Zek's way.

    Your way is good enough though, so carry on. I did a whole load of crazy things when I was learning. You can worry all day whether it is correct or not. It's better to plough on and do it.

    CelestialBadger on
  • JNighthawkJNighthawk Registered User regular
    edited February 2010
    Zek wrote: »
    Zek wrote: »
    For example if you make a function that returns the number of players in a list and it takes a Player as an argument, any normal human would just scratch their head and baffle over what it does.

    Maybe it's my "inexperience" talking, but to me, passing the head of a list to a function that returns the number of items in the list makes perfect sense.

    That's just it, it's not the head of a list. It's a Player. Nobody would suspect that it also contains list functionality by looking at its name. The "next" pointer has no inherent meaning in the definition of a Player, it's something that belongs in outside logic.

    Stop it. Plenty of real world applications do in-object linked lists. It's a preference, with neither way being right or wrong. Make your suggestions, but don't call something out as wrong when it isn't. A big plus for keeping list management inside of the class itself is that you have a single spot for a memory footprint, rather than splitting it into a couple of places.

    JNighthawk on
    Game programmer
  • ZekZek Registered User regular
    edited February 2010
    JNighthawk wrote: »
    Zek wrote: »
    Zek wrote: »
    For example if you make a function that returns the number of players in a list and it takes a Player as an argument, any normal human would just scratch their head and baffle over what it does.

    Maybe it's my "inexperience" talking, but to me, passing the head of a list to a function that returns the number of items in the list makes perfect sense.

    That's just it, it's not the head of a list. It's a Player. Nobody would suspect that it also contains list functionality by looking at its name. The "next" pointer has no inherent meaning in the definition of a Player, it's something that belongs in outside logic.

    Stop it. Plenty of real world applications do in-object linked lists. It's a preference, with neither way being right or wrong. Make your suggestions, but don't call something out as wrong when it isn't. A big plus for keeping list management inside of the class itself is that you have a single spot for a memory footprint, rather than splitting it into a couple of places.

    Plenty of real-world programmers write crazy unreadable code too. I think the vast majority of applications don't have such strict performance requirements that it's worth micromanaging stuff like that at the expense of readability.

    Zek on
  • bowenbowen How you doin'? Registered User regular
    edited February 2010
    If you're looking at his entire object and class layout, it can be confusing. For someone writing an app for fun and speediness, it's ultimately pointless. Since he's making good progress, it shouldn't matter. And in 2 years from now when he revisits it, he'll go "wow that was dumb" and redo it. That is, after all, how people learn.

    I've never seen a programmer hold good standards 100% of the time. Ever. Well, at least not one that ever accomplished much more than "Hi there, this is what's in my file:".

    bowen on
    not a doctor, not a lawyer, examples I use may not be fully researched so don't take out of context plz, don't @ me
Sign In or Register to comment.