提问者:小点点

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


对于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”是无法访问的。有人知道为什么会这样吗?怎样做才是正确的?提前谢谢!


共1个答案

匿名用户

注意,您得到的是链接器错误,而不是编译时错误。就编译而言,一切都很好,但您还没有完成足够的工作来满足整个工具链。问题是,您从未给出变量的定义,而链接器在将所有内容汇集到一起时无法找到它。

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

对于类的静态成员,如果它们是ODR使用的,则必须在应用程序中的一个地方声明它们,通常是在一个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静态成员是隐式的“内联”变量,这意味着一个定义将被放置到每个看到它的对象文件中,其方式不会导致重复定义错误。这类似于“内联”对于函数的含义。因此,仅通过类声明,它就可以为您生成定义,因此如果您使用C++17或更高版本,就不需要上面提到的。cpp文件。