أنشئ قائمة بالمتغيرات الخاصة القابلة للتغيير من خلال وظيفة عامة في لغة C++

StackOverflow https://stackoverflow.com//questions/25008667

سؤال

لدي حوالي 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, ، مفيد أليس كذلك؟

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top