我正在阅读以下源代码(取自此存储库(。
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++概念?
这个问题已经有了一个公认的答案,但它很模糊,而且是基于猜测,所以我会尝试给出一个更明确的答案:
当声明一个可以复制的类时,必须将其定义为AActor
或UActorComponent
。两者都使用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()
并且将该函数的实现留给您时,它才会执行此操作。