参数前的"class"是什么意思?

What does "class" mean before parameter?

Unreal Engine 生成以下函数:

void AFlyingPawn::SetupPlayerInputComponent(class UInputComponent* InputComponent)
{
    //stuff...
}

注意参数类型前的 "class" 说明符。这是什么意思?

1.第一种可能性,如果之前没有声明UInputComponent,这可能是一个forward declarations。所以

void AFlyingPawn::SetupPlayerInputComponent(class UInputComponent* InputComponent)

forward声明了一个名为UInputComponent的class,参数InputComponent的类型为UInputComponent*.

Note that a new class name may also be introduced by an elaborated type specifier which appears as part of another declaration, but only if name lookup can't find a previously declared class with the same name.

class U;
namespace ns{
    class Y f(class T p); // declares function ns::f and declares ns::T and ns::Y
    class U f(); // U refers to ::U
    Y* p; T* q; // can use pointers and references to T and Y
}

2。第二个possibility,关键字class可以用来消歧。

If a function or a variable exists in scope with the name identical to the name of a class type, class can be prepended to the name for disambiguation, resulting in an elaborated type specifier

例如

int UInputComponent;
class UInputComponent { /* ... */ };

// without the class keyword it won't compile because the name UInputComponent is ambiguous
void AFlyingPawn::SetupPlayerInputComponent(class UInputComponent* InputComponent) 

3。第三种可能,可能没有任何意义

如果 UInputComponent 已声明为 class,则使用或不使用关键字 class 不会改变任何内容。请注意,如果先前声明的类型不匹配,则编译将失败。

通常 class 关键字用于声明新的 class 类型。但不是在这种情况下。

这称为前向声明
当您要使用的类型未知时使用这些。 F.e。想象一下两个 header 文件。他们每个人都使用另一个的类型。这是循环依赖,是不允许的。但是你仍然需要在每个文件中使用其他类型,对吗?

你可以做的是在一个文件中转发声明类型,然后你可以去掉包含。摆脱 include 解决了循环依赖并使您丢失了类型的所有信息(可用成员 f.e.),但您可以使用类型本身。这也为您节省了很多 "space" 因为编译器不必包含其他 header.

我不想说太多,因为已经有很好的答案了:
When can I use a forward declaration?

post 没有很好地说明您为什么要进行前向声明。正如我所说,它解决了循环依赖并使您免于包含类型。 include一个文件就是让编译器把文件的内容复制到include所在的地方。但您并不总是需要知道文件的内容。如果您可以仅使用我链接的 post 中描述的功能,则可以保存包含。这反过来会减少编译器输出的大小。

虚幻引擎的工作原理

您可能知道,Unreal 管理着相同 base classes 的 多个实现 来定义共同点。然后,每个开发人员都必须从引擎必须提供的内容中创建子 classes,以便在引擎中执行任务。

在这种情况下,它是关于一个 InputComponent,用于处理用户输入、解释它并将其传递给 Controllers and/or,随后,典当。

例如,如果要定义 PawnsPlayerControllersAIControllers[=56= 等元素]、HUD 等,您可以在 GameMode 中进行设置,然后配置到项目设置中,或者直接通过世界设置(以防您的关卡需要特定的游戏模式)。这些引用也是 classes,它们将在适当的时候由引擎实例化以设置 Game.

陷阱来了

考虑到这一点,缺点就来了。在 UE4 C++ 中(是的,这是一回事!),由于引擎将未解决的问题联系在一起,有时您将无法使用某些 classes,因为它们未声明。当然,您可以包含它们,但想一想:如果您将一个 class 所需的所有包含都包含进来,却发现另一个可能间接需要那个,将创建多少循环依赖?

解决方案是前向声明。然而,这种情况是一种特殊的风格,称为 Shorthand 前向声明,您在其中声明一个类型 在您使用 [=73= 的确切位置].

如果您只使用它一次,这将非常方便,这样您就不会在文件开头得到一个糟糕的声明列表。

将其带入现实世界

例如,如果您想知道当前定义的默认 Pawn class,您可以检查 GameMode[=56] 中的 GetDefaultPawnClass public 变量=](我们称之为 MyGameMode)。变量定义如下:

TSubclassOf < APawn > DefaultPawnClass

看到 TSubclassOf 了吗?这实际上是一个确保类型安全的 Class 模板。这实际上是对编辑器的提示,只向您显示源自 APawn.

的 classes

如果您使用自定义类型并基于我目前所讨论的内容,您可以找到如下内容:

TSubclassOf<class ASpeedyPawn> MySpeedyPawn;