将 class 的静态常量属性传递给函数

passing static const attribute of class to a function

对于我在屏幕上绘制位图的 arduino 学校项目,我想将所述位图存储为 类 中的无符号字符数组。

目前我是这样做的:

class Actor{
  public:
    static constexpr unsigned char sprite[8] = {0x97, 0xd5, 0xb7, 0x00, 0xe0, 0x4a, 0x44, 0x4a};
};

void setup() {
  Actor a;

  u8g2.begin(); // setup for display
  u8g2.drawXBM(10, 10, 8, 8, a.sprite); // draw bitmap to display buffer
  u8g2.sendBuffer(); // send buffer to display
}

这会导致以下错误消息:

/tmp/cc8frii8.ltrans0.ltrans.o: In function `u8g2_DrawXBM':
/home/pichler/Arduino/libraries/U8g2/src/clib/u8g2_bitmap.c:146: undefined reference to `Actor::sprite'
/home/pichler/Arduino/libraries/U8g2/src/clib/u8g2_bitmap.c:146: undefined reference to `Actor::sprite'
collect2: error: ld returned 1 exit status
exit status 1

这让我相信无法访问变量“sprite”。有谁知道为什么会这样,以及如何正确地做?提前致谢!

注意,您遇到的是链接器错误,而不是编译时错误。就编译而言,一切都很好,但您所做的还不足以满足整个工具链。问题是,您从未给出变量的定义,链接器在将所有内容组合在一起时无法找到它。

如果您使用 C++ 17 进行编译,这个问题就会消失。发生的事情是,当您将 a.sprite 传递给函数时,数组衰减为指针类型(指向第一个元素),并且自它必须有一个地址,被认为是 odr used。这意味着该变量在您的应用程序中必须具有明确的位置,因此要明确声明(就像任何普通的静态变量一样,它是 odr-used。)

对于 class 的静态成员,如果它们是 odr-used,则必须在应用程序的一个地方声明它们,通常是在 cpp 文件中:

class Foo {
    static constexpr int x;
};

// Foo.cpp
#include "Foo.h"

// Give a definition so it has a single location
int Foo::x;

将此定义与您的应用程序的其余部分一起编译,问题就会消失。

在 c++17 中,constexpr 静态成员是隐式“内联”变量,这意味着一个定义将被放置到每个看到它的目标文件中,以一种不会导致重复定义错误的方式。这类似于“内联”对函数的含义。因此,仅根据您的 class 声明,它就可以为您生成定义,因此如果您使用 c++17 或更高版本,则不需要上述的 .cpp 文件。