Конструктор запрашивает неправильное количество аргументов

Я создал класс в Unreal под названием Groundmode.

GroundMode.h: #pragma один раз

#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() {}

Я хочу иметь возможность создать экземпляр этого класса в другом классе. 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();
    }

Когда я пытаюсь создать экземпляры UGroundMode с новым ключевым словом, я получаю следующую ошибку компиляции: D:\Documents\Unreal Projects\NMR\Source\NMR\PlayerPhysicsCollisionInfo.cpp(25): ошибка C2661: 'UGroundMode::operator new' : ни одна перегруженная функция не принимает 1 аргумент

Что я делаю не так? Конструктор не принимает аргументов кроме 1.


person user2725919    schedule 23.05.2020    source источник
comment
Вы не new UObjects и не храните их нигде по значению. Пожалуйста, начните с некоторых базовых руководств по UE C++.   -  person Rotem    schedule 23.05.2020
comment
Как будто я и не думал делать туториалы. :P Все, что я могу найти, отстой.   -  person user2725919    schedule 23.05.2020
comment
@user, возможно, вы искали одобренные материалы от Epic? unrealengine.com/en-US/resources   -  person JohnFilleau    schedule 23.05.2020


Ответы (1)


Выражение new, как вы делаете здесь, делает две вещи.

  1. Он выделяет память для объекта, вызывая соответствующую функцию выделения для этого объекта.
  2. Он создает объект в этой выделенной памяти.

Когда он вызывает функцию распределения для класса T, он сначала определяет размер этого класса, std::size_t size, и передает его в качестве первого параметра функции распределения. Функция распределения для класса — это первая разрешенная operator new() функция, доступная классу в пределах его области действия. Любые необязательные параметры размещения затем отправляются в качестве следующих параметров в функцию размещения. Параметры размещения — это выражения, заключенные в круглые скобки сразу после ключевого слова new:

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)`

Ваша проблема заключается в том, что выражение new пытается выполнить выделение и находит соответствующее operator new(). Классы могут переопределять operator new(), что и делает ваш класс. Ключевое слово new примет sizeof(T) и попытается отправить его в качестве первого параметра функции operator new, определяемой классом.

Вы спросите, где эта перегруженная функция operator new(), определяемая классом?

Прямо здесь

UObject, от которого наследуется ваш класс, имеет объявленную функцию void* UObject::operator new(), которая принимает пять, считайте их ПЯТЬ, параметров.

Ключевое слово new идентифицирует этот operator new() как operator new() вашего класса, но видит, что вы передаете только один параметр (sizeof(T)), и терпит неудачу.


Решение

Как описано на связанной странице Unreal, выражения new нельзя использовать с объектами UObject. Вместо этого используйте StaticConstructObject().


Если вы все равно хотите вызвать глобальный operator new

Если вы хотите сделать движок Unreal еще нереалистичнее, вы можете указать соответствующую функцию operator new, явно указав ее область видимости. Вы можете попытаться получить доступ к глобальной функции operator new(), поместив индикатор глобальной области действия перед оператором new:

downMode = ::new UGroundMode();

Конечно, тогда вы столкнетесь с проблемой, что ::new UGroundMode(), как и любая другая операция new, возвращает UGroundMode*, который вы пытаетесь сохранить в объекте UGroundMode. Это не удастся. Я не знаю, что будет делать движок Unreal. Наверное, плохие дела.


дальнейшее чтение

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

person JohnFilleau    schedule 23.05.2020
comment
Насколько я знаю, вам следует звонить NewObject<T>, а не StaticConstructObject. Кроме того, вы должны указать любые UObject как UPROPERTY, и вы можете пометить их спецификатором свойства Instanced, чтобы объект был создан автоматически в содержащем классе. - person Rotem; 23.05.2020
comment
@Rotem не стесняйтесь редактировать ответ. Я ничего не знаю об Unreal. - person JohnFilleau; 23.05.2020
comment
@Rotem Было бы неплохо, если бы вы сказали что-то подобное, а не комментировали стиль обучения кодированию. Спасибо, хотя я попробую это, поскольку я не могу заставить работать StaticConstructObject. Я отредактирую ответ, как только выясню это. - person user2725919; 24.05.2020
comment
@user2725919 user2725919 Мой первоначальный комментарий не был подлым или пренебрежительным, извините, если он таковым оказался. Это просто звучало так, как будто вы находитесь на этапе с UE, на котором вам было бы гораздо лучше прочитать вводную документацию по C++ об UObjects. - person Rotem; 25.05.2020
comment
@Rotem Хорошо, извини за чрезмерную реакцию. Это расстраивает из-за ограниченных ресурсов для изучения Unreal. Тонны информации о том, как использовать чертежи, очень мало на C++ за пределами прямой документации. Я буду читать документацию по UObjects. - person user2725919; 25.05.2020
comment
Помните, что лучшая документация — это исходный код движка. Каждый раз, когда я хочу понять, как сделать что-то, я просто проверяю, как Epic сделал что-то подобное. - person Rotem; 25.05.2020