C++ c++;bool改变时的触发功能
我有一个不断流化的布尔值。我需要在bool变为true时触发一个函数,在bool变为false时触发另一个函数,但每次更改仅触发一次,因此我不能使用C++ c++;bool改变时的触发功能,c++,boolean-logic,C++,Boolean Logic,我有一个不断流化的布尔值。我需要在bool变为true时触发一个函数,在bool变为false时触发另一个函数,但每次更改仅触发一次,因此我不能使用while(true)循环 什么是C++在观察值和触发时最好的方法?p> 谢谢。我将通过设置flagTrue变量和flagFalse变量来实现这一点。当遇到第一个True时,flagTrue将从false更改为True,并忽略所有后续True布尔值。类似地,当您遇到firat False时,flagFalse将从False变为True,并忽略以下所有
while(true)
循环
<>什么是C++在观察值和触发时最好的方法?p>
谢谢。我将通过设置flagTrue变量和flagFalse变量来实现这一点。当遇到第一个True时,flagTrue将从false更改为True,并忽略所有后续True布尔值。类似地,当您遇到firat False时,flagFalse将从False变为True,并忽略以下所有False布尔值。此外,当所检查的布尔值从True更改为False时,您将把flagTrue更改为False,在另一种情况下也是如此。
例如:
看看观察者模式。您可以将布尔值封装在帮助器类中,该类在布尔值设置时触发事件 可观测布尔的示例实现:
#include <vector>
class Observer {
public:
virtual void valueChanged() = 0;
};
class ObservableBool {
private:
bool value;
std::vector<Observer*> observers = std::vector<Observer*>();
public:
bool getValue() {
return value;
}
bool setValue(bool value) {
bool changed = (value != this->value);
this->value = value;
if(changed) raiseEvent();
}
void addObserver(Observer* observer) {
observers.push_back(observer);
}
void removeObserver(Observer* observer) {
observers.erase(std::find(observers.begin, observers.end, observer));
}
private:
void raiseEvent() {
for (int i = 0; i < observers.size; ++i) {
observers[i]->valueChanged();
}
}
};
#包括
类观察员{
公众:
虚空值已更改()=0;
};
电子图书类{
私人:
布尔值;
std::vector observer=std::vector();
公众:
bool getValue(){
返回值;
}
布尔设置值(布尔值){
bool changed=(值!=此->值);
这个->值=值;
如果(更改)raiseEvent();
}
无效添加观察者(观察者*观察者){
观察员。推回(观察员);
}
无效移除观察者(观察者*观察者){
observators.erase(std::find(observators.begin,observators.end,observator));
}
私人:
void raiseEvent(){
对于(int i=0;i<0.size;++i){
观察者[i]->valueChanged();
}
}
};
这可以改进很多。一个非常好的方法是实现从bool到bool的隐式转换(但是要小心,重载bool的“=”运算符可能会很危险)。您可以将其模板化以支持任意类型,而不仅仅是bool,您应该使用智能指针而不是原始指针(
std::weak_ptr
最好),并且您可能应该使用函数指针来正确支持lambda,而不是Observer类。如果您做得正确,您可以像使用普通布尔值一样使用该类,在设置新值时会有很小的开销。默认情况下,对更改的所有反应都由更改值的线程执行。我可能会从以下内容开始:
#include <functional>
#include <atomic>
#include <iostream>
struct trigger
{
using closure_type = std::function<void()>;
trigger(closure_type on_set, closure_type on_reset, bool initial_state = false)
: _state { initial_state }
, _on_set(std::move(on_set))
, _on_reset(std::move(on_reset))
{}
void set() {
if (not _state.exchange(true)) {
_on_set();
}
}
void reset() {
if (_state.exchange(false)) {
_on_reset();
}
}
std::atomic<bool> _state;
std::function<void()> _on_set;
std::function<void()> _on_reset;
};
void has_set() {
// you can marshall accross threads here by posting calls to a
// queue
std::cout << __func__ << std::endl;
}
void has_unset() {
// you can marshall accross threads here by posting calls to a
// queue
std::cout << __func__ << std::endl;
}
int main()
{
trigger t { has_set, has_unset };
t.set();
t.set();
t.reset();
t.reset();
}
#包括
#包括
#包括
结构触发器
{
使用closure_type=std::function;
触发器(集合上的闭合类型,复位上的闭合类型,布尔初始状态=false)
:_状态{初始状态}
,_在_集上(标准::移动(在_集上))
,_on_reset(标准::移动(on_reset))
{}
空集(){
if(非_state.exchange(true)){
_关于_集();
}
}
无效重置(){
如果(_state.exchange(false)){
_on_reset();
}
}
原子态;
std::函数集上的函数;
std::功能_on_重置;
};
void有_集(){
//您可以通过将调用发送到
//排队
std::cout派对有点晚了,但是如果你只是想把它搞定(比如测试),这里有一个稍微简单的解决方案:
这似乎比实现布尔包装类、触发器和观察者模式要简单一些。查找感谢!(已编辑)因此相反的结果是:if(bool==false&&flagflse==false){//DoSomething flagTrue=false;flagflse=True;}
是这样吗?我添加了初始化。我相信他们会让这更清楚。是的,你添加的相反内容是正确的。我已经更新了我的代码。请检查。啊,我明白了。这很有意义。再次感谢你!你不需要两个标志,一个就足够了:静态bool isActive=false;bool newVal=read();if(newVal!=isActive){isActive=newVal;/*回调取决于isActive*/}
std::atomic::exchange在多线程环境中安全的同时为您提供以前的状态信息。
#include <functional>
#include <atomic>
#include <iostream>
struct trigger
{
using closure_type = std::function<void()>;
trigger(closure_type on_set, closure_type on_reset, bool initial_state = false)
: _state { initial_state }
, _on_set(std::move(on_set))
, _on_reset(std::move(on_reset))
{}
void set() {
if (not _state.exchange(true)) {
_on_set();
}
}
void reset() {
if (_state.exchange(false)) {
_on_reset();
}
}
std::atomic<bool> _state;
std::function<void()> _on_set;
std::function<void()> _on_reset;
};
void has_set() {
// you can marshall accross threads here by posting calls to a
// queue
std::cout << __func__ << std::endl;
}
void has_unset() {
// you can marshall accross threads here by posting calls to a
// queue
std::cout << __func__ << std::endl;
}
int main()
{
trigger t { has_set, has_unset };
t.set();
t.set();
t.reset();
t.reset();
}
/**
* @brief Set a boolean variable.
* @param b Pointer to the boolean variable.
* @param value Set to this value.
* @return Returns if the value was to be changed.
*/
bool set(bool* b, bool value)
{
// if b isn't going to change
if (*b == value) return false;
// if b is going to change
else
{
*b = value;
return true;
}
}
/**
* @brief A possible implementation
*/
int main()
{
bool my_variable = false;
while(true)
{
// Set my_variable and flag it if it changed
bool changed = set(&my_variable, some_function());
// check for changed
if (changed)
{
// ...
}
}
}