Circular Dependency: How do you subclass a base class with a TArray of your subclass?

Title gore, I know.

I am having this circular dependency that I don’t know how to solve.

I have a base class with a UPROPERTY() marked TArray of a subclass. That is needed because the subclass will have the same functions as the base class, and the subclass is used for interacting with the base class.

I will need to put a subclass header #include at the top of the base class for the TArray, and the subclass will need a base class header #include so that the subclass can be able to inherit from the base class.

Confused?

Picture Time!

ue4_depends.png

How do I solve this? I used header guards (#ifndef, the #define), and the #pragma once is already generated by default. All of these don’t work.

Hi,

In general a base class will have no knowledge of it’s sub classes, when you make these sorts of dependencies your going against the ideas of abstraction that classes offer.

You could do something like this to declare the class and then remove the header:



TArray<class SubClass*> SubclassArray;


But the better way to do it would be to use virtual functions for the functions that the base class will use and store an array of pointers to the base class. In your base class header:



class BaseClass
{
...
virtual void SomeFunction();
...
TArray<BaseClass*> ObjectsArray;
}


Then in your sub class you can override that function:



class SubClass : public BaseClass
{
...
virtual void SomeFunction() override;
...
}


Then when you call ObjectsArray[n]->SomeFunction() it will call the function on the sub classes’ version of the function instead of the base class.

Yet another way to do this would be instead or storing an array at all make some protected function in base class for the subclass to call when they need to interact with it. Eg:



class BaseClass
{
...
protected:

void DoSomeThingWithBaseClass(struct FData& Data);
...
}


What exactly is the best way to do it really depends on your use case. If you can post more details about what exactly it is you need to do I can probably make a better suggestion but you almost certainly don’t want to have your baseclass depending on some subclass.

The base class does not have FRotator. The sub class has FRotator.
The base class can only move. The sub class can only turn.
Both classes have same functionalities, the same components, the same colliders, the same physics and collision presets, and the same properties (materials, etc.).

The base class has a TArray that remembers where the subclasses are in the world. The sub classes only remembers other subclasses and not itself. You’ll have a chain of subclasses starting from the base class. One key press, “Turn”, will cause all subclasses to turn by a certain number of angles, creating a tail that curls in a direction.

That is what I am doing right now.

I don’t think you need to use more than one class here at all. Correct me if I’m wrong but what you want to do is control the movement and rotation of a tail by recusing from a point in the tail to propagate the movement and rotation to all points in the tail ‘under’ that point?

What I would do is have some sort of tail class that holds an array of tail components and then when you want to transform if you can start at index i and go to n applying the transformation.

In your description it seems like you would make a new subclass for each section? This isn’t really what subclasses are meant for. They should extend and/or modify the data and functions of the first class, ie all classes that extend AActor are an actor but also do something else. If you’re only changing the data then you should be making a new object of the class.

So I should be extending UActorComponent for the tail components so that the base Actor class have all references to the components? I can nest components inside components, however deep it may go?

Check out Forward Declaration. It’s your friend in times like these :slight_smile:

I didn’t know UE4 allows forward declaration of classes. I was getting the impression that UCLASS() can’t do forward declaration due to the heavy usage of macros.