第三章 断言

第一节 简单的断言

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

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. MyBatis_05(各种查询功能)

    MyBatis各种查询功能: 如果查询出的数据只有 "一条",可以通过: 1-实体类对象接收 2-List集合接收 3-Map集合接收,结果{password=123456, se ...

  2. SpringBoot启动流程与自动装配

    是什么 Spring Boot基于Spring框架之上的一个微服务架构开发框架大大简化了Spring的开发.因为Spring Boot提供了大量的自动配置.而且它是基于Java配置方式的开发(全注解) ...

  3. java位运算分析

    java位运算 java位运算在平常的编码过程中十分场景,通常框架都替我们封装好了,我对于细节方面反而一知半解,下面就重新梳理一下. 优秀的框架使得我们轻松,也使得我们距离真相越来越远. 位运算种类 ...

  4. PYTHON用户流失数据挖掘:建立逻辑回归、XGBOOST、随机森林、决策树、支持向量机、朴素贝叶斯和KMEANS聚类用户画像|附代码数据

    原文链接:http://tecdat.cn/?p=24346 最近我们被客户要求撰写关于用户流失数据挖掘的研究报告,包括一些图形和统计输出. 在今天产品高度同质化的品牌营销阶段,企业与企业之间的竞争集 ...

  5. ADT 更新遇到的一个BUG解决方案【转】

    蠻長一陣子沒有更新ADT,正好Android 5.0 Release有一段時間,就順勢更新: 當按下Next後進行更新ADT 23.0.4 途中卻發生如下圖的問題: An error occurred ...

  6. prometheus Alertmanager webhook

      一.自定义邮件告警 二.使用docker部署微信机器人告警 1.制作镜像 2.启动容器和指定webhook容器 一.自定义邮件告警 在alertmanager服务的配置文件中指定自定义告警文件 # ...

  7. 金蝶K3无法查看关联信息

    场景: 某个用户点击采购订单界面--关联信息,界面显示正在加载,但是无法显示所有关联单据. 步骤: 1. 在其他电脑登录存在同样问题. 2. 其他模块可以正常显示 3. 删除该用户t_UserProf ...

  8. DELL服务器基于centos7安装OMSA

    DELL服务器基于centos7安装OMSA 参考链接: https://www.cnblogs.com/sky-cheng/p/14951071.html https://www.dell.com/ ...

  9. 【Python】开始学习叭

    学习视频:https://www.bilibili.com/video/BV1wD4y1o7AS    

  10. ALV值存放图标

    SPAN { font-family: "新宋体"; font-size: 12pt; color: rgba(0, 0, 0, 1); background: rgba(255, ...