第三章 断言

第一节 简单的断言

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

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. kubernetes弃用dockershim

    转载自:https://www.51cto.com/article/710688.html 前段时间,kubernetes推出了1.24版本,曾经轰动一时的docker弃用也正式实装了,这意味着1.2 ...

  2. 微信退费报错:SSLHandshakeException No appropriate protocol (protocol is disabled or cipher suites are inappropr)

    微信退费报错:No appropriate protocol (protocol is disabled or cipher suites are inappropr) javax.net.ssl.S ...

  3. 关于import-route static 和default-route-advertise区别知识总结

    关于import-route static 和default-route-advertise区别知识总结 一.相关解释 import-route static  命令不能引入外部路由的默认路由,OSP ...

  4. 高级测试工程师&资深测试工程师应实现的价值

    一 技能 自动化: 接口自动化 web ui 自动化(selenium) 移动端自动化 二 项目支撑----项目集,不是单个项目(大小项目) 1.具体功能web 2.小程序 3.移动端 三 项目职责 ...

  5. uniapp 中获取微信小程序的原生导航栏高度

    const custom = wx.getMenuButtonBoundingClientRect() // console.log(custom) that.yuansheng= custom.he ...

  6. ES深分页

    一.背景 1.ES默认分页from+size 2.在大数据量和深度分页的时候,效率非常低 二.效率低原因 1.例如要查第501页的10条数据,from为5000,size为10 2.ES会查询并排序5 ...

  7. linux 网络操作 route iptables ufw

    linux 网络操作 route iptables ufw sudo ufw status sudo ufw allow ssh sudo ufw allow http sudo ufw deny h ...

  8. 常见的hash数据结构

    遍历 hash表是一种比较简单和直观的数据结构,在查找时也有很好的性能.但是hash表不能提供有序遍历,这个是其特性决定,所以不足为奇.但是,更为实际的一个问题是如果遍历整个hash表中的所有元素? ...

  9. Supervisor安装及配置

    Supervisor安装 # 安装 easy_install supervisor # 生成默认配置文件 echo_supervisord_conf > /etc/supervisord.con ...

  10. sql server 常用高级查询sql

    数据源:表:coursename kecheng fenshu张三 语文 81张三 数学 75李四 语文 76李四 数学 90王五 语文 81王五 数学 100王五 英语 90赵六 语文 88赵六 数 ...