Download

How do I make the constructor call the child's version of a function?

Hi everyone. Old-school UE3 programmer here. I’m starting my very first C++ project and I have no idea what I’m doing. I’m trying to make two classes, one parent, and one child. I want the parent to be a hexagon-shaped static mesh and I want the child to be a pentagon-shaped static mesh. This is what I’ve done:

HXWorldNode.h



class HXGAME_API AHXWorldNode : public AActor
{
    GENERATED_BODY()

   public:
   AHXWorldNode();
   UStaticMeshComponent* VisualMesh;
   virtual void BuildStaticMeshComponent();
};


HXWorldNode.cpp



#include "HXWorldNode.h"

AHXWorldNode::AHXWorldNode()
{
   VisualMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));
   VisualMesh->SetupAttachment(RootComponent);

   BuildStaticMeshComponent();
}

void AHXWorldNode::BuildStaticMeshComponent()
{
   static ConstructorHelpers::FObjectFinder<UStaticMesh> HexVisualAsset(TEXT("/Game/HexWorld/hexagon.hexagon"));

   if (HexVisualAsset.Succeeded())
   {
      VisualMesh->SetStaticMesh(HexVisualAsset.Object);
      VisualMesh->SetRelativeLocation(FVector(0.0f, 0.0f, 0.0f));
   }
   UE_LOG(LogTemp, Log, TEXT("Made a hexagon!"));
}

HXWorldNode_Pentagon.h



class HXGAME_API AHXWorldNode_Pentagon : public AHXWorldNode
{
   GENERATED_BODY()
public:
   virtual void BuildStaticMeshComponent() override;
};


HXWorldNode_Pentagon.cpp



#include "HXWorldNode_Pentagon.h"

void AHXWorldNode_Pentagon::BuildStaticMeshComponent()
{
   static ConstructorHelpers::FObjectFinder<UStaticMesh> HexVisualAsset(TEXT("/Game/HexWorld/pentagon.pentagon"));

   if (HexVisualAsset.Succeeded())
   {
      VisualMesh->SetStaticMesh(HexVisualAsset.Object);
      VisualMesh->SetRelativeLocation(FVector(0.0f, 0.0f, 0.0f));
   }
   UE_LOG(LogTemp, Log, TEXT("Made a pentagon!"));
}


When I try to drop one of my pentagons into the world, it makes a hexagon and in the log it says “Made a hexagon!” How do I make a HXWorldNode_Pentagon use AHXWorldNode_Pentagon::BuildStaticMeshComponent()?

And for bonus points, how can I replace the different functions with a different string? Instead of “/Game/HexWorld/hexagon.hexagon” and “/Game/HexWorld/pentagon.pentagon” in their different functions, how can I replace that with a variable?

Thanks for helping this old dog learn new tricks.

And if I put all of BuildStaticMeshComponent()'s functionality directly into the constructor, it compiles, but it crashes the editor with this error:


Default subobject StaticMeshComponent Mesh already exists for HXWorldNode_Pentagon /Script/HXGame.Default__HXWorldNode_Pentagon.


Edit: I fixed this one by just leaving the line “VisualMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT(“Mesh”));” out of the child class. And I can choose the mesh I want by setting it up in the constructor.

try not over riding it, just take this out



virtual void BuildStaticMeshComponent() override;

from your HXWorldNode_Pentagon.h file. See if that will fix it.

Thanks, but if I take that line out the header file, and leave the function in the HXWorldNode_Pentagon.cpp file, I get this error:


'BuildStaticMeshComponent': member function not declared in 'AHXWorldNode_Pentagon'

And if I rename the function in HXWorldNode_Pentagon.cpp to AHXWorldNode::BuildStaticMeshComponent() I get this error:


 (?BuildStaticMeshComponent@AHXWorldNode@@UEAAXXZ) already defined in HXWorldNode.cpp.obj; second definition ignored

Interesting, i guess the rule that a derived class will see base class public or protected stuff as public in the derived class is not so in this engine?

You can’t do this in C++.

Conceptually while executing the HXWorldNode constructor, the object is only a HXWorldNode and is not an HXWorldNode_Pentagon yet. This is why calling the virtual function won’t execute overrides.

The solution for this outside of UE4 is usually some post-construction function. But since you are in UE4 and your types are actors, I would suggest moving that functionality to an override of the Actor::BeginPlay function. There are also earlier ones, but BeginPlay is usually my first try.

If you make that change, then the string won’t matter because you won’t be able to use the ConstructorHelper anyway. I’m not sure what an equivalent would be, usually I’d do that with a blueprint so that all asset references are setup in editor. You might be able to set it up as a member that is a TSoftObjectPtr and configured through an ini.

You cannot call a virtual function in constructor.
https://scc.ustc.edu.cn/zlsc/sugon/intel/ssadiag_docs/pt_reference/references/sc_cpp_virtual_call_in_ctor.htm

Instead, you can override AActor::PostActorCreated.

Thanks for that info. That Explains a lot.

Sweet that should help me get my model(start gate) in thru adding its class. Every time i added the class thru the editor it would crash and not show me the start gate and say the making of the model was crashing the game. Now i know why, thanks a bunch.

Edit: Did not help me like i thought it would. thanks for the good info.