열거적인 비트 필드 컨테이너 클래스
-
22-08-2019 - |
문제
C ++에서 비트 플래그를 더 잘 이해하기 위해 작은 클래스를 작성하려고합니다. 그러나 무언가가 작동하지 않습니다. 잘못된 값을 인쇄합니다. 문제는 어디에 있습니까? 깃발을 추가하는 방법을 오해 했습니까? 아니면 비트 필드에 가지고 있는지 확인하십시오.
그녀는 코드 :
#include <iostream>
enum flag
{
A = 1, B = 2, C = 4
};
class Holder
{
public:
Holder() : m_flags(A) {}
~Holder() {}
void add_flag(flag f) { m_flags |= f; }
bool has_flag(flag f) { return ((m_flags&f)==f); }
void remove_flag(flag f)
{
unsigned int flags = 0;
for (int i = 1; i<=(int)C; i *= 2)
{
if ((flag)i!=f && has_flag(f))
flags |= f;
}
m_flags = flags;
}
void print()
{
std::cout << "flags are now: " << m_flags << " | holding: ";
for (int i = 1; i<=(int)C; i *= 2)
{
if (has_flag((flag)i))
std::cout << i << " ";
}
std::cout << std::endl;
}
private:
unsigned int m_flags;
};
int main()
{
Holder h;
h.print(); // should print 1
h.add_flag(B);
h.print(); // should print 1 2
h.remove_flag(A);
h.print(); // should print 2
h.add_flag(C);
h.print(); // should print 2 4
h.remove_flag(B);
h.print(); // should print 4
}
프로그램 출력 :
flags are now: 1 | holding: 1
flags are now: 3 | holding: 1 2
flags are now: 1 | holding: 1
flags are now: 5 | holding: 1 4
flags are now: 0 | holding:
해결책
개인적으로 나는 std :: vector <bool>을 사용하여 깃발을 처리 할 것입니다.
하지만:
나는 당신의 제거 깃발이 약간 복잡하다고 생각합니다. 대신 시도해보십시오.
void remove_flag( flag f )
{
if ( has_flag( f ) == true )
{
m_flags ^= f; // toggle the bit leaving all other unchanged
}
}
편집 : 댓글이 내가 왜하지 않았는지 물었습니다 do m_flags &= ~f
. 나는 최적화 질문이 아닌 '학습자'질문으로 질문을했다. 나는 그의 코드를 빠르지 않고 올바르게 만드는 방법을 보여줍니다.
다른 팁
remove_flag () 메소드에는 버그가 있으므로 플래그 | = i;
그러나 다음과 같이 O (1)을 수행하십시오.
void remove_flag(flag f) { m_flags &= ~f; }
has_flag () 그리고 remove_flag () 잘못되었습니다. 그들은 다음과 같이 가야합니다.
bool has_flag(flag f) { return !!(m_flags & f); }
void remove_flag(flag f)
{
m_flags &= ~f;
}
모두가 이미 이것을 못 박았습니다 : 플래그 & = ~ f;
HAS_FLAG () : F의 모든 비트가 설정되어 있으면 True를 반환하려고합니까? 아니면 그들 중 하나 이상이 설정되어 있다면? 플래그의 차이점 & f == F vs 플래그 & f! = 0입니다.
#include를 고려할 수 있습니다u003Ciomanip> 그리고 cout << hex <
열거는 클래스 보유자 안에있을 수 있습니다.
class Holder
{
public:
enum flag { A=1, B=2, C=4; };
...
};
그런 다음 사용합니다 홀더 :: a 대신에 ㅏ.
당신은 (i = 0; i에 사용하고 싶을 수도 있습니다.
Add_flag/has_flag/remove_flag 메소드가 열거 된 유형이 아닌 int를 가져 가기를 원할 수 있습니다. 그것은 많은 캐스팅을 제거합니다. 가능한 모든 int 값을 지원하지 않으려면 검증 방법과 거부 경로를 사용할 수 있습니다. 그건 그렇고, add_flag (플래그 (5736))를 부르는 것을 막는 것은 없습니다. 그리고 당신은 이미 Enum_flag에 캐스팅하고 있습니다.
m_flag 대신 mflag를 사용하고 싶을 수도 있습니다. 그것은 당신의 선택입니다. 그러나 글꼴에 따라 m_x*m_y-m_z*m_y-m_x*m_z와 같은 코드를 보면-에 대해 _. (혹은 그 반대로도.)
마찬가지로 Add_flag 대신 AddFlag를 고려하십시오. 이와 같은 것이 중요하지 않습니다. 그러나 설명 이름이 길면 밑줄이 추가되기 시작합니다. 그런 다음 유혹은 이름을 약칭하여 코드를 더 둔화시킵니다.
내 $ 0.02.