SFML RenderTarget.draw:不完整类型的无效使用

SFML RenderTarget.draw : Invalid use of incomplete type

我正在看书https://www.packtpub.com/game-development/sfml-game-development

在第 3 章第 61 页,我们正尝试在这样的目标上绘制精灵:

void Aircraft::drawCurrent(sf::RenderTarget& target,
sf::RenderStates states) const
{
    target.draw(mSprite, states);
}

github 上的书的配套代码在这里 https://github.com/SFML/SFML-Game-Development-Book/blob/master/03_World/Source/Aircraft.cpp#L31

当我尝试编译时,它给我这个错误:

 error: invalid use of incomplete type ‘class sf::RenderTarget’
     target.draw(sprite, states);
     ^~~~~~

看着文档我摸不着头脑,看起来是正确的做法https://www.sfml-dev.org/documentation/2.4.2/classsf_1_1RenderTarget.php#a12417a3bcc245c41d957b29583556f39

本书后面的代码位于 https://github.com/ishanatmuz/SFMLSnippets/blob/chapter-3/aircraft.cpp#L11

您被此处类型的前向声明绊倒了。

  • 使用(例如)class MyTypeName {...}; 定义完整类型。这为它命名并定义了它的实际结构(即成员、它们的类型、大小、对齐方式等)。

  • 一个不完整的类型基本上只是外壳,比如class MyTypeName;,只是告诉编译器这个名字代表的类型实际上是一个class。否则当你使用它时它不知道如何解释 MyTypeName

如果您只是为 MyTypeName class 使用指针或引用,那么它的实际 structure/contents 并不重要。因此,使用不完整的类型就足够了(它在几个 SFML header 中声明,因此它不必为 class 包含完整的 header)。

但是,一旦您开始调用该类型的成员,您将需要完整的类型,因为编译器必须了解实际类型的内存布局。仅仅知道它是一个 class(或整数、字符串文字等)已经不够了。为了解决这个问题,你实际上包含了 header 文件,里面有完整的类型。


为什么还要使用前向声明?

多种原因,最突出的原因:

  • 更快。如果编译器知道 MyTypeName 是 class 就足够了(例如定义指针或引用),那么解析一行就足够了。它不必解析可能的数百行、存储结构信息等,只是为了在几行之后将其丢弃。

  • 帮你实现循环依赖。想象一下 class A 有一个指向 class B 和 vice-versa 的 object 的指针。您不能在另一个之后定义一个 class,因为当您在 B.

    之前定义 A 时,编译器将不知道 B 是什么