对于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。这意味着变量必须在应用程序中具有明确的位置,因此必须显式声明(与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文件。