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/

C++ Question

Sir CarcassSir Carcass I have been shown the end of my worldRound Rock, TXRegistered User regular
edited February 2010 in Help / Advice Forum
Is it possible to have a variable in a variable name?

I have some global instances of a class, NPC1, NPC2, NPC3, etc. I'm writing a function that will display detailed stats for an NPC. I was hoping to be able to pass an integer, like 4, and have the function show the stats of NPC4. I don't know if something like NPC<npcInt>.getName() is possible.

If not, how could I do this? Can I pass a global object through a function? I guess I could set them up as a linked list, which I may end up doing, but it seems a little overkill.

Sir Carcass on

Posts

  • GanluanGanluan Registered User regular
    edited February 2010
    Reflection can do this for you.

    I know exactly how to do this in C# but imagine in C++ it's similar. Look for a method that gives you access to a variable or object based on its string name. This is usually accomplished by instantiating a reflected instance of the assembly you are working in, which gives you access to all of your own assembly's metadata. You can then access your objects by concatenating NPC + number.

    Reflection is discouraged at times for its implications on performance, but as long as you don't do something like this in a performance-intensive loop it shouldn't be an issue.

    Sorry if that was a bit vague, I'm more familiar with .NET now.

    That being said, having global instances of classes that are all the same and just differ in the data they hold should probably be encapsulated in some kind of collection class which will handle some of this for you based purely on indexing.

    Ganluan on
  • CelestialBadgerCelestialBadger Registered User regular
    edited February 2010
    What you want to do is not easily possible in C++. Your idea about the linked list is good. It's not overkill. Use the STL (Standard Template Library) which has them built in.

    CelestialBadger on
  • CelestialBadgerCelestialBadger Registered User regular
    edited February 2010
    Ganluan wrote: »
    I know exactly how to do this in C# but imagine in C++ it's similar. Look for a method that gives you access to a variable or object based on its string name. This is usually accomplished by instantiating a reflected instance of the assembly you are working in, which gives you access to all of your own assembly's metadata. You can then access your objects by concatenating NPC + number.

    Woo. That's not the easy option. I'm not even sure it's possible. For an inexperience coder like the OP it would be impossible.

    CelestialBadger on
  • CelestialBadgerCelestialBadger Registered User regular
    edited February 2010
    Did some further research. C++ does not support reflection.

    CelestialBadger on
  • Sir CarcassSir Carcass I have been shown the end of my world Round Rock, TXRegistered User regular
    edited February 2010
    I wouldn't say I was inexperienced.... :cry: This is just something I've never dealt with. I've never used the built in stuff as I've always written my own, but this might be a good time to check it out.

    Sir Carcass on
  • CelestialBadgerCelestialBadger Registered User regular
    edited February 2010
    I wouldn't say I was inexperienced.... :cry: This is just something I've never dealt with. I've never used the built in stuff as I've always written my own, but this might be a good time to check it out.

    Sorry, didn't mean to insult you. I'm not experienced enough to attempt what Ganluan suggested in C++ ... and I've been using the language 20 years. C++ does not have a lot of the features of more modern languages, but it makes up for them in speed and efficiency.

    CelestialBadger on
  • CelestialBadgerCelestialBadger Registered User regular
    edited February 2010
    Check this out:

    http://www.cplusplus.com/reference/stl/vector/

    You can use a simple array if the number of NPCs never varies.

    CelestialBadger on
  • GanluanGanluan Registered User regular
    edited February 2010
    Wow my bad, I'm too used to the newer .NET and OO languages that I didn't realize C++ can't do reflection. My other comment about using a collection of some type still stands though :P

    Ganluan on
  • Sir CarcassSir Carcass I have been shown the end of my world Round Rock, TXRegistered User regular
    edited February 2010
    The more I think about it, the more I think a linked list might just be better. Basically, each "NPC" will represent the head of a house. I think I'll also have a list or tree connected to each one to track their offspring. I was mainly just curious if something like I originally asked was possible, even though I figured it wasn't.

    Sir Carcass on
  • JasconiusJasconius sword criminal mad onlineRegistered User regular
    edited February 2010
    Why don't you just assign an ID property to your NPC objects and loop through an array of NPC's, attempting to match a given ID?


    I mean, that's what you are describing. Matching an object to a token. Which is what ID's are.

    Jasconius on
  • bowenbowen How you doin'? Registered User regular
    edited February 2010
    You can do what you want, but it wouldn't work the same way as it would in other languages.

    You could have a map data structure in C++ that has a variable name as it's key and a pointer to a object as it's value. This is all very basic and I haven't implemented it, but it's theoretically possible.

    That way you could do something like:
    (NPC["steven"]).DoAction();
    

    STL map for more information. However for a small project a linked list isn't out of the question either. Keep in mind Big O notation for searching/insertion/modification though when using data structures -- neither of these might be the best.

    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
  • Sir CarcassSir Carcass I have been shown the end of my world Round Rock, TXRegistered User regular
    edited February 2010
    Well, the problem with that is that NPC1, NPC2, NPC3, and NPC4 represent your 4 opponents, which will change throughout the game as you move on or people die. Adding an ID will help with other things, though.

    Ah, the joys of designing by the seat of your pants.

    Sir Carcass on
  • GanluanGanluan Registered User regular
    edited February 2010
    I gotta say, things like this make me love C#.

    Ganluan on
  • bowenbowen How you doin'? Registered User regular
    edited February 2010
    Maps probably work perfectly for what you want because you could do something like what you posted in the OP:
    (npcs[5]).GetName();
    

    It's probably the way I'd recommend to do it in most languages that support maps (dictionaries in .NET). You're basically looking for key/value pairs and the key can be anything and so can the value.

    Technically you could use the user as a key and ouput a map to npcs to get their names:
    ((user["Carcass"]).GetNPC()[1]).GetName();
    
    

    That may or may not be valid code but you get the idea.

    In your case the key is a number and the value is a pointer to an NPC object I'm guessing.

    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
  • JasconiusJasconius sword criminal mad onlineRegistered User regular
    edited February 2010
    This sounds like the kind of thing that could be easily solved by biting the bullet and putting in a switch statement with a line for each potential input.

    If you have 4 and only 4 entities to choose from, it's no more "bad" than what you've already done by painting yourself into doing reflection ;)

    Reflection, in my opinion, is something to be avoided unless you have no other reasonable alternative. Even if it means writing maybe 15 more lines of code to deal with it.

    Jasconius on
  • bowenbowen How you doin'? Registered User regular
    edited February 2010
    Yeah avoid reflection like the plague, there's almost no need for it in practice unless you're taking advantage of runtime loading of assemblies. Even then, the headache just isn't worth it most of the time.

    The solution I gave is about 100x less complicated although not quite as simple as the switch statement. Plus, headaches, and all.

    I actually changed a system that used reflection, recently, into one that used a simple scripting engine (moving towards a LUA based one) and was easier to debug issues.

    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
  • His CorkinessHis Corkiness Registered User regular
    edited February 2010
    Ganluan wrote: »
    I gotta say, things like this make me love C#.
    There is literally nothing about C# that would make this problem significantly easier to solve (Reflection, in fact, would make it harder). No offense to the OP, but this is a trivial problem. Use one of the STL data structures. A std::vector is basically an array that you don't need to worry about the size of. Which structure you use depends on how the objects are going to be accessed. If you post a little more info about your program, it'd be easier to recommend one.

    His Corkiness on
  • GanluanGanluan Registered User regular
    edited February 2010
    While it doesn't solve the OP's problem, I do find it strange people still think Reflection is "bad".

    I use it pretty extensively in an enterprise-level app that has strict speed requirements. It allows me to write one data layer class with a handful of methods that will handle any of hundreds of tables and their associated operations. It's pretty easy to debug too, at least using Visual Studio. It allows for dramatically more scalable apps (in the right scenarios, of course). I work directly with MS partners at times and they actually recommended a similar pattern using reflection.

    As for my comment about C#, I meant the fact that C++ doesn't have Reflection and doesn't support true OO functions that .NET and other languages like Ruby do.

    Ganluan on
  • Smug DucklingSmug Duckling Registered User regular
    edited February 2010
    Anywhere you have NPCX (where X is between 1 and 4) just replace it with NPC[X] and initialize the NPC array somewhere. Done. (And really, if you're calling variables things like var1, var2, etc, they should be in an array or list anyway.)

    Smug Duckling on
    smugduckling,pc,days.png
  • Smug DucklingSmug Duckling Registered User regular
    edited February 2010
    Ganluan wrote: »
    While it doesn't solve the OP's problem, I do find it strange people still think Reflection is "bad".

    I use it pretty extensively in an enterprise-level app that has strict speed requirements. It allows me to write one data layer class with a handful of methods that will handle any of hundreds of tables and their associated operations. It's pretty easy to debug too, at least using Visual Studio. It allows for dramatically more scalable apps (in the right scenarios, of course). I work directly with MS partners at times and they actually recommended a similar pattern using reflection.

    As for my comment about C#, I meant the fact that C++ doesn't have Reflection and doesn't support true OO functions that .NET and other languages like Ruby do.

    I dislike it because it's reeeeally hard to figure out what code that relies heavily on reflection is actually doing. You can do retarded stuff like dynamically generating function names. Like:
    what_function_should_i_use(some args)(some more args)
    

    ugh. or
    ("render_" . $blah)()
    

    shudder

    What's worse is nothing like ctags or automated source analysis tools knows what to do with this stuff, so you're on your own. Confused. Please god just use inheritance. I admit that a lot of people use it. But I still can't imagine why.

    When it makes sense to me are for things like django, where they have dynamic function argument names, which can be used to filter database queries:
    Model.objects.get(modelproperty1_iexact="foo", modelproperty2_lt=3)
    

    Smug Duckling on
    smugduckling,pc,days.png
  • BoredomBoredom Registered User regular
    edited February 2010
    Jasconius wrote: »
    Why don't you just assign an ID property to your NPC objects and loop through an array of NPC's, attempting to match a given ID?


    I mean, that's what you are describing. Matching an object to a token. Which is what ID's are.


    I haven't read the entire thread so don't kill me if this has been said already.

    But a HashMap or HashTable sounds ideal for this. It's sort of a "black box" type of list. Instead of looping through it to find what you want, you just pass a key value (say, "NPC4") and it'll return the object you want. This is highly efficient and internally there is a minimum of looping.

    http://en.wikipedia.org/wiki/Hash_table


    I'd recommend looking at a 3rd party implementation. I hear Boost offers a Hash Table implementation, but I haven't tried it and I haven't used C++ in ages.

    Boredom on
  • ecco the dolphinecco the dolphin Registered User regular
    edited February 2010
    Hey, I'm assuming that you've got something like:

    CNPCData NPC1, NPC2, NPC3, NPC4;

    Have you considered going:

    CNPCData NPC[4];

    So that you can just go:
    CNPCData *GetNPC(int nNPCNumber)
    {
      if((nNPCNumber < <0) || (nNPCNumber >= 4))
        return NULL;
    
      return &(NPC[nNPCNumber]);
    }
    

    ?

    ecco the dolphin on
    Penny Arcade Developers at PADev.net.
  • bowenbowen How you doin'? Registered User regular
    edited February 2010
    Boredom wrote: »
    Jasconius wrote: »
    Why don't you just assign an ID property to your NPC objects and loop through an array of NPC's, attempting to match a given ID?


    I mean, that's what you are describing. Matching an object to a token. Which is what ID's are.


    I haven't read the entire thread so don't kill me if this has been said already.

    But a HashMap or HashTable sounds ideal for this. It's sort of a "black box" type of list. Instead of looping through it to find what you want, you just pass a key value (say, "NPC4") and it'll return the object you want. This is highly efficient and internally there is a minimum of looping.

    http://en.wikipedia.org/wiki/Hash_table


    I'd recommend looking at a 3rd party implementation. I hear Boost offers a Hash Table implementation, but I haven't tried it and I haven't used C++ in ages.

    A Hash table is very similar to mapping and dictionaries. Except now you have to worry about collision data, which is always a pain.

    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
  • Sir CarcassSir Carcass I have been shown the end of my world Round Rock, TXRegistered User regular
    edited February 2010
    Hey, I'm assuming that you've got something like:

    CNPCData NPC1, NPC2, NPC3, NPC4;

    Have you considered going:

    CNPCData NPC[4];

    So that you can just go:
    CNPCData *GetNPC(int nNPCNumber)
    {
      if((nNPCNumber < <0) || (nNPCNumber >= 4))
        return NULL;
    
      return &(NPC[nNPCNumber]);
    }
    

    ?

    Using an array might actually be best. I don't know why I didn't think of that to begin with.

    Sir Carcass on
  • GanluanGanluan Registered User regular
    edited February 2010
    When it makes sense to me are for things like django, where they have dynamic function argument names, which can be used to filter database queries:
    Model.objects.get(modelproperty1_iexact="foo", modelproperty2_lt=3)
    

    I'm actually using it for something similar - for example, I have a method that dynamically maps one object to another, completely different object (like an ORM lite) and it uses reflection to determine property names/values so it can map appropriately.

    Even if you use something like Custom Attributes in C#, you're likely using Reflection.

    Ganluan on
  • BoredomBoredom Registered User regular
    edited February 2010
    bowen wrote: »
    Boredom wrote: »
    Jasconius wrote: »
    Why don't you just assign an ID property to your NPC objects and loop through an array of NPC's, attempting to match a given ID?


    I mean, that's what you are describing. Matching an object to a token. Which is what ID's are.


    I haven't read the entire thread so don't kill me if this has been said already.

    But a HashMap or HashTable sounds ideal for this. It's sort of a "black box" type of list. Instead of looping through it to find what you want, you just pass a key value (say, "NPC4") and it'll return the object you want. This is highly efficient and internally there is a minimum of looping.

    http://en.wikipedia.org/wiki/Hash_table


    I'd recommend looking at a 3rd party implementation. I hear Boost offers a Hash Table implementation, but I haven't tried it and I haven't used C++ in ages.

    A Hash table is very similar to mapping and dictionaries. Except now you have to worry about collision data, which is always a pain.

    This is true, I agree. In fact your suggestion seems ideal for what the OP wants to do.

    I hadn't read your post when I wrote that, and I've been away from C++ long enough that I don't remember this stuff. Out of curiosity - in what situation would hash tables be better than maps?

    I mean, in a hash table, I believe the hash output of the input "key" object is what serves as the index for the object you want. I wonder how it's implemented internally in a map - is the key simply transformed into something other than a hash, which is guaranteed to not collide with anything else?

    Boredom on
  • bowenbowen How you doin'? Registered User regular
    edited February 2010
    Hash tables tend to be better when you need speed.

    It's a lot easier to search for '12124122' or '13' or find their order than it is for 'StevenQ'. So long as your hashing function is top notch and you deal with duplicate numbers gracefully. He'd probably be okay with a hash table since he's natively looking at numbered data right now anyways.

    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.