2009-02-07 27 views
1

我試圖寫一個小類來更好地理解C++中的位標誌。但有些東西沒有解決。它打印錯誤的值。哪裏有問題?我誤解了如何添加標誌?或者檢查一下位域是否有它們?Enum位域容器類

繼承人的代碼:

#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: 

回答

3

個人而言,我會使用std ::矢量< bool>的處理標誌,因爲它是包裝的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。我把這個問題看作是一個「學習者」問題,而不是一個優化問題。我展示瞭如何讓他的代碼正確,而不是快速。

3

有一個在你的remove_flag()方法,它應該是一個標誌漏洞| =我;

但是,這樣做O(1)所示:

void remove_flag(flag f) { m_flags &= ~f; } 
3

has_flag()remove_flag()是錯誤的。他們應該是這樣的:

bool has_flag(flag f) { return !!(m_flags & f); } 
void remove_flag(flag f) 
{ 
    m_flags &= ~f; 
} 
+0

他的has_flag實現工作得很好。 – Eclipse 2009-02-07 16:37:18

+0

嗯,它不應該。 – 2009-02-10 01:51:38

0

大家都已經注意到了:flag & =〜f;

You might look at my earlier posting.

has_flag():你看,如果f中的所有位設置爲返回true?或者如果其中至少有一個設置了?這是標誌差異& f == f   vs  標誌& f  != 0。

你可能會考慮的#include <了iomanip >和cout < <六角< < M_FLAG < <(分解)。 (十六進制到位轉換可以在你的腦海中更容易地完成。)

枚舉可以在類持有者中。

class Holder 
{ 
public: 
    enum flag { A=1, B=2, C=4; }; 
... 
}; 

你會再使用持有人::一個代替一個

您可能需要使用(I = 0;我< N; i ++在)如果has_flag(1 < <ⅰ)...

您可能希望add_flag/has_flag/remove_flag方法採取一個int而不是枚舉類型。這擺脫了很多鑄造。如果您不想支持所有可能的int值,則可以使用驗證方法和拒絕路徑。順便說一下,沒有任何東西阻止我調用add_flag(flag(5736))。而且你已經非常頻繁地使用enum_flag。

您可能想要使用mFlag而不是m_flag。這是你的選擇。但是,當您查看像m_x * m_y-m_z * m_y-m_x * m_z這樣的代碼時,根據您的字體,可能很容易將_誤認爲 - 。 (反之亦然)。

同樣,考慮addFlag而不是add_flag。對於這樣的事情並不重要。但是當你有一個很長的描述性名字時,那些下劃線開始加起來,佔用線空間。然後,誘惑就是縮寫名稱,讓你的代碼更加呆板。

只是我的0.02美元。