将 bool 变量作为参数传递的更好方法?

Better way to pass bool variable as parameter?

我想知道是否有更好的方法来编写它以获得更好的可读性。 如果您有如下功能,

void animal(bool hasFourLegs, bool hasHead, bool hasBody);

当你调用这个函数时,你最终会得到类似

的东西
animal(true, false, true);

这让我每次遇到这样的函数都会去看看定义。

所以...

我就是这样做的!

const bool HAS_FOURLEGS = true;
const bool NO_HEAD = false;
const bool HAS_BODY = true;

animal(HAS_FOURLEGS, NO_HEAD, HAS_BODY);

但我不喜欢在每次调用函数时都声明const bool

CPP 好像不支持

animal(bool hasFourlegs = true, bool hasHead = false, bool hasBody = true);

有没有更好更短的方法?

使用标志:

  enum {
    HAS_LEGS = 0x01,
    HAS_HEAD = 0x02,
    HAS_BODY = 0x04,
  };

  void animal(int properties);

  animal(HAS_LEGS | HAS_HEAD);

当我 运行 遇到与此相关的问题时,我有时会创建一个 enum 即使只有 2 个预期选择:

例如,代替下面的函数声明:

bool search(..., bool recursive);

我会选择:

enum class SearchOpt
{
    Recursive,
    NonRecursive
};

bool search(..., SearchOpt opt);

因此,调用语法更改为:

bool found = search(..., true);

至:

bool found = search(..., SearchOpt::Recursive);

注意:这样可以避免每次调用该函数时都必须创建自己的常量。

编辑

正如其他人所建议的那样,与其为每个选项设置单独的 bool 并因此为每个选项设置单独的 enum,不如将单个 enum 配置为 bit旗帜。

评论是你的朋友!

animal(   true,   //hasFourLegs
          false,  //hasHead
          true    //hasBody
      );

您可以使用按位值,如下所示:

const int hasLegs = 0x01;
const int noHead = 0x02;
const int hasBody = 0x04;

然后调用 animal 并使用以上任意组合,例如: 动物(有腿+有身体);

Decalre animal 带有一个 int 参数。

inside `animal`, test the bits:
if (parameter & haasBody)
{
    // it has a body....
}

另一种选择是使用 class 在它们密切相关的地方保存参数:

struct AnimalOptions {
  bool hasHead, hasBody, hasLegs;
  AnimalOptions() : hasHead(false), hasBody(false), hasLegs(false);
}

...

AnimalOptions opt;
  opt.hasHead = true;

  animal(opt);

只要您的函数似乎采用了一堆具有相同类型的参数,而且它们的顺序不容易记住,这种技术就会很有用。当您的函数需要几个 int 时,它同样有用。

奇怪,没有人建议来自 Boost.parameter 的命名参数:http://www.boost.org/doc/libs/1_59_0/libs/parameter/doc/html/index.html

作为其他答案的替代方案,我喜欢 tagged_bool that Andrzej Krzemieński 在他的博客上提出的。

C++20 将 designated initializers 作为聚合初始化的一部分。您可以使用布尔参数创建结构并按值传递结构。您甚至可以使用默认参数值。

struct AnimalParts {
    bool hasFourLegs = false;
    bool hasHead = true;
    bool hasBody = true;
}

void animal(AnimalParts parts);

然后像这样使用它:

animal({.hasFourLegs = true, .hasHead = false});

这与您建议的命名参数习语非常接近。在编译方面,这两个选项似乎都产生了可比较的输出,参见 Godbolt.

我不确定这是正确的做法,但我还是忍不住要分享这个想法。

让我们假设该函数不是您的,而是来自一些难以更改的流行API。

void animal(bool hasFourLegs, bool hasHead, bool hasBody);

在这种情况下,可以这样调用它:

animal(bool("hasFourlegs"), !bool("hasHead"), bool("hasBody"));

C-string始终是一个非零指针,转换为true

一个可能的缺点是编译时间...? 另一个是代码行长度的增加...