第三章 断言

第一节 简单的断言

断言让程序的进程中断,方便程序员发现在哪里发生了问题。

AGameBase * GameBase = nullptr;
check(false);
check(GameBase);
//断言给false或者给空指针、0效果都一样,都会触发。

断言的目的是为了告诉方法或函数有问题。

第二节 额外信息断言

verifyf(false, TEXT("sssss %s"),*this->GetName());
checkf(false, TEXT("sssss %s"),*this->GetName());

这两个用起来都一样,触发断言后会在退出提示信息里提示信息内容。

第三节 阻塞流程断言

checkNoEntry();

只要经过这个函数就断。

checkNoReentry();

检测这个函数是否被执行了两次,第一次没问题不会断,第二次会断。

checkNoRecursion();

检测有没有递归,要是出现递归就直接崩。

第四节 断点式断言

ensure(0 && "check(GameBase && GameBase can not be NULL)");

程序运行到此相当于遇到断点了,点击继续可以继续运行程序。

ensureMsgf(0, TEXT("%s"), *this->GetName());

同上,并可通过此获得更多额外信息。

第四章 智能指针基础

第一节 共享指针

继承自UObject类的对象们会被GC标记,在程序关闭时释放资源。但是对于原生的类,需要使用智能指针来进行内存管理。

class TaskA{
public :
int32 a;
float b;
}
TSharedPtr<AActor> A;//这是不兼容的,共享指针会回收,AActor继承自UObject也会回收
TSharedPtr<TaskA> Task_a;
void ATaskActor::TaskA()
{
Task_a = NULL;
//不可复制性
TSharedPtr<TaskA> Task_b;
Task_b = Task_a;
//在TArray中使用要注意,容器将类或指针作为了一个复制
TArray<TSharedPtr<TaskA>>;
//尽量不要在函数的声明周期临时声明一个共享指针,因为很消耗性能,内存开销更大。
}

共享指针是不可以复制的。再次出现对内容的引用则增加引用计数,当引用计数降到0的时候类会被清理。

TSharedPtr<TaskA> Task_a;
void ATaskActor::TaskAA()
{
//这样将普通的TaskA转换为智能指针
Task_a = MakeShareable(new TaskA());
//.是对智能指针里的内容作判断,直接用指针的话,那就是访问Task里面的内容。
if(Task_a.IsValid() \\ Task_a.Get())
{
Task_a.Get()->a;
//销毁
Task_a.Reset();
}
}

第二节 共享引用

共享指针不能置为 NULL,只要共享引用存在,共享指针就一定有效。

void ATaskActor::TaskSharedPtr()
{
Task_a = MakeShareable(new TaskA());
}
void ATaskActor::TaskSharedRef()
{
TSharedRef<TaskA> Task_b(new TaskA()); //获取数据的两种方式
Task_b->a;
(*Task_b).a;
}
void ATaskActor::TaskSharedRefAndPtr()
{
TSharedRef<TaskA> Task_b(new TaskA());
//将共享指针转换为了共享引用,之间是隐式转换。
Task_a = Task_b; //对于一个普通的指针,通过这种方式转换为共享指针
TaskA * NewTaskA = new TaskA();
Task_a = MakeShareable(new TaskA());
}

共享引用在声明的时候必须初始化,因为必须有效。

第六章 UE4基础代理

第一节 单播与原生C

DECLARE_DELEGATE(FDelegateTaskA);//无参无返回值代理
DECLARE_DELEGATE_OneParam(FDelegateTaskB, bool);//带一个参数的代理
DECLARE_DELEGATE_RetVal(bool,FDelegateTaskC);//带返回值的代理
DECLARE_DELEGATE_RetVal_OneParam(int32,FDelegateTaskD,FString&);//带一个参数一个返回值的代理
static void print_F(FString NewsString)
{
if(GEngine)
{
GEngine->AddOnScreenDebugMessage(-1,20,FColor::Red,NewsString);
}
}
//代理
class ClassA
{
public:
FDelegateTaskA DelegateTaskA;
FDelegateTaskB DelegateTaskB;
FDelegateTaskC DelegateTaskC;
FDelegateTaskD DelegateTaskD;
//初始化,调用执行代理
void Init()
{
bool IsRight = false;
int32 Index = 0;
FString NewStr = TEXT("Hello World");
//四种代理参数返回值等不一样。
DelegateTaskA.ExecuteIfBound();
DelegateTaskB.ExecuteIfBound(IsRight);
//判断是否已经绑定好了,不然直接调用容易崩。
if(DelegateTaskC.IsBound())
{
//这个代理返回类型是bool
IsRight = DelegateTaskC.Execute();
} if(DelegateTaskD.IsBound())
{
//这个代理返回类型是int32
Index = DelegateTaskD.Execute(NewStr);
}
}
};
class ClassB
{
public:
ClassB(ClassA *NewClass_a)
{
if(NewClass_a)
{
m_classA = NewClass_a;
//在B的构造中将B中的函数绑定到A中的各个委托上
m_classA->DelegateTaskA.BindRaw(this,&ClassB::ExecuteA);
m_classA->DelegateTaskB.BindRaw(this,&ClassB::ExecuteB);
m_classA->DelegateTaskC.BindRaw(this,&ClassB::ExecuteC);
m_classA->DelegateTaskD.BindRaw(this,&ClassB::ExecuteD);
}
} //析构解绑
~ClassB()
{
if(m_classA)
{
m_classA>DelegateTaskA.Unbind();
m_classA>DelegateTaskB.Unbind();
m_classA>DelegateTaskC.Unbind();
m_classA>DelegateTaskD.Unbind();
//此时测试一下
m_classA->Init();
//释放内存
delete m_classA;
//指针置空
m_classA = nullptr;
}
} void ExecuteA()
{
print_F(TEXT("A"));
} void ExecuteB(bool isRight)
{
if(isRight)
print_F(TEXT("B = true"));
else
print_F(TEXT("B = false"));
} bool ExecuteC()
{
print_F(TEXT("bool false"));
return false;
} int32 ExecuteD(FString &cde)
{
print_F(TEXT("D lalala") + cde);
return 0;
} private:
ClassA *m_classA;
};

我称Init()之为委托触发器。

第二节 单播与共享指针

如果类是一个共享指针。

class ClassB : public TSharedFromThis<ClassB>
{
public:
void init()
{
m_classA = MakeShareable(new ClassA());
m_classA->DelegateTaskA.BindRaw(this,&ClassB::ExecuteA);
}
//通过这种方式来获取
FORCEINLINE TSharedRef<ClassA> Getm_classA()
{
return m_classA.ToSharedRef();
}
private:
TSharedPtr<ClassA> m_classA;
}

第三节 单播与UObject

void AMainActor::BeginPlay()
{
Super::BeginPlay(); ClassB *NewClassB = new ClassB(); //这里进行绑定,将AMainActor::Print_c绑定到A的DelegateTaskA委托上。
NewClassB->Getm_classA()->DelegateTaskA.BindUObject(this,&AMainActor::Print_c);
//这里间接执行委托事件,实际在A的init函数中执行被绑定的委托
NewClassB->Getm_classA()->Init();
}
void AMainActor::Print_c()
{
print_F(TEXT("dddd"));
}
class ClassB: public TSharedFromThis<ClassB>
{
public:
classB()
{
m_classA = MakeShareable(new ClassA());
}
void Init()
{
m_classA = MakeShareable(new ClassA()); }
FORCEINLINE TSharedRef<ClassA> Getm_classA()
{
return m_classA.ToSharedRef();
}
private:
TSharedPtr<ClassA> m_classA;
}

第四节 单播与静态函数

static void PrintA()
{
print_F(TEXT("Print_A"));
}
void AMainActor::BeginPlay()
{
Super::BeginPlay(); ClassB *NewClassB = new ClassB();
//将静态函数PrintA绑定到A的DelegateTaskA
NewClassB->Getm_classA()->DelegateTaskA.BindStatic(Print_A);
//执行委托
NewClassB->Getm_classA()->Init();
}

第五节 单播与子函数名

NewClassB->Getm_classA()->DelegateTaskA.BindUFunction(this,TEXT("Print_c"));
//this表示绑定的对象,后面的是绑定的函数名
//被绑定的函数的声明需要添加UFUNCTION()宏,不然会找不到函数

第七章 复杂代理

第一节 多播代理绑定

和单播代理一样使用,不过多播代理没有返回值

DECLARE_MULTICAST_DELEGATE_OneParam(FDelegateTaskF,FString&);

FDelegateTaskF DelegateTaskF;

DelegateTaskF.Broadcast(TEXT("Hello"));

第二节 动态多播代理

动态多播代理只能绑定一个函数,在绑定下个函数的时候,会把上个函数替换掉。

UEC++学习(2)的更多相关文章

  1. Android学习——windows下搭建NDK_r9环境

    1. NDK(Native Development Kit) 1.1 NDK简介 Android NDK是一套允许开发人员使用本地代码(如C/C++)进行Android APP功能开发的工具,通过这个 ...

  2. linux内核数据结构学习总结

    目录 . 进程相关数据结构 ) struct task_struct ) struct cred ) struct pid_link ) struct pid ) struct signal_stru ...

  3. 用深度学习做命名实体识别(二):文本标注工具brat

    本篇文章,将带你一步步的安装文本标注工具brat. brat是一个文本标注工具,可以标注实体,事件.关系.属性等,只支持在linux下安装,其使用需要webserver,官方给出的教程使用的是Apac ...

  4. 从直播编程到直播教育:LiveEdu.tv开启多元化的在线学习直播时代

    2015年9月,一个叫Livecoding.tv的网站在互联网上引起了编程界的注意.缘于Pingwest品玩的一位编辑在上网时无意中发现了这个网站,并写了一篇文章<一个比直播睡觉更奇怪的网站:直 ...

  5. Angular2学习笔记(1)

    Angular2学习笔记(1) 1. 写在前面 之前基于Electron写过一个Markdown编辑器.就其功能而言,主要功能已经实现,一些小的不影响使用的功能由于时间关系还没有完成:但就代码而言,之 ...

  6. ABP入门系列(1)——学习Abp框架之实操演练

    作为.Net工地搬砖长工一名,一直致力于挖坑(Bug)填坑(Debug),但技术却不见长进.也曾热情于新技术的学习,憧憬过成为技术大拿.从前端到后端,从bootstrap到javascript,从py ...

  7. 消息队列——RabbitMQ学习笔记

    消息队列--RabbitMQ学习笔记 1. 写在前面 昨天简单学习了一个消息队列项目--RabbitMQ,今天趁热打铁,将学到的东西记录下来. 学习的资料主要是官网给出的6个基本的消息发送/接收模型, ...

  8. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  9. Unity3d学习 制作地形

    这周学习了如何在unity中制作地形,就是在一个Terrain的对象上盖几座小山,在山底种几棵树,那就讲一下如何完成上述内容. 1.在新键得项目的游戏的Hierarchy目录中新键一个Terrain对 ...

  10. 《Django By Example》第四章 中文 翻译 (个人学习,渣翻)

    书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:祝大家新年快乐,这次带来<D ...

随机推荐

  1. 调度器45—wake_affine

    基于 Linux-5.10 一.wake_affine 简介 1. 背景 在进程唤醒选核路径中, wake_affine 倾向于将被唤醒进程(wakee)尽可能安排在 waker所在 CPU 上, 这 ...

  2. 代码格式 linux

    indent -kr -i8 -ts8 -sob -l80 -ss -bs -psl test.c

  3. sqoop mysql2hive

    a./etc/profile添加export HADOOP_CLASSPATH=$HADOOP_CLASSPATH:$HIVE_HOME/lib/*b.将hive-site.xml 拷贝到 $SQOO ...

  4. JavaScript常用的8个数组去重实战源码

      JavaScript常用的8个数组去重实战源码 在我们学习和使用JavaScript的中,会经常使用到数组的去重,接下来的内容,来给大家分享一下,我们在开发过程中,常用到的数组去重方法,这些方法都 ...

  5. Oracle JDK 和 OpenJDK 有什么区别?

    OpenJDK是Sun在2006年末把Java开源而形成的项目,这里的"开源"是通常意义上的源码开放形式,即源码是可被复用的,例如IcedTea.UltraViolet都是从Ope ...

  6. VS2017创建Linux项目实现远程GDB调试

    vs2017新增linux for C++的模块,尝试安装了一下环境. 首先,安装VS2017,安装时注意选择以下模块: 安装完成后,需要配置Linux服务端的部分,我的配置过程如下: 第一步,安装V ...

  7. react 脚手架搭建项目 报错C:\Program Files\nodejs\node_cache\_logs\2022-12-28T14_38_28_286Z-debug-0.log

    报错内容: 解决方法: 第一步: 删除C:\Program Files\nodejs\node_cache\_logs 目录下所有文件 第二步:切换镜像 npm config set registry ...

  8. 常用的Linux命令与它们的功能

    概要 filename 文件名 dir 文件夹名 string 字符串 username 用户名 groupname 组名 regex 正则表达式 path 路径 partition 分区名 port ...

  9. 封装ESXi网卡驱动

    只能使用 Windows 7 系统 只能使用 Windows 7 系统 只能使用 Windows 7 系统 OK,留下的继续吧,

  10. 更改svn地址

    svn修改了服务器地址之后,本地要更新一下地址: 1. 在svn目录上右键,选TortoiseSVN->Relocate 2. 在To URL中填写新的地址,点击OK