أنشئ قائمة بالمتغيرات الخاصة القابلة للتغيير من خلال وظيفة عامة في لغة C++
-
20-12-2019 - |
سؤال
لدي حوالي 20 منطقيًا خاصًا داخل فصل دراسي في لغة C++.أود أن تكون متاحة للعامة باستخدام وظيفة (عامة).
هل من الممكن تمرير اسم متغير (خاص) كوسيطة لمثل هذه الوظيفة؟على سبيل المثال،
void setTrue(std::string varName)
{
someFunctionToConvertStringToVariable = true;
}
بدلا من ذلك، أعتقد ذلك
void setTrue(std::string varName)
{
if (varName == "boolA")
{
boolA = true;
}
else if (varName == "boolB")
{
boolB = true;
}
}
ستعمل، ويمكن استخدام switch(varName)
لتقليل عدد LOC اللازم.
من المفترض أن يكون هناك خيار آخر يتمثل في جعل جميع القيم المنطقية عامة، ثم الوصول إليها باستخدام myClass.boolA = true;
من برنامج الاتصال - لست متأكدًا من أن هذه هي أفضل فكرة، لكنها بالتأكيد أبسط، وهذه حجة لصالحها.
هل هناك طريقة مقبولة/أفضل بشكل عام للقيام بهذا النوع من الأشياء؟هل قمت للتو بإعداد المشكلة بشكل سيء وهل هناك طريقة أكثر ذكاءً للقيام بذلك؟ربما ا enum
من varnames سيسمح بفحص المتغيرات التي تم تمريرها، لكنني لا أعتقد أن ذلك سيجعل من السهل بالضرورة تعيين القيمة المنطقية.
المحلول
يمكنك استخدام أ std::map<std::string, bool>
لتخزين bool
قيم.ثم،
void setTrue(std::string varName)
{
// Add some checks to make sure that varName is valid.
varNames[varName] = true;
}
نصائح أخرى
إذا كانت قائمة هذه المتغيرات لن تتغير، فيمكنني أن أقترح عليك استخدام عامل التعداد وتجاوز النص المنخفض:
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];
}
إنها غير قابلة للتوسيع في وقت التشغيل ولكنها ستمنحك أمانًا أفضل في وقت الترجمة من الخرائط.
الحل الثاني هو الطريق للذهاب هنا، ومع ذلك أعتقد أن حالة التبديل لا تقلل من LOC, بجانب حقيقة ذلك لن يعمل مع `std::string!
void setTrue(const std::string& varName)
{
if (varName == "boolA")
{
boolA = true;
}
else if (varName == "boolB")
{
boolB = true;
}
}
ضد:
void setTrue(const std::string& varName)
{
switch(str2int (varName))
{
case str2int ("boolA"):
boolA = true;
break;
case str2int("boolB"):
boolB = true;
break;
default:
assert (false);
}
}
وتذكر أنه إذا كنت لا ترغب في تعديل المعلمة التي تم تمريرها، فمن الجيد تمريرها كـ const
!في هذه الحالة سأمررها شخصيًا على أنها const
مرجع.
عشرين bool
هو الكثير، في الواقع.
بدلا من ذلك، أنصح باستخدام bitset
مفهرسة بالثوابت (باستخدام enum
على سبيل المثال).بافتراض 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
ملحوظة:يتم تنفيذ جميع عمليات الوصول خارج النطاق بواسطة bitset
, ، مفيد أليس كذلك؟