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
是什么
我正在看书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
有一个指向 classB
和 vice-versa 的 object 的指针。您不能在另一个之后定义一个 class,因为当您在B
.A
时,编译器将不知道B
是什么