Q:

Accessor Method to view private variable based on argument in a class in c++?

My problem is that I have many variables in my class and I want them to be accessed via an accessor method. Of course I could have several accessor functions to output my private variables but how can I make it so I can access any of them via an argument. My class: 
class Character {
public:
    void setAttr(string Sname,int Shealth,int SattackLevel,int SdefenseLevel)  {
        name = Sname;
        health = Shealth;
        attackLevel = SattackLevel;
        defenseLevel = SdefenseLevel;

    }
    int outputInt(string whatToOutput)  {
        return whatToOutput //I want this to either be health, attackLevel or defenseLevel
    }

private:
    string name;
    int health;
    int attackLevel;
    int defenseLevel;
};

Basically what I want to know is how do I return a private variable in regards to the outputInt function. Most OOP tutorials have one function to return each variable which seems like a very unhealthy thing to do in a large program.

A:

C++ doesn't support what you try to accomplish: reflection or detailed runtime information about objects. There is something called "Run-Time Type Information" in C++, but it can't provide information about your variable name: the reason is because, in the compiled and linked binary this information (names of your variables) will not be necessarily present anymore. 
However, you can accomplish something close to that, using i.e. std::unordered_map instead of plain integer variables. So it's possible to access values by their names, as strings.
Please consider the following code:
#include <string>
#include <iostream>
#include <unordered_map>

using namespace std;

class Character {
public:
  void setAttr(const string& Sname, int Shealth, int SattackLevel, int SdefenseLevel) {
    name = Sname;
    values.insert(std::make_pair("health", Shealth));
    values.insert(std::make_pair("attackLevel", SattackLevel));
    values.insert(std::make_pair("defenseLevel", SdefenseLevel));
  }
  int outputInt(const string& whatToOutput) {
    return values.at(whatToOutput);
  }

private:
  string name;
  std::unordered_map<std::string, int> values;
};

int main(int argc, char* argv[]) {
  Character yourCharacter;
  yourCharacter.setAttr("yourName", 10, 100, 1000);
  std::cout << "Health: " << yourCharacter.outputInt("health") <<std::endl;
  std::cout << "Attack level: " << yourCharacter.outputInt("attackLevel") << std::endl;
  std::cout << "Defense level: " << yourCharacter.outputInt("defenseLevel") << std::endl;
  return 0;
}

It will output as expected:
Health: 10
Attack level: 100
Defense level: 1000

Another option without dependency on unordered_map would be, to use predefined static strings for your variable names and an array or vector for your values. So we could replace the class Character above with something like:
static std::string variableNames[3] = {
  "health",
  "attackLevel",
  "defenseLevel"
};

class Character {
public:
  void setAttr(const string& Sname, int Shealth, int SattackLevel, int SdefenseLevel) {
    name = Sname;
    variableValues[0] = Shealth;
    variableValues[1] = SattackLevel;
    variableValues[2] = SdefenseLevel;
  }
  int outputInt(const string& whatToOutput) {
    int retVal = 0;
    for (size_t i = 0; i < sizeof(variableNames)/sizeof(std::string); ++i) {
      if (!whatToOutput.compare(variableNames[i])) {
        retVal = variableValues[i];
      }
    }
    return retVal;
  }

private:
  string name;
  int variableValues[3];
};

And getting still same output. However, here you have to manage a list with all your variable names inside the string array manually - I don't like this solution and would prefer one of the others above personally.
Most common ways in C++ to handle such a design is to have seperate getHealth(), getAttackLevel(), getDefenseLevel() functions instead. However, this will miss one use-case, which is: if you want to let the user input a string, like i.e. "health" and display the corresponding variable then, you would need to write code by yourself to call the corresponding getXXX() function. If this is not a issue in your case, consider the following code which is much cleaner:
#include <string>
#include <iostream>

using namespace std;

class Character {
public:
  void setAttr(const string& Sname, int Shealth, int SattackLevel, int SdefenseLevel) {
    name = Sname;
    health = Shealth;
    attackLevel = SattackLevel;
    defenseLevel = SdefenseLevel;
  }
  int getHealth() const { return health; }
  int getAttackLevel() const { return attackLevel; }
  int getDefenseLevel() const { return defenseLevel; }
private:
  string name;
  int health, attackLevel, defenseLevel;
};

int main(int argc, char* argv[]) {
  Character yourCharacter;
  yourCharacter.setAttr("yourName", 10, 100, 1000);
  std::cout << "Health: " << yourCharacter.getHealth() <<std::endl;
  std::cout << "Attack level: " << yourCharacter.getAttackLevel() << std::endl;
  std::cout << "Defense level: " << yourCharacter.getDefenseLevel() << std::endl;
  return 0;
}

One other unrelated advice: Instead of using string as parameter types for your functions, use const string& (const reference to string; see my example code above). This allows easier calling of your functions (they can be called directly with an string literal without the need to create additional variables in the calling code) and they will not make a additional unnecessary copy. The only copy then will take place at: name = Sname; (in your code two copies took place).

