在 C++ 中,基于 class 中的参数查看私有变量的访问器方法?
Accessor Method to view private variable based on argument in a class in c++?
我的问题是我的 class 中有很多变量,我希望通过访问器方法访问它们。当然,我可以有多个访问器函数来输出我的私有变量,但我该怎么做才能通过参数访问其中的任何一个。我的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;
};
基本上我想知道的是如何 return 关于 outputInt 函数的私有变量。大多数 OOP 教程都有一个函数来 return 每个变量,这在大型程序中似乎是一件非常不健康的事情。
我不知道这对你来说是否是个好主意,但你可以使用通过引用传递的 public typedef 结构并设置你的值。
class Character {
public:
//...
typedef struct allvalues{
string vname;
int vhealth;
int vattackLevel;
int vdefenseLevel;
}allvalues;
void getValues(allvalues& val){
val.vname = name;
val.vhealth = health;
val.vattackLevel = attackLevel;
val.vdefenseLevel = detenseLevel;
}
//...
};
//...
//somewhere in the code
Character myCarac;
//...
//Here how to use it
Character::allvalues values;
myCarac.getValues(values);
C++ 不支持您尝试完成的任务:关于对象的反射或详细的运行时信息。在 C++ 中有一个叫做 "Run-Time Type Information" 的东西,但它不能提供关于你的变量名的信息:原因是因为在编译和链接的二进制文件中,这个信息(你的变量名)将不再存在。
但是,您可以使用 std::unordered_map 而不是普通整数变量来完成类似的事情。所以可以通过名称访问值,如字符串。
请考虑以下代码:
#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;
}
它将按预期输出:
Health: 10
Attack level: 100
Defense level: 1000
另一个不依赖于 unordered_map
的选项是,使用预定义的静态字符串作为变量名,使用数组或向量作为值。所以我们可以用类似的东西替换上面的 class Character
:
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];
};
并且仍然得到相同的输出。但是,在这里您必须手动管理一个列表,其中包含字符串数组中的所有变量名称 - 我不喜欢这个解决方案,个人更喜欢上面的其他解决方案之一。
C++ 中处理此类设计的最常见方法是使用单独的 getHealth()
、getAttackLevel()
、getDefenseLevel()
函数。但是这样会漏掉一个用例,就是:如果想让用户输入一个字符串,比如"health"
然后显示对应的变量,就需要自己写代码调用对应的getXXX()
函数。如果这不是您的问题,请考虑以下更简洁的代码:
#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;
}
另一个不相关的建议:不要使用字符串作为函数的参数类型,而是使用 const string&
(对字符串的常量引用;请参阅上面的示例代码)。这允许更轻松地调用您的函数(它们可以直接使用字符串文字调用,而无需在调用代码中创建额外的变量)并且它们不会进行额外的不必要的复制。然后唯一的副本将发生在:name = Sname;
(在您的代码中发生了两个副本)。
我的问题是我的 class 中有很多变量,我希望通过访问器方法访问它们。当然,我可以有多个访问器函数来输出我的私有变量,但我该怎么做才能通过参数访问其中的任何一个。我的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;
};
基本上我想知道的是如何 return 关于 outputInt 函数的私有变量。大多数 OOP 教程都有一个函数来 return 每个变量,这在大型程序中似乎是一件非常不健康的事情。
我不知道这对你来说是否是个好主意,但你可以使用通过引用传递的 public typedef 结构并设置你的值。
class Character {
public:
//...
typedef struct allvalues{
string vname;
int vhealth;
int vattackLevel;
int vdefenseLevel;
}allvalues;
void getValues(allvalues& val){
val.vname = name;
val.vhealth = health;
val.vattackLevel = attackLevel;
val.vdefenseLevel = detenseLevel;
}
//...
};
//...
//somewhere in the code
Character myCarac;
//...
//Here how to use it
Character::allvalues values;
myCarac.getValues(values);
C++ 不支持您尝试完成的任务:关于对象的反射或详细的运行时信息。在 C++ 中有一个叫做 "Run-Time Type Information" 的东西,但它不能提供关于你的变量名的信息:原因是因为在编译和链接的二进制文件中,这个信息(你的变量名)将不再存在。
但是,您可以使用 std::unordered_map 而不是普通整数变量来完成类似的事情。所以可以通过名称访问值,如字符串。 请考虑以下代码:
#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;
}
它将按预期输出:
Health: 10
Attack level: 100
Defense level: 1000
另一个不依赖于 unordered_map
的选项是,使用预定义的静态字符串作为变量名,使用数组或向量作为值。所以我们可以用类似的东西替换上面的 class Character
:
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];
};
并且仍然得到相同的输出。但是,在这里您必须手动管理一个列表,其中包含字符串数组中的所有变量名称 - 我不喜欢这个解决方案,个人更喜欢上面的其他解决方案之一。
C++ 中处理此类设计的最常见方法是使用单独的 getHealth()
、getAttackLevel()
、getDefenseLevel()
函数。但是这样会漏掉一个用例,就是:如果想让用户输入一个字符串,比如"health"
然后显示对应的变量,就需要自己写代码调用对应的getXXX()
函数。如果这不是您的问题,请考虑以下更简洁的代码:
#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;
}
另一个不相关的建议:不要使用字符串作为函数的参数类型,而是使用 const string&
(对字符串的常量引用;请参阅上面的示例代码)。这允许更轻松地调用您的函数(它们可以直接使用字符串文字调用,而无需在调用代码中创建额外的变量)并且它们不会进行额外的不必要的复制。然后唯一的副本将发生在:name = Sname;
(在您的代码中发生了两个副本)。