Why are you able to access UE4 classes private member variables?

When following along with the tanks vs. zombies tutorial from unreal there is section where the programmer creates a spring arm component in the tank’s constructor like so


    ATank::ATank()
    {
        USpringArmComponent* springArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("Spring Arm"));
    }


and then he goes on accessing that SpringArm’s variables and setting default values for them:



    ATank::ATank()
    {
        USpringArmComponent* SpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("Spring Arm"));
        SpringArm->CameraLagSpeed = 2.0f;
        SpringArm->TargetArmLength = 300.f;
    }


The problem is those variables - CameraLagSpeed, TargetArmLength - and others are actually private in the USpringArmComponent class in UE4:


 UCLASS(ClassGroup=Camera, meta=(BlueprintSpawnableComponent), hideCategories=(Mobility))
    class ENGINE_API USpringArmComponent : public USceneComponent
    {
    	GENERATED_UCLASS_BODY()
    
    	/** Natural length of the spring arm when there are no collisions */
    	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Camera)
    	float TargetArmLength;
    
    	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Lag, meta=(editcondition="bEnableCameraLag",   ClampMin="0.0", ClampMax="1000.0", UIMin = "0.0", UIMax = "1000.0"))
    	float CameraLagSpeed;
    
           etc..........
    }

Since in C++ the default access specifier (public, private, protected) is private when you don’t specifiy it yourself. So why are you able to access SpringArm’s variables? Does UE4’s classes actually default to the public specifier instead of private?

USpringArmComponent is still using the old GENERATED_UCLASS_BODY() macro instead of the new GENERATED_BODY() macro.
The former sets the access specifier to public. This was chaged in GENERATED_BODY(), but a large part of the UE4 source code is still using GENERATED_UCLASS_BODY().

3 Likes

UPROPERTY members cannot be private. The GENERATED_ macro contains a “public:” declaration that makes everything under it public by default.