首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

为什么委托构造函数不能按预期工作UE4

委托构造函数是C++11引入的一种构造函数重用的机制,允许一个构造函数委托给同一个类的另一个构造函数进行部分或全部的工作。然而,在UE4引擎中,委托构造函数无法按预期工作,这是因为UE4的构造函数实现方式与标准C++有一些不同。

在UE4中,构造函数的实现依赖于蓝图编辑器和引擎的反射系统。蓝图编辑器允许开发人员使用可视化界面来创建和编辑游戏逻辑,这就导致了一些与标准C++不同的行为。由于委托构造函数在编译时需要解析和处理,而蓝图编辑器中的对象是在运行时才创建的,所以UE4无法正确处理委托构造函数。

具体来说,UE4引擎将所有的构造函数视为蓝图编辑器中可用的可选构造函数,并且通过引擎的反射系统进行管理。由于委托构造函数不符合UE4的构造函数管理机制,因此无法在蓝图编辑器中正确使用。

要解决这个问题,开发人员可以采用其他方法来达到构造函数重用的目的。一种常见的方法是使用初始化列表(initializer list)来初始化成员变量,从而减少代码的重复。另一种方法是使用辅助函数或工厂函数来封装公共的构造逻辑,然后在不同的构造函数中调用这些函数。

总结起来,委托构造函数无法按预期工作是因为UE4引擎的构造函数实现方式与标准C++有所不同,而且在蓝图编辑器和引擎的反射系统中无法正确处理委托构造函数。开发人员可以通过使用初始化列表、辅助函数或工厂函数等其他方法来实现构造函数的重用。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

UE4的智能指针 TSharedPtr

因为std的做不到全平台可用,UE4的智能指针可以无缝兼容UE4的容器,可以不要求保证线程安全,这样能带来更好的性能,允许赋值空指针,提供了一些UE4自己的辅助函数,而且UE4的性能更好(包括将函数inline...为什么要专门提这一点,是因为UE4里有些比较睿智的API,理论上可以接受空对象,但函数的参数却只接受TSharedRef而不要TSharedPtr,这时还是可以自己搞个空壳对象换掉TSharedRef里的老对象...,后面有个回调,成功加载好了之后再对this做剩下的事情,这里肯定就会把this作为lambda的upvalue(我也不知道应该叫什么就延用lua的命名吧,ue4委托内部叫payload),这时怎么保证在加载期间...UE4委托提供了CreateSP静态函数,方便快速创建带智能指针的Delegate,可以直接把AsShared的结果作为参数传进去。...你可能会好奇,为什么要这么中转一遍,直接在构造函数里调用UpdateWeakReferenceInternal不就好了吗?

2.4K20

UE4 如何实现与 iOS 原生之间的数据交互

作为 2021 年的第一个工作日,好的文章肯定是少不了的,今天就来给大家讲讲 UE4 开发在移动平台中最重要的一个环节: 数据交互。...可能大家要笑了,委托不就是 delegate 吗? iOS 用的熟的不要再熟了,没错,UE4委托与 iOS 的委托其实是一个道理,只是在代码实现的形式上有所区别....实现一个委托,需要执行以下几步操作: 声明委托 声明委托,需要用到 UE4 提供的特定宏来声明,UE4委托提供了如下的宏定义: 本篇的就实现的简单一点,因为我在上面定义的回调函数只有一个返回值,所以我就使用...委托声明好了,那接下来就是要将回调函数绑定到委托上,在这里我用了 CreateUObject 这个函数来绑定委托,这样当我们的委托执行这个这个回调函数的时候,就会触发 testCallBack ,我们就能获取到回调值了...通过调用 Execute() 函数来执行绑定到委托的回调函数,不过为了检查执行前委托是否已经绑定,所以这个我用这个函数来执行比较安全:ExecuteIfBound(), 代码如下: #pragma once

1K30
  • UE4的TripleBuffer

    先看构造函数和析构函数 可以外部提供3个Buffer传进来,也可以内部new出来3个BufferType类型的Buffer,其中BufferType是模板的参数,需要业务用的时候自己指定,如果是内部new...因为有3个Buffer,这个Buffer在构造的时候是个3个元素的数组,所以我们可以用下标来表示Read,Write,Temp分别用的是第几个数组。...那既然TripleBuffer这么好用,为什么UE4内部用的这么少呢?可以全局搜索,除了一个Test代码,基本没有地方在用。...验证结果,无论读写快慢,最终可以看到完全符合了预期。...但TQueue就完全不会有这样的问题,所以这就解释清楚了为什么UE4内部在要求高性能的场景,即使有大量内存碎片也要使用TQueue(其实每次都new问题不严重,因为UE4有实现自己的内存池,重载了new

    90410

    UE4的TArray(一)

    TArray,是UE4的可动态扩容数组容器,是UE4里最常见,也是用的最多的一种容器,类似于STL中的vector,除了数组的基本功能外,还有一些从性能上来考虑的设计很有亮点,我觉得可能更适合游戏使用吧...TArrayView类似于动态span,而span使用默认STL需要开启C++20,ue4默认是C++14的,这里也是UE4比较有优势的一点。...在提供这么多拷贝构造函数的同时,也对等重载了operator =,具体实现和拷贝构造函数差不多。...其中初始化列表的拷贝构造函数和等号重载运算符,具体是这样使用的: 除了拷贝构造函数外,还提供了C++11新增的移动构造函数 可以看到内部实现,移动构造函数只是把传入TArray的Allocator的指针和数组容量拷贝到当前数组...可能会好奇,为什么移动构造函数里调用的函数是MoveOrCopy,什么情况会发生拷贝呢?

    2.8K10

    UE4的智能指针 UObject相关

    其中最上层的基类是UObjectBase,他在创建的时候会把自己交给UE4的两个全局容器来管理,在销毁的时候把自己从管理自己的容器中移除,具体可以看下面这张图: 1 创建 在UObjectBase构造函数中...你可能会好奇为什么这里调用的改名函数呢?...创建的时候,两个容器都是在构造函数中一起加进去的,而销毁的时候Hash在BeginDestroy就清理了,而Array在析构函数才清理,这是一个要注意的地方,为什么有的对象可以在UObjectArray...上面Init函数是成员函数,那么每个对象调用Init时候肯定都会调用一次StaticInit,但StaticInit内部只有在对象GGCObjectReferencer为NULL时候才会执行,所以即使调用了多次真正只会构造一个...在FGCObject构造函数中可以看到,就直接调用了Init,在析构函数中调用了GGCObjectReferencer->RemoveObject(this),这就说明了FGCObject自己存活的时候就在

    3.1K30

    UE4 中通过单例类实现全局数据管理

    初学者必知的UE4新建关卡时的一些设置【虚幻引擎】。控件 UI 的摆放如下图所示,一个蓝色按钮和一个红色按钮,下面对应是蓝色方和红色方的比分。图片然后修改关卡蓝图,将 UMG 添加到视口。...图片最后启动运行关卡,预期能看到以下画面。图片二、C++ 代码新建 C++ 类,注意需要打开 显示所有类,继承自 Object 父类,并将生成的类命名为 Singleton,如下图所示。...图片图片编辑源码如下,需要注意的是由于反射机制, ue4 中的构造函数没办法转为私有。...图片图片编写完成后,保存并编译,接下来启动关卡,预期效果如下图所示。每点击一次蓝色按钮,蓝色比分加一;每点击一次红色按钮,红色比分加一。...WikiUE4[C++]在虚幻引擎实现单例模式 - 知乎[UE4]线程锁FScopeLock用法_玄冬Wong的博客-CSDN博客

    1.6K21

    C++(UE4) Memory Management Review

    以下是关于 C++(UE4) 内存管理的一点简单分享 原始方式(Raw) malloc/free 是 C 中用于分配内存和释放内存的主要方式 new/delete 是 C++ 中用于分配内存和释放内存的主要方式...,除了内存管理之外, new/delete 还负责调用对象的构造函数和析构函数 new[]/delete[] 是 new/delete 的数组形式 比较重要的一点是, new/delete 等内存管理的调用一定要匹配...,然后在该内存处调用对象的构造函数 delete 运算符表达式基本也分为两步操作,首先调用对象的析构函数,然后调用 operator delete 函数释放对象的内存 operator new 与 operator...delete 可以定制重载 UE4 进行了自己的重载工作(通过宏等方式) new 还有一些"变种"操作,譬如 placemenet new 等等,更多信息可以在这里找到 正常方式(Normal)...原始的内存管理方式存在很多问题,譬如逻辑控制上很难做到没有遗漏,而且让程序员人为的保证调用的匹配本身也非常困难 借助值语义对象的构造函数和析构函数可以帮助我们改善这个问题 这种方式有个专用名词: RAII

    1.1K30

    UE4的队列TQueue

    游戏引擎肯定要优先保证性能,所以这就是为什么UE4没有选择std::deque或TChunkedArray类似数据结构来实现队列的原因。 那UE4的队列是怎样做的?...为什么要这样写 quabqi:UE4的TripleBuffer TTripleBuffer的成员变量 先看Align(16),16字节对齐这个很好理解,C++的字节对齐上限std::max_align_t...怎样保证操作是原子的,这里后面来说 构造和析构函数: 默认就会new一个空节点,作为头和尾,虽然浪费一个节点内存,但这样就不用判断空指针的情况。...具体流程是让Tail指向自己的Next,并把旧数据用默认构造的对象覆盖掉,再删掉更老的无效节点,就完成任务了。可以看到这里的代码连MemoryBarrier都没有加。...UE4全局重载了new和delete,实际调用的是FMemory上的Malloc和Free函数 可以在TQueue的注释上看到下面这句,说明UE4的开发同学确实意识到了这个问题,可以搞个节点池化,但可能还没来及做或没考虑好怎样实现最优吧

    2.9K30

    UE45 usf、ush UniformBuffer的黏合过程

    已有文章中简单提到过,这里再以另外的视角更详细地描述整个过程 UE4 HLSL 和 Shader 开发指南和技巧 第一次写UE shader大概都会疑惑,usf、ush里面的那些“View“、“BasePass...FMobileBasePassUniformParameters, "MobileBasePass"); 去初始化这个FShaderParametersMetadata,在FShaderParametersMetadata的构造函数中会将自己加入的一个全局的链表中...启动阶段收集了每个ShaderType所使用的UniformBuffer(TMap的Key)名称,它们的声明会在必要时(一般是材质编译时)生成,同样也是字符串 这对应最终shader中的内容 至于为什么会是注释...模块(Worker或Block单线程编译)的是一个Input,其中主要也就包括FShaderCompilerEnvironment 以D3DCompile为例,在进入CompileD3DShader函数之后主要工作是根据...所以如果不小心使用了一个Uniform结构不存在的成员,那么它不会进行替换,最终的编译报错同样会是 undeclared identifier xxx(结构名),这在不留意的时候可能会非常令人迷惑 以上过程UE4

    1.4K30

    UE4的TSparseArray

    UE4里也有一个这样的容器,但是内部实现却跟安卓的版本完全不同,我个人觉得UE4版本的实现,才是名副其实的SparseArray,而谷歌的版本从功能上来说叫SparseMap可能更合适。...为什么要介绍TSparseArray这个容器呢?你可能觉得这个容器你平时都没有用到,看名字又很冷门,即使不知道对写程序能有什么影响?...其实并不是这样的,只要你在写UE4程序,那么这个容器你就基本上一直在用,因为他是TMap和TSet内元素的容器,你使用TSet和TMap时数据实际就存在内部的TSparseArray中,UE4的TMap...FSparseArrayAllocationInfo,这是个临时变量,只用来返回结果,有两个元素Index和Pointer,分别表示这个元素的位置和内存地址,这样外面就可以在Pointer上调用placement new来调用构造函数了...(C++的placement new只调用构造函数,不会分配内存) 为什么能直接在这个结构上,而不是在内部Pointer上调用呢,是因为专门实现了这个运算符,如下图所示,返回的就是Pointer,所以实际就是在

    1.4K20

    帮助面向对象开发者理解关于JavaScript对象机制

    当我们创建一个新对象的时候,发生了什么,对象、构造函数和原型到底什么。...当调用构造函数创建实例后,该实例的内部会包含一个指针(内部对象),指向构造函数的原型对象。...__proto__是对象的原型指针,prototype是构造函数所对应的原型指针。 语法糖做了什么 ES6推出了class语法,为定义构造函数和原型增加了便利性和可读性。...构造函数用于定义实例属性和方法,仅负责创造对象,与对象不存在直接的引用关系。 __proto__是对象的原型指针,prototype是构造函数的原型指针。...委托行为意味着某些对象在找不到属性或者方法引用时会把这个请求委托给另一个对象。对象之间的关系不是复制而是委托

    44520

    UE4 EditorPIE比移动端卡顿的可能原因

    这篇文章不长篇分析代码了,因为部分工作和想法由于时间、成本关系我也没完整验证,开个短文章讨论,或许有相同问题解决经验的朋友也能带来一些想法(之前也确实听其它公司的同学聊过一些他们遇到的问题)。...但实际发现在PIE中重命名时flush并不是必须的,所以可以考虑扩展一个不flush的函数,供gameplay中创建服务器对象设置名称这种情况使用。...个人觉得这是比较关键的导致差异性的原因,可能很多人会想这种和平台硬件没关系的代码为什么不能做到PC和移动端代码一致?这样对业务开发、debug、性能内存分析各种地方都有巨大好处。...UE4 Package加载的分析可以阅读一下别人的文章 UE4加载模块分析笔记(一) UE4加载模块分析笔记(二) 其实评论区就不止一个人有疑问,为什么Editor设计成这样,这也是我刚看到时的最大疑问...我觉得理论上是可行的,我确实也做过一些尝试能大体正确地跑起来,但因为改得太底层怕有一些没考虑完全的地方,所以一直只当做实验性的工作,有问题长期发现。

    99910

    ·方法

    “input-parameters” —— 在小括号()里面,它是没有类型化的参数,为什么不用声明参数类型,其实编译器会根据上下文(根据委托的签名)推断出其类型,有点像动态语言的做法。...“member“ —— 成员,是指方法、属性、构造函数等待   2. “=>”  —— 运算符。   ...以下代码编译会报错:“无法将 lambda 表达式 转换为预期委托类型,因为块中的某些返回类型不可隐式转换为委托返回类型 ”,因为签名不一样。   ...·构造函数   构造函数的表达式主体定义通常包含单个赋值表达式或一个方法调用,该方法调用可处理构造函数的参数,也可初始化实例状态。   ...以下示例定义 Location 类,其构造函数具有一个名为“name”的字符串参数。 表达式主体定义向 Name 属性分配参数。

    71870

    UE4的资源管理

    为什么要做资源管理? 开发一个大型游戏,因为美术资源和游戏数据都是海量的,不可能把所有的数据都放在内存里。...对于UE4来说,这个过程大概有这几个步骤: 读取资源文件的数据到内存 根据内存的二进制数据,把空壳对象反序列化成实际的对象 如果这个对象有依赖其他对象,就递归的去做1和2的操作,直到这个对象完整可用 调用对象的初始化函数...这个函数就是UE4资源加载的大入口,后面整套资源加载都隐藏在了这个函数之后。...首先看参数,有路径,加载完成的回调委托,以及返回一个加载的handle。...并等待所有依赖资源完成 加载所有的Export对象,这一步有IO 执行PostLoad,并把对象加入引擎管理,完成加载 EDL流程 在EDL内部会把加载流程拆成多个Event,每个Event会做对应的工作

    3.1K30

    C#3.0新增功能10 表达式树 04 执行表达式

    例如,此代码工作正常,因为 int 不实现 IDisposable: private static Func CreateBoundFunc() { var constant...在稍后执行 CreateBoundFunc 返回的函数之后,可随时访问该变量。...现在,在执行从此方法返回的委托时,将在执行时引发 ObjectDisposedException。 出现表示编译时构造的运行时错误确实很奇怪,但这是使用表达式树时的正常现象。...总结 可以编译表示 lambda 表达式的表达式树,以创建可执行的委托。 这提供了一种机制,用于执行表达式树所表示的代码。 表达式树表示会为创建的任意给定构造执行的代码。...只要编译和执行代码的环境匹配创建表达式的环境,则一切将按预期进行。 如果未按预期进行,那么错误也是很容易预知的,并且将在使用表达式树的任何代码的第一个测试中捕获这些错误。

    86120

    关于重构的总结

    为什么要重构 重构有风险,它必须修改运行中的程序,这可能引入一些不易察觉的错误。那么,为什么我们还要重构呢?...关于测试 确保所有测试都完全自动化,让它们检查自己的测试结果 考虑可能出错的边界条件,把测试火力集中在那儿 编写未完善的测试并运行,好过对完美测试的无尽等待 当事情被认为应该出错时,别忘了检查是否抛出了预期的异常...,从来没有被其他任何类用到 以工厂函数取代构造函数构造函数替换为工厂函数 当创建对象时不仅仅是需要做简单的构建动作时 封装向下转型 将向下转型动作移到函数中 某个函数转型的对象,需要由函数调用者向下转型...处理概括关系 名称 解释 动机 字段上移 将该字段移至超类 子类拥有相同的字段时 函数上移 将该函数移至超类 有些函数,在子类中产生相同的结果 构造函数本体上移 在超类中新建一个构造函数,并在子类构造函数中调用它...,调整子类函数,改为委托超类,然后去掉两者之间的继承关系 某个子类只使用了超类接口中的一部分,或是根本不需要继承而来的数据时 以继承取代委托委托继承受托类 两个类之间存在委托关系,且极简的委托函数太多时

    98010

    JavaScript原型-进阶者指南

    在这一点上,我们知道三件事: 1.如何创建构造函数。 2.如何将方法添加到构造函数的原型中。 3.如何使用Object.create将失败的查找委托函数的原型。...回顾一下我们的Animal构造函数,最重要的两个部分是创建对象并返回它。如果不使用Object.create创建对象,我们将无法在失败的查找上委托函数的原型。...this.energy -= length } 这是为什么?for循环将循环遍历对象本身以及它所委托的原型的所有可枚举属性。...这是为什么?for循环将循环遍历对象本身以及它所委托的原型的所有可枚举属性。因为默认情况下,您添加到函数原型的任何属性都是可枚举的,我们不仅会看到名称和能量,还会看到原型上的所有方法 - 吃,睡,玩。...重新创建Object.create 在这篇文章中,非常依赖于Object.create来创建委托构造函数原型的对象。

    1.3K50
    领券