【问题标题】:Make a list of private variables changeable through a public function in C++通过 C++ 中的公共函数制作可更改的私有变量列表
【发布时间】:2014-07-29 05:18:49
【问题描述】:

我在 C++ 的一个类中有大约 20 个私有布尔值。 我希望这些可以使用(公共)功能公开访问。

是否可以将(私有)变量的名称作为参数传递给这样的函数? 例如,

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 of varnames 将允许检查传递的变量,但我认为这不一定会使设置布尔值更容易。

【问题讨论】:

  • 你可以有一个 20 个数组,而不是 20 个私有变量,并在公共成员函数中传递索引来更改。
  • 在一个班级中有 20 个私人 bools 是一种巨大的设计气味 - 这意味着您的班级设计糟糕,并且您尝试建模您正在解决的任何问题的方式都需要重新考虑.
  • 可能是真的,但它们适用于大约 10k 行代码,并且布尔值以if(boolA) cout<< "silly description of whats happening now"; 的方式进行管理。日志文件的长度根据设置的布尔值在多个数量级上有所不同,因此如果我只想找出某个部分的问题,将 most 设置为 false 会很有帮助。
  • 使它们可以从调用程序中更改对其他用户更有帮助,他们不想一遍又一遍地重新编译库,或者(更重要的是)想要更改值 mid程序,在 delta 时间段的循环中运行(即,程序在 t=30 秒时中断,前 29 秒不要发送垃圾日志)

标签: c++ private-members public-method


【解决方案1】:

您可以使用std::map<std::string, bool> 来存储bool 值。那么,

void setTrue(std::string varName)
{
    // Add some checks to make sure that varName is valid.

    varNames[varName] = true;
}

【讨论】:

  • 要去试试这个 - 怀疑这将是我需要的答案
  • 检查varname是否有效是通过检查map::find (key)的返回值而不是使用随机访问...如果它等于map::end它是无效的。
  • 正确答案,但请将 std::string 更改为 const ref 并使用 find
  • 正如其他人所指出的,std::map::operator [] 不应该在这里使用,因为如果varName 不存在,它会将其添加到varNames 中,这不是重点,使用std::map::find
  • 这当然是我要求的答案,因此将其标记为已接受。可能已经调查过了,我的问题并没有很好地提出,但这给了我一些研究/工作的东西。谢谢
【解决方案2】:

如果这些变量的列表不会改变,我可以建议你使用枚举和覆盖下标运算符:

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];
}

它在运行时不可扩展,但会比映射提供更好的编译时安全性。

【讨论】:

  • 枚举确实是一种方式。在 C++11 中,您可以精确地希望枚举将 size_t 作为后备存储,以便在转换为索引时不需要转换......并且还因为使用无符号存储 First 变得不必要。下一步是使用std::array
【解决方案3】:

您的第二个解决方案是去这里的方式,但是我认为 switch case 不会减少 LOC除了it won't work with an `std::string! p>

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);
    }
}

请记住,如果您不想修改传递的参数,最好将其传递为const!在这种情况下,我会亲自将其作为const 参考传递。

【讨论】:

  • 你错过了从上面的链接复制str2int实现
  • 我不是来复制代码的,这只是为了让大家了解一下 LOC.... >
【解决方案4】:

20 个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 执行的,是不是很方便?

【讨论】:

    猜你喜欢
    • 2011-03-03
    • 1970-01-01
    • 2013-03-18
    • 1970-01-01
    • 2012-05-29
    • 2010-09-20
    • 2016-01-09
    • 1970-01-01
    • 2011-05-25
    相关资源
    最近更新 更多