Accessing pointers to child class instances from parent class

Hi, I have the following setup:
I have a CharacterClass which has several Components which all inherit from a BaseComponent class. In the BeginPlay of the BaseComponent class I run a protected RegisterComponent(UBaseComponent* Component) method which the child classes all run as RegisterComponent(this). My BaseComponent class then stores the references to the child classes by trying a cast to their specific class types. I have the BaseComponent class log out a message when a child component is successfully registered. This happens for all of them.

Now I’m trying to access the reference of ChildComponentClass1 from ChildComponentClass2 for example. Seeing as the instance pointers I have stored on the BaseComponent class is protected, I’d expect to be able to access this pointer, but when I do a null check from ChildComponentClass1, ChildComponentClass2 is not initialised. Am I doning something super nooby, or can anyone suggest a better way of letting component classes communicate without having to involve my container class (CharacterClass)?

Here is the relevant source code.

BaseComponent.h

UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class MYGAME_API UBaseComponent : public UActorComponent
{
	GENERATED_BODY()

public:	
	// Sets default values for this component's properties
	UBaseComponent();

protected:
	// Called when the game starts
	virtual void BeginPlay() override;
	
    void RegisterComponent(class UBaseComponent* Component);

	bool IsSafePointer(class UBaseComponent* Component, FString ComponentName);


	//keep a reference to all components so they can be recalled
	class UChildComponent1* ChildComponent1 = nullptr;
	class UChildComponent2* ChildComponent2 = nullptr;
	class UChildComponent3* ChildComponent3 = nullptr;
	
	
};

BaseComponent.cpp

#include "MyGame.h"
#include "ChildComponent1.h"
#include "ChildComponent2.h"
#include "ChildComponent3.h"
#include "BaseComponent.h"


// Called when the game starts. BeginPlay() should be run as Super::BeginPlay() on each child class to register them
void UBaseComponent::BeginPlay()
{
	Super::BeginPlay();

	/** Calls the RegisterComponent Method and passes its own instance in, registering a pointer to itself for other components to access */
	RegisterComponent(this);
	
}

// BeginPlay should be run as Super::BeginPlay on each child class to register them
void UBaseComponent::RegisterComponent(UBaseComponent * Component)
{
	// Try to cast to each component sub-type and if successfull, register pointer and return out of the method
	ChildComponent1 = Cast<UChildComponent1>(Component);
	
    if (ChildComponent1 != nullptr)
	{
		UE_LOG(LogTemp, Warning, TEXT("Registered %s "), *ChildComponent1 ->GetName());
		return;
	}

    ChildComponent2 = Cast<UChildComponent2>(Component);
	
    if (ChildComponent2 != nullptr)
	{
		UE_LOG(LogTemp, Warning, TEXT("Registered %s "), *ChildComponent2 ->GetName());
		return;
	}

    //etc...

	

}

bool UBaseComponent::IsSafePointer(UBaseComponent * Component, FString ComponentName = FString("Undefined"))
{
	if (Component != nullptr)
	{
		return true;
	}
	else
	{
		UE_LOG(LogTemp, Error, TEXT("Component Pointer Test Failed on: %s"), *ComponentName);
		return false;
	}
	
}

The Child Classes simply extend UBaseComponent and run Super::BeginPlay(). Then at some point after all child components are registered, Child 1 tries to access Child 2 though the IsSafePointer method which in turn fails. Child 1 has Child 2’s .h file included in its .cpp file.

Any ideas?

Many thanks in advance! :slight_smile:

Nik

I think you may misunderstand something, code in parent classes effects the same object they been called to and parent class code is simply running at that child object and nothing else. So if you make object of child class, you will only effect that child object so what happens with your code is:

Child 1 created

Child 1 Begin play

Child 1 register to child 1’s ChildComponent1 varable

Child 2 created

Child 2 Begin play

Child 2 register to child 2’s ChildComponent2 varable

So all it doing is setting this on it’s own object, which kind of seems pointless :stuck_out_tongue:

To do what you want to do, you need to keep those variables in more general object, in case of components, the best place for that would be actor that host them.

Thanks, . Embarrassingly, the answer came to me as soon as my head hit the pillow last night. I will admit it was very late and I wasn’t really thinking clearly. It seems so obvious now facepalm. I think your suggestion of just accessing the instance pointers through the container class makes the most sense. Thanks for taking the time!
Nik