成员声明中的“class”关键字是什么意思?

Mar*_*c M 2 c++ unreal-engine5

我目前正在学习 C++(用于虚幻引擎)。我在示例代码中遇到了一段我不明白的代码:

class APangaeaCharacter : public ACharacter
{
    GENERATED_BODY()

public:
    APangaeaCharacter();

    // Called every frame.
    virtual void Tick(float DeltaSeconds) override;

    /** Returns TopDownCameraComponent subobject **/
    FORCEINLINE class UCameraComponent* GetTopDownCameraComponent() const { return TopDownCameraComponent; }
    /** Returns CameraBoom subobject **/
    FORCEINLINE class USpringArmComponent* GetCameraBoom() const { return CameraBoom; }

private:
    /** Top down camera */
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
    class UCameraComponent* TopDownCameraComponent;

    /** Camera boom positioning the camera above the character */
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
    class USpringArmComponent* CameraBoom;
};

Run Code Online (Sandbox Code Playgroud)

这是关于以 开头的行FORCEINLINE class。这里是否声明了一个新类或者它到底意味着什么?

Kae*_*Rin 5

更新 10/04/2023:我认为语法的名称称为详细类型说明符


您看到的语法告诉编译器您正在使用的类型是在其他地方定义的类。这些类称为不完整类型。从这篇文章

完整类型是描述标识符但缺少确定标识符大小所需的信息的类型。不完整的类型可以是:

  • 您尚未指定其成员的结构类型。
  • 您尚未指定其成员的联合类型。
  • 您尚未指定其维度的数组类型。

您将看到第一种情况:您尚未指定其成员的结构类型。(注意:structs 和classes 在 C++ 中或多或少是相同的,只有细微的差别)。

您只能以有限的方式使用不完整的类型。创建指向它的指针很好,这是因为对象指针始终具有相同的大小(无论它指向什么类型)。


至于为什么 Unreal 在类定义中使用不完整类型:

  • 它可以帮助减少编译时间。看到这个问题。请注意,引用的帖子中的“前向声明”涉及使用不完整类型。

  • 它允许您引用其他标头中声明的类的标头。想象一下以下情况(为简洁起见,省略了 Unreal 宏):

// FirstActor.h
#pragma once
#include "SecondActor.h"
class AMyFirstActor : public AActor
{
    AMySecondActor* Ptr;
}

// SecondActor.h
#pragma once
#include "FirstActor.h"
class AMySeoondActor : public AMyFirstActor
{
    FirstActor* Ptr;
}

Run Code Online (Sandbox Code Playgroud)

上面的例子不会编译。由于 的存在#pragma once,第一个标头实际上扩展为:

class AMySeoondActor : public AMyFirstActor
{
    AMyFirstActor* Ptr;
}
class AMyFirstActor : public AActor
{
    AMySecondActor* Ptr;
}
Run Code Online (Sandbox Code Playgroud)

如果成员声明之前没有前缀,当您说但到目前为止找不到该类时class,编译器将尝试查找该类的实际定义。使用前缀,编译器将注意到它是在其他地方定义的类型并继续。FirstActorFirstActor* Ptr;class

另一种等效的方法是使用class前面的前缀:

// FirstActor.h
#pragma once
#include "SecondActor.h"
class ASecondActor;
class AMyFirstActor : public AActor
{
    AMySecondActor* Ptr;
}

// SecondActor.h
#pragma once
#include "FirstActor.h"
class AMyFirstActor;
class AMySeoondActor : public AMyFirstActor
{
    AMyFirstActor* Ptr;
}

Run Code Online (Sandbox Code Playgroud)