【问题标题】:c++ evaluate value of variable type bool dynamicallyc ++动态评估变量类型bool的值
【发布时间】:2018-07-10 19:56:54
【问题描述】:

情况:我正在尝试实现两个类,一个称为“特殊”类。 special 有一个成员变量bool conditions 和一个方法perform_special。 另一个类名为manager,它具有special 类型的成员变量。仅当 condition 为真时,我希望 manager 在其 special 成员上调用 perform_special

到目前为止,我已经实现了这段代码:

#include<iostream>
using namespace std;

class special{
  public:
    special(){};
    void perform_special();
    void set_conditions( bool cond );
    bool get_conditions();
  private:
    bool conditions;
};
void special::perform_special(){ cout<<"special performed."<<endl; }
void special::set_conditions( bool cond ){ conditions = cond; }
bool special::get_conditions(){ return conditions; }

class manager{
  public:
    manager(){};
    void check_specials();
    void set_effect( special* eff );
  private:
    special* effect;
};
void manager::check_specials(){
  if(effect->get_conditions()){ effect->perform_special(); }
}
void manager::set_effect( special *eff ){ effect = eff; }

int main(){
  int a=3; int b=2;
  bool cond = a<b;
  special effect1;
  effect1.set_conditions( cond );

  a=2; b=3;
  manager manager1;
  manager1.set_effect( &effect1 );
  manager1.check_specials();

  return 0;
}

这就是它的作用:它创建布尔值cond,它立即被评估为false,因为此时a&lt;b 为假。现在它将此条件赋予一个特殊变量,该变量再次赋予一个管理器变量。当经理在其特殊变量上调用check_special 时,没有任何反应,因为cond 为假。

这是我的问题:我不希望立即评估 cond。正如您在代码中看到的,a 和 be 的值可能会发生变化,因此表达式 a&lt;b 的值也会发生变化。如何实现 cond 的值仅在调用函数 check_specials() 并使用变量 a 和 b 的最新值时进行评估?

背景:我正在尝试实现一个基于文本的冒险游戏,所以“特殊”将是在一堆条件为真时发生的某种特殊效果。 “经理”将是某种处理游戏并保存所有特殊效果等的主类。我想在主函数中声明这些特殊效果并将它们传递给manager类型的变量“游戏”然后开始游戏的常规,所以我需要manager 来动态评估特殊效果的条件表达式,因为条件会随着时间而明显变化。

【问题讨论】:

  • 看看“演员”。振兴凤和精神,就是用好这种东西。
  • 尽量远离managermaster 类,它们往往会产生糟糕的代码。最简单的解决方案可能是将所需的数据放在适当的位置,因此manager 需要ab,因此应该将它们作为成员而不是将它们放在main 中。这可能会解决所有此类问题。
  • 从技术上讲,您可以使用 lambdas 进行以后的评估,但是您会遇到对象生命周期的麻烦,因为您需要保证在评估它们时要评估的东西仍然存在,这可能会变得非常棘手。
  • "condition" 不是布尔值,它是一个“闭包”——保持对某些(可能是外部)状态的引用并返回取决于该状态的布尔值。根据您使用的 C++ 版本和第三方库,有不同的方法可以实现此模式。
  • 它被认为是不好的,因为“旨在让经理拥有包括示例中的 a 和 b 在内的各种东西”。您的班级通常应该只承担一项责任,而不是做所有事情。见god object。对于游戏,专门查找“实体组件系统”。你真的不想要special ghost("a ghost appears!");,而是你可能想要std::vector&lt;special&gt; the_monsters;

标签: c++ boolean adventure


【解决方案1】:

您可以构建一个Cond 类,原型为:

struct Cond
{
    int& a;
    int& b;
    operator bool() const {return a < b;}
};

你会用它来实例化

Cond cond{a, b};

代替您当前的 cond 声明。

然后您将在测试时写入if (cond),这将通过引用使用ab 的当前值。

这是这种惰性求值技术的主要内容,但这只是开始。主要的陷阱是悬空引用的可能性,也许可以用std::reference_wrapper解决。

【讨论】:

  • 为什么不能依赖默认的复制构造函数?
  • 我对这个解决方案的问题是条件被固定为两个值的比较。我是游戏的上下文,我需要能够通过任意条件
  • @xskxzr 没有理由 - 我对将成员变量引用设置为其他成员变量的情况感到困惑:这里不是这种情况,所以没有问题。感谢您指出。
【解决方案2】:

您将bool 类型的变量传递给方法cond(),变量只能保存值。你需要传递的是一个函数,它返回bool

class special{
  public:
      using predicate = std::function<bool()>;

      void set_conditions( predicate p );
      ...
};

现在您可以传递函数、函子、lambda 等,稍后将对其进行评估:

int main()
{
  int a=3; int b=2;
  auto cond = [&]{ return a<b; };
  special effect1;
  effect1.set_conditions( cond );
  ...
}

【讨论】:

  • 您能解释一下 [&] 的含义吗?这是否使cond 成为指向函数return a&lt;b; 的指针? (我现在不能自己尝试:()
  • 这是一个 lambda,通过引用捕获所有局部变量(因为您需要跟踪 ab 值)。当然,您需要注意 lambda 不会超过这些变量。为简单起见,我让 lambda 捕获所有内容,您可以明确写出捕获 ab
  • 关键是引用捕获。我认为您最好突出显示它。
  • 恐怕我不懂语法...我收到错误function does not name a type 和谓词相同。
猜你喜欢
  • 1970-01-01
  • 2016-08-28
  • 2017-06-12
  • 2021-11-19
  • 1970-01-01
  • 2014-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多