我正在读这本书https://www.packtpub.com/game-development/sfml-game-development
在第3章第61页,我们试图在目标上绘制一个sprite,如下所示:
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;
一样,只告诉编译器这个名称代表一个实际上是类的类型。否则,无论何时使用它都不会知道如何解释MyTypeName
。如果您只使用MyTypeName
类的指针或引用,则其实际结构/内容并不重要。因此,使用不完整类型(在几个SFML头中声明,因此它不必包含类的完整头)就足够了。
但是,一旦开始调用该类型的成员,您将需要完整类型,因为编译器必须知道实际类型的内存布局。仅仅知道它是一个类(或整数,字符串文字等)已经不够了。要解决此问题,您实际上包含了包含完整类型的头文件。
多种原因,最突出的原因:
MyTypeName
是一个类(例如定义指针或引用)就足够了,解析一行就足够了。它不必解析潜在的数百行,存储结构信息等,只是为了将它丢弃几行。A
有一个指向类B
的对象的指针,反之亦然。你不能一个接一个地定义一个类,因为当你在B
之前定义A
时,编译器不会知道B
是什么。