0

I have build a class in Unreal called Groundmode

GroundMode.h: #pragma once

#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "Components/BoxComponent.h"
#include <NMR\GroundDirection.h>
#include "GroundMode.generated.h"

UCLASS()
class NMR_API UGroundMode : public UObject
{
    GENERATED_BODY()

    public:
        UGroundMode();   
};

GroundMode.cpp:

#include "GroundMode.h"

UGroundMode::UGroundMode() {}

I want to be able to instantiate this class in another class. PlayerPhysicsCollisionInfo.h

#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "GroundMode.h"
#include "PlayerPhysicsCollisionInfo.generated.h"


UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class NMR_API UPlayerPhysicsCollisionInfo : public UActorComponent
{
    GENERATED_BODY()

public: 
    UPlayerPhysicsCollisionInfo();

    UGroundMode downMode;
    UGroundMode upMode;
    UGroundMode leftMode;
    UGroundMode rightMode;
};

PlayerPhysicsCollisionInfo.cpp: #include "PlayerPhysicsCollisionInfo.h"

    void UPlayerPhysicsCollisionInfo::BeginPlay()
    {
        Super::BeginPlay();
        downMode = new UGroundMode();
        upMode = new UGroundMode();
        leftMode = new UGroundMode();
        rightMode = new UGroundMode();
    }

When I attempt to create instances of UGroundMode with the new keyword I get the following compile error: D:\Documents\Unreal Projects\NMR\Source\NMR\PlayerPhysicsCollisionInfo.cpp(25) : error C2661: 'UGroundMode::operator new': no overloaded function takes 1 arguments

What am I doing wrong? The constructor takes no arguments not 1.

user2725919
  • 197
  • 1
  • 4
  • 15

1 Answers1

2

The new expression, like you're doing here, does two things.

  1. It allocates memory for the object by calling an appropriate allocation function for that object.
  2. It constructs the object in that allocated memory.

When it calls the allocation function for a class T, it first determines the size of that class, std::size_t size, and passes that as the first parameter to the allocation function. The allocation function for a class is the first resolved operator new() function available to a class within its scope. Any optional placement params are then sent as the next parameters to the allocation function. Placement params are parentheses-enclosed expressions immediately after the new keyword:

T* foo = new T(); // good old fashioned uncomplicated new
          ^
          |
          +---- wants to call a `operator new(std::size_t)` function

T* bar = new(1, 2) T(); // a little more complicated
          ^    ^
          |    |
          |    +----- these are placement params
          +---------- wants to call `operator new(std::size_t, int, int)`

Your issue is when the new expression tries to do the allocation and finds its appropriate operator new(). Classes can override operator new(), which your class does. The new keyword will take sizeof(T), and attempt to send that as the first parameter to the class-defined operator new function.

Where is that class-defined overloaded operator new() function, you ask?

Right here

UObject, which your class inherits from, has a void* UObject::operator new() function declared that takes five, count 'em FIVE, parameters.

The new keyword identifies this operator new() as your class' operator new(), but sees that you're only passing the one parameter (sizeof(T)), and fails.


The solution

As described on the linked Unreal page, new expressions are not to be used with UObject objects. Use StaticConstructObject() instead.


If you want to call the global operator new anyway

If you want to make Unreal engine even unrealer, you can specify an appropriate operator new function by explicitly scoping it. You can attempt to access the global operator new() function by putting the global scope indicator at the front of you new statement:

downMode = ::new UGroundMode();

Of course, then you'll run into the problem that ::new UGroundMode(), like any other new operation, returns a UGroundMode* which you're trying to store in a UGroundMode object. This will fail. I don't know what it will do the Unreal engine. Probably bad things.


Further reading

https://en.cppreference.com/w/cpp/language/new
https://en.cppreference.com/w/cpp/memory/new/operator_new

JohnFilleau
  • 4,045
  • 1
  • 15
  • 22
  • AFAIK you should call `NewObject`, not `StaticConstructObject`. Furthermore, you should specify any `UObject`s as `UPROPERTY`, and you can mark them with the `Instanced` property specifier so that the object will be constructed automatically in the containing class. – Rotem May 23 '20 at 15:26
  • @Rotem feel free to edit the answer. I don't know anything about Unreal. – JohnFilleau May 23 '20 at 19:17
  • @Rotem Would have been nice if you had said something like that rather then making a learn to code style comment. Thanks though I'll try that as I cannot get StaticConstructObject working. I'll edit the answer once I figure it out. – user2725919 May 24 '20 at 03:13
  • 1
    @user2725919 My original comment was not meant to be mean or dismissive, I'm sorry if it came across as such. It just sounded like you are at a stage with UE in which you would be much better served by reading the introductory c++ documentation about UObjects. – Rotem May 24 '20 at 21:29
  • @Rotem Okay sorry for over reacting. Its frustrating because of the limited resources for learning Unreal. Tons of info on how to use blueprints very little on C++ outside of straight documentation. I will read the documentation about UObjects. – user2725919 May 25 '20 at 04:05
  • Remember that the best documentation is the engine source code. Any time I want to figure out how to do something I just check how Epic did something similar. – Rotem May 25 '20 at 13:27