一个类怎么可能有一个函数实现却没有声明



我正在阅读以下源代码(取自此存储库(。

void AVariableReplicationCharacter::GetLifetimeReplicatedProps(TArray< FLifetimeProperty >& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
// Variable A doesn't have any additional replication condition 
DOREPLIFETIME(AVariableReplicationCharacter, A);
// Variable B should only replicate to the owner of this actor
DOREPLIFETIME_CONDITION(AVariableReplicationCharacter, B, COND_OwnerOnly);
}

该函数在.cpp中实现,但在.h中没有相应的声明。令人惊讶的是,它可以被编译。

我试图用一个更简单的方法复制它,如下所示,但它没有编译。

#include <iostream>
using namespace std;
class Parent
{
public:
virtual void Job() const;
};
void Parent::Job() const
{
cout << "Parent" << endl;
}
class Child : public Parent
{
public:
virtual void Job() const override;
};
void Child::Job() const
{
Parent::Job();
cout << "Child" << endl;
}
class GrandChild : public Child
{
};
//= ATTEMPTING TO IMPLEMENT WITHOUT DECLARATION
void GrandChild::Job() const 
{
Child::Job();
}
int main()
{
std::cout << "Hello World!n";
std::getchar();
}

问题

我这里缺少什么C++概念?

这个问题已经有了一个公认的答案,但它很模糊,而且是基于猜测,所以我会尝试给出一个更明确的答案:

当声明一个可以复制的类时,必须将其定义为AActorUActorComponent。两者都使用UCLASS()宏来表示以下类声明需要使用Unreal Header Tool(UHT(集成到Unreals反射中,该工具在实际构建之前运行并生成代码。该代码被写入一个生成的名为";foo.generated.h";并且代码文件被称为";foo.gen.cpp";其中";foo";代表您的头文件名(无扩展名(。标头始终是标头中的最后一个include,并且每个标头文件存在一次,而不是每个类。

在类内部,您还必须调用GENERATED_BODY()宏(或者GENERATED_UCLASS_BODY()宏,但我认为这是遗留的东西(。这就是UHT为类本身生成的代码的去向。它包含关于UPROPERTY()UFUNCTION()声明的信息,如果您在类上使用反射,它还声明了GetLifetimeReplicatedProps()的重写,然后您必须实现它。

这并不是UHT声明的唯一方法。如果您正在使用RPC,您还必须创建一个您实际上没有声明的实现。声明为Foo()的方法将以Foo_Implementation()为主体(因为实际Foo()的实现将通过UHT创建,在某个时刻调用您的实现(,甚至可以选择Foo_Validate()

你可以在这里阅读更多关于这方面的信息。

关于UHT,虚幻文档非常模糊,但我鼓励你在他们的GitHub上查看它的代码。此外,您实际上可以";转到声明";CCD_ 15。您应该能够在标题中查看生成的代码,它们位于";"中间/构建";项目的文件夹。

函数在.cpp中实现,但在.h中没有相应的声明。

成员函数的声明必须以一种或另一种形式存在于类定义内部

最有可能的是,这里的宏用于间接编写相关成员函数的声明。在任何情况下,为了能够在类之外定义成员函数,该特定成员函数的相应声明必须在类内部。该声明是否来自宏无关。

这是因为GENERATED_BODY()宏会在UCLASS()中自动创建GetLifetimeReplicatedProps(TArray< FLifetimeProperty >& OutLifetimeProps) const的声明。只有当它找到带有Replicated说明符的UPROPERTY()并且将该函数的实现留给您时,它才会执行此操作。

最新更新