第三章 断言
第一节 简单的断言
断言让程序的进程中断,方便程序员发现在哪里发生了问题。
1 2 3 4
| AGameBase * GameBase = nullptr; check(false); check(GameBase);
|
断言的目的是为了告诉方法或函数有问题。
第二节 额外信息断言
1 2
| verifyf(false, TEXT("sssss %s"),*this->GetName()); checkf(false, TEXT("sssss %s"),*this->GetName());
|
这两个用起来都一样,触发断言后会在退出提示信息里提示信息内容。
第三节 阻塞流程断言
只要经过这个函数就断。
检测这个函数是否被执行了两次,第一次没问题不会断,第二次会断。
检测有没有递归,要是出现递归就直接崩。
第四节 断点式断言
1
| ensure(0 && "check(GameBase && GameBase can not be NULL)");
|
程序运行到此相当于遇到断点了,点击继续可以继续运行程序。
1
| ensureMsgf(0, TEXT("%s"), *this->GetName());
|
同上,并可通过此获得更多额外信息。
第四章 智能指针基础
第一节 共享指针
继承自UObject类的对象们会被GC标记,在程序关闭时释放资源。但是对于原生的类,需要使用智能指针来进行内存管理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class TaskA{ public : int32 a; float b; } TSharedPtr<AActor> A; TSharedPtr<TaskA> Task_a; void ATaskActor::TaskA() { Task_a = NULL; TSharedPtr<TaskA> Task_b; Task_b = Task_a; TArray<TSharedPtr<TaskA>>; }
|
共享指针是不可以复制的。再次出现对内容的引用则增加引用计数,当引用计数降到0的时候类会被清理。
1 2 3 4 5 6 7 8 9 10 11 12 13
| TSharedPtr<TaskA> Task_a; void ATaskActor::TaskAA() { Task_a = MakeShareable(new TaskA()); if(Task_a.IsValid() \\ Task_a.Get()) { Task_a.Get()->a; Task_a.Reset(); } }
|
第二节 共享引用
共享指针不能置为 NULL,只要共享引用存在,共享指针就一定有效。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
| 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()) { IsRight = DelegateTaskC.Execute(); } if(DelegateTaskD.IsBound()) { Index = DelegateTaskD.Execute(NewStr); } } }; class ClassB { public: ClassB(ClassA *NewClass_a) { if(NewClass_a) { m_classA = NewClass_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()之为委托触发器。
第二节 单播与共享指针
如果类是一个共享指针。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| void AMainActor::BeginPlay() { Super::BeginPlay(); ClassB *NewClassB = new ClassB(); NewClassB->Getm_classA()->DelegateTaskA.BindUObject(this,&AMainActor::Print_c); NewClassB->Getm_classA()->Init(); } void AMainActor::Print_c() { print_F(TEXT("dddd")); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| 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; }
|
第四节 单播与静态函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| static void PrintA() { print_F(TEXT("Print_A")); } void AMainActor::BeginPlay() { Super::BeginPlay(); ClassB *NewClassB = new ClassB(); NewClassB->Getm_classA()->DelegateTaskA.BindStatic(Print_A); NewClassB->Getm_classA()->Init(); }
|
第五节 单播与子函数名
1 2 3
| NewClassB->Getm_classA()->DelegateTaskA.BindUFunction(this,TEXT("Print_c"));
|
第七章 复杂代理
第一节 多播代理绑定
和单播代理一样使用,不过多播代理没有返回值
1 2 3 4 5
| DECLARE_MULTICAST_DELEGATE_OneParam(FDelegateTaskF,FString&);
FDelegateTaskF DelegateTaskF;
DelegateTaskF.Broadcast(TEXT("Hello"));
|
第二节 动态多播代理
动态多播代理只能绑定一个函数,在绑定下个函数的时候,会把上个函数替换掉。