通过 typedef 定义 C++ 新类型

C++ new types definition via typedef

我是 C++ 的新手,我遇到了一个问题,我需要在 class 中通过 typedef 定义新的数据类型(具体来说是联合)。我的class.h模块的相关代码片段如下

class Manager
{

  public:

    static const uint8_t NO_BYTES_IN_PACKET;
    static const uint8_t NO_PYLD_BYTES_IN_CONTROL_PACKET;

    // control packet structure
    typedef union{
        struct{
            uint8_t header[3];                                
            uint8_t payload[NO_PYLD_BYTES_IN_CONTROL_PACKET];  
        }pkt_parts_t;
        uint8_t pkt_array[NO_BYTES_IN_PACKET];
    }control_pkt_u;

  private:

}

我的问题是常量

static const uint8_t NO_BYTES_IN_PACKET;
static const uint8_t NO_PYLD_BYTES_IN_CONTROL_PACKET;

在关联的 .cpp 模块中定义

const uint8_t Manager::NO_BYTES_IN_PACKET = 8;
const uint8_t Manager::NO_PYLD_BYTES_IN_CONTROL_PACKET = 5;

因此,我一直收到一条错误消息:错误:在编译过程中,数组绑定不是“]”标记前的整数常量。我的想法是将联合定义移动到 .cpp 模块中,但我不确定这是否是正确的方法。你有什么意见?谢谢你的任何想法。

如果你没有odr-use那些static const int,你不需要在.cc文件中定义它们,只需将值放在.h 文件:

class Manager
{

  public:

    static const uint8_t NO_BYTES_IN_PACKET = 8;
    static const uint8_t NO_PYLD_BYTES_IN_CONTROL_PACKET = 5;

/* .... */

};

但是,如果你odr-use那些常量,比如获取它们的地址,那么你需要在.cc文件中定义它们,.h文件中的class定义保持不变:

const uint8_t Manager::NO_BYTES_IN_PACKET;
const uint8_t Manager::NO_PYLD_BYTES_IN_CONTROL_PACKET;

编辑: 对于声称 static const int 不能用作 compile-time 常量的评论或其他答案,他们的说法是错误的。

以下内容转自[class.static.data]/3(强调我的):

If a non-volatile const static data member is of integral or enumeration type, its declaration in the class definition can specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression ([expr.const]). A static data member of literal type can be declared in the class definition with the constexpr specifier; if so, its declaration shall specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression. [ Note: In both these cases, the member may appear in constant expressions. — end note ] The member shall still be defined in a namespace scope if it is odr-used ([basic.def.odr]) in the program and the namespace scope definition shall not contain an initializer.

问题是 static const 并不意味着它是一个编译时间常量。作为一个不是的例子,它可能是程序启动的时间。

你想要的是 constexpr 告诉编译器它可以在编译时计算,这意味着你的数组大小定义明确并且它传达了你的意图更清楚。

class Manager{
    public:
        constexpr uint8_t NO_BYTES_IN_PACKET = 8;
        ...

此外;它将迫使您解决真正的问题,即其他编译单元无法看到常量的大小,因为您没有在 header.

中定义它