Make a list of private variables changeable through a public function in C++
-
20-12-2019 - |
Question
I have about 20 private bools within a class in C++. I would like for these to be publicly accessible using a (public) function.
Is it possible to pass the name of a (private) variable as an argument to such a function? For example,
void setTrue(std::string varName)
{
someFunctionToConvertStringToVariable = true;
}
Alternatively, I think that
void setTrue(std::string varName)
{
if (varName == "boolA")
{
boolA = true;
}
else if (varName == "boolB")
{
boolB = true;
}
}
would work, and could use a switch(varName)
to reduce the number of LOC needed.
Another option would presumably be to just make all of the booleans public, and then access them using myClass.boolA = true;
from the calling program - I'm not sure this is the best idea, but it's certainly simpler, and so that's an argument in its favour.
Is there a generally accepted/best way to do this type of thing? Have I just set up the problem badly and is there a much smarter way to go about this? Perhaps an enum
of varnames would allow passed variables to be checked, but I don't think that would necessarily make it easier to set the boolean.
Solution
You can use a std::map<std::string, bool>
to store the bool
values. Then,
void setTrue(std::string varName)
{
// Add some checks to make sure that varName is valid.
varNames[varName] = true;
}
OTHER TIPS
If the list of these variables isn't going to change, I can propose you to use enumeration and overriden subscript operator:
enum MyBools
{
First = 0,
BoolA = First,
BoolB,
//...
Bool20,
Last = Bool20,
}
class MyIndexedBools
{
private:
bool m_Bools[MyBools::Last + 1];
public:
bool& operator[] (MyBools index);
};
bool& operator[] (MyBools index);
{
if (index < First || index > Last)
throw "error";
return m_Bools[index];
}
It is not extensible in runtime but will give you better compile-time safety than maps.
Your second solution is the way to go here, however I think that the switch case does not reduce the LOC, beside the fact that it won't work with an `std::string!
void setTrue(const std::string& varName)
{
if (varName == "boolA")
{
boolA = true;
}
else if (varName == "boolB")
{
boolB = true;
}
}
VS:
void setTrue(const std::string& varName)
{
switch(str2int (varName))
{
case str2int ("boolA"):
boolA = true;
break;
case str2int("boolB"):
boolB = true;
break;
default:
assert (false);
}
}
And keep in mind that if you do not want to modify the passed parameter it is good practice to pass it as const
! In that case I'd personally pass it as const
reference.
Twenty bool
is a lot, indeed.
Instead, I would advise using a bitset
indexed with constants (using enum
for example). Assuming C++11:
class SomeClass {
public:
enum class Flag: size_t {
Flag1,
Flag2,
Flag3,
...,
Flag20
};
bool get_flag(Flag f) const { return _flags.test(size_t(f)); }
void set_flag(Flag f, bool value) { _flags.set(size_t(f), value); }
private:
std::bitset<size_t(Flag20) + 1> _flags;
}; // class SomeClass
Note: all out of range accesses are carried out by bitset
, handy isn't it ?