Why declare a var as "class Type Name" and not just "Type Name"?

I’ve seen it all over the UE code, but I don’t get it.

Why declare a variable as class Type Name, like in ACharacter: class USkeletalMeshComponent* Mesh;, and not USkeletalMeshComponent* Mesh;?

Both looks to be pointers to a USkeletalMeshComponent object; is it a type of forward declaration?

Thanks

Hi,

It’s a kind of forward declaration called an ‘elaborated type specifier’:

http://en.cppreference.com/w/cpp/language/elaborated_type_specifier

It’s bad practice though, as it can go horribly wrong in the presence of namespaces and doesn’t really work for templates and enums. We try to discourage it, but some existing code (and occasionally new code) has it.

If you want a declaration, it should always be done at the correct scope (usually global scope), like this:

class USkeletalMeshComponent;

USTRUCT()
struct FThing
{
    GENERATED_BODY()

    UPROPERTY()
    USkeletalMeshComponent* Mesh;
};

Hope this helps,

Steve

Can you give an example where in the presence of namespaces this can go wrong? <3

For example:

namespace X
{
    // Will compile as taking ::Y* if a global Y has seen already, or as taking X::Y* if it hasn’t
    void Func(class Y* Param);
}

// Will compile only if A::B has been declared already, making it redundant as a forward declaration
void Func2(class A::B* Param);

Steve

Basically, it only really works for global stuff declaring other global stuff. And only if that global stuff isn’t an enum or template.

Steve

Thanks, that explains a lot.

…but, just a curiosity about that case in Character.h.

At the top there is a forward declaration, then variables and functions with ‘elaborated type specifier’ for the same class:

class USkeletalMeshComponent;
class ENGINE_API ACharacter : public APawn
{
	class USkeletalMeshComponent* Mesh;
	class USkeletalMeshComponent* GetMesh() const;
}
FORCEINLINE USkeletalMeshComponent* ACharacter::GetMesh() const { return Mesh; } //<- And one without elaborated type specifier

Are those just some leftover?

Yeah, it’ll be legacy stuff, or possibly copy+paste in the case of the Mesh and GetMesh() declarations. It’ll probably get tidied up at some point.

Steve