【问题标题】:What does "class" mean before parameter?参数前的“类”是什么意思?
【发布时间】:2017-05-09 18:51:33
【问题描述】:

虚幻引擎生成以下函数:

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

注意参数类型之前的“类”说明符。什么意思?

【问题讨论】:

  • 和没有“class”一样。
  • 但是为什么要把它放在那里呢?还有参考吗?
  • 在 C 中,如果你有一个 struct foo,你可以使用它:struct foo f;。 C++ 不需要这个,但它保持向后兼容性,并将其扩展到 class 关键字。
  • @DeiDei,C 没有类,所以我非常怀疑这样做是为了向后兼容。到目前为止,前向声明似乎是最有可能的理论。

标签: c++ syntax parameters unreal-engine4


【解决方案1】:

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

void AFlyingPawn::SetupPlayerInputComponent(class UInputComponent* InputComponent)

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

请注意,新的类名也可以由 elaborated type specifier 引入,它作为另一个声明的一部分出现,但仅限 如果name lookup 找不到先前声明的具有相同的类 名字。

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可用于消歧。

如果作用域中存在名称与类类型名称相同的函数或变量,则可以在名称前添加类以消除歧义,从而产生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 或不使用不会改变任何内容。请注意,如果先前声明的类型不匹配,则编译将失败。

【讨论】:

  • 谢谢。那么它是哪一个;)
  • @ShitalShah 这取决于上下文,但我会打赌第一个。 :)
【解决方案2】:

虚幻的工作原理

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

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

例如,如果要定义PawnsPlayerControllersAIControllers等元素,则HUD等等,您可以在 GameMode 中进行配置,然后配置到项目设置中,或者直接通过 World Settings 配置到关卡中(如果您的关卡需要特定的游戏模式)。这些引用也是类,引擎将在适当的时候实例化它们以设置游戏

陷阱来了

考虑到这一点,缺点就来了。在 UE4 C++ 中(是的,这是一件事!),由于引擎绑定了松散的末端,有时您将无法使用某些类,因为它们没有被声明。当然,您可以包含它们,但请考虑一下:如果您将一个类所需的所有包含项全部包含在内,而另一个类可能间接需要该类,则会创建多少循环依赖项?

解决方案是转发声明。然而,这种情况是一种特殊的风格,称为 Shorthand Forward Declaration,在这种情况下,您在使用类的确切位置声明类型

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

把它带到现实世界

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

TSubclassOf < APawn > DefaultPawnClass

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

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

TSubclassOf<class ASpeedyPawn> MySpeedyPawn;

【讨论】:

    【解决方案3】:

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

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

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

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

    该帖子没有很好地涵盖的内容是您想要进行前向声明的原因。正如我所说,它解决了循环依赖并让您免于包含类型。包含文件意味着让编译器将文件的内容复制到包含的位置。但您并不总是需要知道文件的内容。如果您只使用我链接的帖子中描述的功能就可以逃脱,您可以保存包含。这反过来会减少编译器输出的大小。

    【讨论】:

    • 我理解前向声明,但到目前为止我从未见过在参数中这样做。我查找了 C++ 语言参考中的参数,但我找不到任何可以说这是可能的东西。
    猜你喜欢
    • 1970-01-01
    • 2012-04-19
    • 1970-01-01
    • 1970-01-01
    • 2016-01-17
    • 1970-01-01
    • 2015-09-21
    • 2013-07-07
    • 2020-12-16
    相关资源
    最近更新 更多