首页 > 编程语言 >UEC++学习(2)

UEC++学习(2)

时间:2023-03-03 12:35:54浏览次数:38  
标签:Task TEXT void ClassB C++ classA 学习 UE 指针

第三章 断言

第一节 简单的断言

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

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"));

第二节 动态多播代理

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

标签:Task,TEXT,void,ClassB,C++,classA,学习,UE,指针
From: https://www.cnblogs.com/Backfire/p/17175159.html

相关文章