<bdo id='ytUA6'></bdo><ul id='ytUA6'></ul>

    1. <i id='ytUA6'><tr id='ytUA6'><dt id='ytUA6'><q id='ytUA6'><span id='ytUA6'><b id='ytUA6'><form id='ytUA6'><ins id='ytUA6'></ins><ul id='ytUA6'></ul><sub id='ytUA6'></sub></form><legend id='ytUA6'></legend><bdo id='ytUA6'><pre id='ytUA6'><center id='ytUA6'></center></pre></bdo></b><th id='ytUA6'></th></span></q></dt></tr></i><div id='ytUA6'><tfoot id='ytUA6'></tfoot><dl id='ytUA6'><fieldset id='ytUA6'></fieldset></dl></div>

        <tfoot id='ytUA6'></tfoot>
      1. <small id='ytUA6'></small><noframes id='ytUA6'>

        <legend id='ytUA6'><style id='ytUA6'><dir id='ytUA6'><q id='ytUA6'></q></dir></style></legend>
      2. 我应该使用#define、enum 还是const?

        时间:2023-08-26
        <i id='4LDI1'><tr id='4LDI1'><dt id='4LDI1'><q id='4LDI1'><span id='4LDI1'><b id='4LDI1'><form id='4LDI1'><ins id='4LDI1'></ins><ul id='4LDI1'></ul><sub id='4LDI1'></sub></form><legend id='4LDI1'></legend><bdo id='4LDI1'><pre id='4LDI1'><center id='4LDI1'></center></pre></bdo></b><th id='4LDI1'></th></span></q></dt></tr></i><div id='4LDI1'><tfoot id='4LDI1'></tfoot><dl id='4LDI1'><fieldset id='4LDI1'></fieldset></dl></div>
        <legend id='4LDI1'><style id='4LDI1'><dir id='4LDI1'><q id='4LDI1'></q></dir></style></legend>

          • <tfoot id='4LDI1'></tfoot>

            <small id='4LDI1'></small><noframes id='4LDI1'>

              <bdo id='4LDI1'></bdo><ul id='4LDI1'></ul>
                    <tbody id='4LDI1'></tbody>
                  本文介绍了我应该使用#define、enum 还是const?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

                  问题描述

                  在我正在处理的 C++ 项目中,我有一个 flag 类型的值,它可以有四个值.这四个标志可以组合在一起.标志描述数据库中的记录,可以是:

                  In a C++ project I'm working on, I have a flag kind of value which can have four values. Those four flags can be combined. Flags describe the records in database and can be:

                  • 新记录
                  • 删除记录
                  • 修改记录
                  • 现有记录

                  现在,对于我希望保留此属性的每条记录,我可以使用枚举:

                  Now, for each record I wish to keep this attribute, so I could use an enum:

                  enum { xNew, xDeleted, xModified, xExisting }
                  

                  但是,在代码的其他地方,我需要选择哪些记录对用户可见,因此我希望能够将其作为单个参数传递,例如:

                  However, in other places in code, I need to select which records are to be visible to the user, so I'd like to be able to pass that as a single parameter, like:

                  showRecords(xNew | xDeleted);
                  

                  所以,我似乎有三种可能的方法:

                  So, it seems I have three possible appoaches:

                  #define X_NEW      0x01
                  #define X_DELETED  0x02
                  #define X_MODIFIED 0x04
                  #define X_EXISTING 0x08
                  

                  typedef enum { xNew = 1, xDeleted, xModified = 4, xExisting = 8 } RecordType;
                  

                  namespace RecordType {
                      static const uint8 xNew = 1;
                      static const uint8 xDeleted = 2;
                      static const uint8 xModified = 4;
                      static const uint8 xExisting = 8;
                  }
                  

                  空间要求很重要(byte vs int)但不是关键.使用定义我失去了类型安全性,而使用 enum 我失去了一些空间(整数)并且当我想要进行按位运算时可能不得不强制转换.使用 const 我想我也失去了类型安全性,因为随机的 uint8 可能会错误地进入.

                  Space requirements are important (byte vs int) but not crucial. With defines I lose type safety, and with enum I lose some space (integers) and probably have to cast when I want to do a bitwise operation. With const I think I also lose type safety since a random uint8 could get in by mistake.

                  还有其他更干净的方法吗?

                  Is there some other cleaner way?

                  如果不是,你会用什么,为什么?

                  If not, what would you use and why?

                  附言其余的代码是相当干净的现代 C++,没有 #defines,我在几个空格中使用了命名空间和模板,所以这些也不是没有问题.

                  P.S. The rest of the code is rather clean modern C++ without #defines, and I have used namespaces and templates in few spaces, so those aren't out of question either.

                  推荐答案

                  组合策略以减少单一方法的缺点.我在嵌入式系统中工作,因此以下解决方案基于整数和按位运算符快速、低内存和低内存的事实.闪存使用率低.

                  Combine the strategies to reduce the disadvantages of a single approach. I work in embedded systems so the following solution is based on the fact that integer and bitwise operators are fast, low memory & low in flash usage.

                  将枚举放在命名空间中,防止常量污染全局命名空间.

                  Place the enum in a namespace to prevent the constants from polluting the global namespace.

                  namespace RecordType {
                  

                  枚举声明并定义编译时检查类型.始终使用编译时类型检查来确保参数和变量的类型正确.C++ 中不需要 typedef.

                  An enum declares and defines a compile time checked typed. Always use compile time type checking to make sure arguments and variables are given the correct type. There is no need for the typedef in C++.

                  enum TRecordType { xNew = 1, xDeleted = 2, xModified = 4, xExisting = 8,
                  

                  为无效状态创建另一个成员.这可以用作错误代码;例如,当您想返回状态但 I/O 操作失败时.它也可用于调试;在初始化列表和析构函数中使用它来知道是否应该使用变量的值.

                  Create another member for an invalid state. This can be useful as error code; for example, when you want to return the state but the I/O operation fails. It is also useful for debugging; use it in initialisation lists and destructors to know if the variable's value should be used.

                  xInvalid = 16 };
                  

                  考虑到这种类型有两个目的.跟踪记录的当前状态并创建掩码以选择处于某些状态的记录.创建一个内联函数来测试该类型的值是否符合您的目的;作为状态标记与状态掩码.这将捕获错误,因为 typedef 只是一个 int 并且诸如 0xDEADBEEF 之类的值可能通过未初始化或错误指向的变量存在于您的变量中.

                  Consider that you have two purposes for this type. To track the current state of a record and to create a mask to select records in certain states. Create an inline function to test if the value of the type is valid for your purpose; as a state marker vs a state mask. This will catch bugs as the typedef is just an int and a value such as 0xDEADBEEF may be in your variable through uninitialised or mispointed variables.

                  inline bool IsValidState( TRecordType v) {
                      switch(v) { case xNew: case xDeleted: case xModified: case xExisting: return true; }
                      return false;
                  }
                  
                   inline bool IsValidMask( TRecordType v) {
                      return v >= xNew  && v < xInvalid ;
                  }
                  

                  如果您想经常使用该类型,请添加 using 指令.

                  Add a using directive if you want to use the type often.

                  using RecordType ::TRecordType ;
                  

                  值检查函数在断言中很有用,可以在使用时立即捕获错误值.运行时发现错误的速度越快,它造成的损害就越小.

                  The value checking functions are useful in asserts to trap bad values as soon as they are used. The quicker you catch a bug when running, the less damage it can do.

                  这里有一些例子可以把它们放在一起.

                  Here are some examples to put it all together.

                  void showRecords(TRecordType mask) {
                      assert(RecordType::IsValidMask(mask));
                      // do stuff;
                  }
                  
                  void wombleRecord(TRecord rec, TRecordType state) {
                      assert(RecordType::IsValidState(state));
                      if (RecordType ::xNew) {
                      // ...
                  } in runtime
                  
                  TRecordType updateRecord(TRecord rec, TRecordType newstate) {
                      assert(RecordType::IsValidState(newstate));
                      //...
                      if (! access_was_successful) return RecordType ::xInvalid;
                      return newstate;
                  }
                  

                  确保正确值安全的唯一方法是使用带有运算符重载的专用类,这留给其他读者作为练习.

                  The only way to ensure correct value safety is to use a dedicated class with operator overloads and that is left as an exercise for another reader.

                  这篇关于我应该使用#define、enum 还是const?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

                  上一篇:基本枚举类继承 下一篇:C++ 字符串枚举

                  相关文章

                  <small id='nf2OT'></small><noframes id='nf2OT'>

                  • <bdo id='nf2OT'></bdo><ul id='nf2OT'></ul>
                  1. <i id='nf2OT'><tr id='nf2OT'><dt id='nf2OT'><q id='nf2OT'><span id='nf2OT'><b id='nf2OT'><form id='nf2OT'><ins id='nf2OT'></ins><ul id='nf2OT'></ul><sub id='nf2OT'></sub></form><legend id='nf2OT'></legend><bdo id='nf2OT'><pre id='nf2OT'><center id='nf2OT'></center></pre></bdo></b><th id='nf2OT'></th></span></q></dt></tr></i><div id='nf2OT'><tfoot id='nf2OT'></tfoot><dl id='nf2OT'><fieldset id='nf2OT'></fieldset></dl></div>

                  2. <tfoot id='nf2OT'></tfoot>
                    <legend id='nf2OT'><style id='nf2OT'><dir id='nf2OT'><q id='nf2OT'></q></dir></style></legend>