문제
나는 깃발로 프로그래밍하는 데별로 익숙하지 않지만 방금 유용한 상황을 발견했다고 생각합니다.
특정 이벤트의 청취자로 등록하는 몇 가지 물체가 있습니다. 그들이 등록하는 이벤트는 건설 될 때 전송되는 변수에 따라 다릅니다. 이 작업을 수행하는 좋은 방법은 다음과 같이 비트 또는 연결된 변수를 보내는 것입니다. 잡기 가능 | 액체 등. 그러면 생성자에서 물체는 어떤 플래그를 설정했는지 확인하고 그 자체를 자체적으로 등록 할 수 있습니다.
그러나 이것은 내가 혼란스러워하는 곳입니다. 바람직하게는 깃발이 열거적 일 것이다. 그러나 그것은 또한 문제이기도합니다. 이 깃발이 있다면 :
enum
{
TAKES_DAMAGE,/* (0) */
GRABBABLE, /* (1) */
LIQUID, /* (2) */
SOME_OTHER /* (3) */
};
그런 다음 깃발을 보내면 some_other (3)를 보내는 것과 동일합니다. 액체, 그렇지 않습니까?
이 물건을 정확히 어떻게 처리합니까?
해결책
열거는 두 가지의 힘이어야합니다.
enum
{
TAKES_DAMAGE = 1,
GRABBABLE = 2,
LIQUID = 4,
SOME_OTHER = 8
};
또는보다 읽기 쉬운 방식으로 :
enum
{
TAKES_DAMAGE = 1 << 0,
GRABBABLE = 1 << 1,
LIQUID = 1 << 2,
SOME_OTHER = 1 << 3
};
왜요 ? 깃발을 겹치지 않고 결합하고이를 수행 할 수 있기를 원하기 때문입니다.
if(myVar & GRABBABLE)
{
// grabbable code
}
... 열거 값이 다음과 같이 보이는 경우 작동합니다.
TAKES_DAMAGE: 00000001
GRABBABLE: 00000010
LIQUID: 00000100
SOME_OTHER: 00001000
그래서 당신이 설정했다고 말합니다 myVar
에게 GRABBABLE | TAKES_DAMAGE
, 여기에 grabbable 깃발을 확인해야 할 때 작동하는 방법은 다음과 같습니다.
myVar: 00000011
GRABBABLE: 00000010 [AND]
-------------------
00000010 // non-zero => converts to true
당신이 설정했다면 myVar
에게 LIQUID | SOME_OTHER
, 작업은 다음과 같습니다.
myVar: 00001100
GRABBABLE: 00000010 [AND]
-------------------
00000000 // zero => converts to false
다른 팁
깃발을 저장하는 또 다른 방법은 기본 유형을 전혀 귀찮게하지 않는 것입니다. 열거를 사용하는 경우, 열거 값은 기본적으로 서명되지 않은 INT로 저장되며, 이는 공통 컴퓨터에서 32 비트입니다. 이것은 당신에게 32 개의 가능한 깃발 만 제공합니다. 확실히 많이, 충분하지 않은 경우가 있습니다.
이제 플래그 세트를 다음과 같은 방식으로 정의 할 수 있습니다.
typedef struct
{
int takes_damage : 1;
int grabbable : 1;
int liquid : 1;
int some_other : 1;
} flags;
이 문제가 발생하지 않으면 ': 1'부분은 컴파일러에게 1 비트 만 사용 하여이 구조물 멤버를 저장하도록 지시합니다.
이제 플래그를 보유 할 변수를 정의하고 해당 깃발과 함께 작업 할 수 있습니다.
flags myflags = {1,0,0,1}; // defines a variable holding a set of flags, with an initial value of takes_damage & some_other
myflags.liquid = 1; // change the flags to include the liquid
if ( myflags.takes_damage ) // test for one flag
apply_damage();
if ( myflags.liquid && myflags.some_other ) // test for multiple flags
show_strange_behavior();
이 방법을 사용하면 제한없이 깃발을 여러 플래그를 정의 할 수 있으며 오버플로를 두려워하지 않고 언제든지 깃발 세트를 확장 할 수 있습니다. 단점은 플래그의 서브 세트를 테스트하는 것이 더 번거롭고 더 많은 코드가 필요하다는 것입니다.
예. 대신, 열거 회원의 힘을 2 :
enum
{
TAKES_DAMAGE = (1 << 0),
GRABBABLE = (1 << 1),
LIQUID = (1 << 2),
SOME_OTHER = (1 << 3)
};
플래그는 두 가지만 전원을 만들어야합니다. 즉, 각각이 저장하는 데이터 유형에 약간 이루어지며, 비트 또는 비트를 할 때는 아무것도 겹치지 않습니다.
열거에서 값을 설정할 수 없습니까?
enum {
TAKES_DAMAGE = 1,
GRABBABLE = 2,
LIQUID = 4
}
그 후, 그냥 조금씩 또는 그들에게 성능을 발휘합니다.
당신은 필요합니다
enum
{
TAKES_DAMAGE = 1,
GRABBABLE = 2,
LIQUID = 4,
SOME_OTHER = 8
};