UE4 面试题整理

1、new与malloc的区别

new:

new首先会去调用operator new函数,申请足够的内存(大多数底层用malloc实现),然后调用类型的构造函数来初始化变量,最后返回自定义类型的指针,delete先调用析构函数,然后调用operator delete函数释放内存(大多数底层用free实现)

__cdecl 是C Declaration的缩写(declaration,声明)

malloc:

malloc是库函数,只能申请内存,没有初始化功能

所以new与malloc最大的区别就是new能进行构造函数初始化


2、strcpy、sprintf、memcpy的区别

strcpy:用于将一个字符串复制到另一个字符串中

sprintf:sprintf函数用于将格式化的字符串输出到一个字符数组中

char str[10];
int num = 4;
sprintf(str, "number is %d", num);
printf("%s\n", str); // 输出 number is 4

memcpy:用于将一个内存地址的数据复制到另一个内存地址中


3、子弹穿墙问题

子弹向前打出一个身位长的射线,若打到了墙面则开始计算子弹与墙的距离,在通过距离除以速度算出时间,时间过后则进行碰撞


4、UE4如何切关卡后保留数据

存放在GameInstancesubsystem中,不要存在gameinstance内,这样会导致项目臃肿


5、UE4客户端能否使用AIController

不可以,在DS(dedicated server)模型下,AIController只存在于服务端,其主要是通过在服务端对Pawn进行操控,
然后再同步到客户端。


6、Blueprintable与NotBlueprintable

将C++类加入蓝图类

如果为NotBlueprintable则不能被蓝图化


7、BlueprintImplementEvent与BlueprintNativeEvent的区别

如果实现了蓝图,那么C++的Implement接口则不调用

如果没写蓝图接口则调用C++接口

而BlueprintImplementEvent只是做接口给蓝图,不拓展C++接口。


8、C++类中默认有什么函数

1、构造函数

2、拷贝构造函数

3、析构函数

4、重载赋值运算符函数


9、UE4生命周期

从先到后:UGameEngine->GameInstance->World和WorldContext->PersistentLevel->GameMode->GameState->PlayerController->PlayerState->HUD->Character

在UGameEngine(继承自UEngine)

首先UEngine的子类有UGameEngine和UEditorEngine,UEngine中的GEngine有访问UE的全局资源,是一个很重要的指针。

void UGameEngine::Init(IEngineLoop* InEngineLoop)
{
	DECLARE_SCOPE_CYCLE_COUNTER(TEXT("UGameEngine Init"), STAT_GameEngineStartup, STATGROUP_LoadTime);
	

	// Call base.
	UEngine::Init(InEngineLoop);

#if USE_NETWORK_PROFILER
	FString NetworkProfilerTag;
	if( FParse::Value(FCommandLine::Get(), TEXT("NETWORKPROFILER="), NetworkProfilerTag ) )
	{
		GNetworkProfiler.EnableTracking(true);
	}
#endif

	// Load and apply user game settings
	GetGameUserSettings()->LoadSettings();
	GetGameUserSettings()->ApplyNonResolutionSettings();

	// Create game instance.  For GameEngine, this should be the only GameInstance that ever gets created.
	{
		FSoftClassPath GameInstanceClassName = GetDefault<UGameMapsSettings>()->GameInstanceClass;
		UClass* GameInstanceClass = (GameInstanceClassName.IsValid() ? LoadObject<UClass>(NULL, *GameInstanceClassName.ToString()) : UGameInstance::StaticClass());
		
		if (GameInstanceClass == nullptr)
		{
			UE_LOG(LogEngine, Error, TEXT("Unable to load GameInstance Class '%s'. Falling back to generic UGameInstance."), *GameInstanceClassName.ToString());
			GameInstanceClass = UGameInstance::StaticClass();
		}

		GameInstance = NewObject<UGameInstance>(this, GameInstanceClass);

		GameInstance->InitializeStandalone();
	}
 
//  	// Creates the initial world context. For GameEngine, this should be the only WorldContext that ever gets created.
//  	FWorldContext& InitialWorldContext = CreateNewWorldContext(EWorldType::Game);

	IMovieSceneCaptureInterface* MovieSceneCaptureImpl = nullptr;
#if WITH_EDITOR
	if (!IsRunningDedicatedServer() && !IsRunningCommandlet())
	{
		MovieSceneCaptureImpl = IMovieSceneCaptureModule::Get().InitializeFromCommandLine();
		if (MovieSceneCaptureImpl)
		{
			StartupMovieCaptureHandle = MovieSceneCaptureImpl->GetHandle();
		}
	}
#endif

	// Initialize the viewport client.
	UGameViewportClient* ViewportClient = NULL;
	if(GIsClient)
	{
		ViewportClient = NewObject<UGameViewportClient>(this, GameViewportClientClass);
		ViewportClient->Init(*GameInstance->GetWorldContext(), GameInstance);
		GameViewport = ViewportClient;
		GameInstance->GetWorldContext()->GameViewport = ViewportClient;
	}

	LastTimeLogsFlushed = FPlatformTime::Seconds();

	// Attach the viewport client to a new viewport.
	if(ViewportClient)
	{
		// This must be created before any gameplay code adds widgets
		bool bWindowAlreadyExists = GameViewportWindow.IsValid();
		if (!bWindowAlreadyExists)
		{
			UE_LOG(LogEngine, Log, TEXT("GameWindow did not exist.  Was created"));
			GameViewportWindow = CreateGameWindow();
		}

		CreateGameViewport( ViewportClient );

		if( !bWindowAlreadyExists )
		{
			SwitchGameWindowToUseGameViewport();
		}

		FString Error;
		if(ViewportClient->SetupInitialLocalPlayer(Error) == NULL)
		{
			UE_LOG(LogEngine, Fatal,TEXT("%s"),*Error);
		}

		UGameViewportClient::OnViewportCreated().Broadcast();
	}

	UE_LOG(LogInit, Display, TEXT("Game Engine Initialized.") );

	// for IsInitialized()
	bIsInitialized = true;
}

 

 

UGameInstance继承自FExec,Exec就是UE4的命令行

void UGameInstance::InitializeStandalone(const FName InPackageName, UPackage* InWorldPackage)
{
	// Creates the world context. This should be the only WorldContext that ever gets created for this GameInstance.
	WorldContext = &GetEngine()->CreateNewWorldContext(EWorldType::Game);
	WorldContext->OwningGameInstance = this;

	// In standalone create a dummy world from the beginning to avoid issues of not having a world until LoadMap gets us our real world
	UWorld* DummyWorld = UWorld::CreateWorld(EWorldType::Game, false, InPackageName, InWorldPackage);
	DummyWorld->SetGameInstance(this);
	WorldContext->SetCurrentWorld(DummyWorld);

	Init();
}

然后在GameInstance的初始化单例中生成对应的World和一个WorldContext

同时GameInstance内对GameMode进行绑定生成,但这个动作不是在初始化函数中进行的,而是在

在PreviewScene中在构造函数中调用了SetGameMode

World中在FSeamlessTravelHandler类中进行Tick设置

去调用的

 

然后在GameMode里面对所有的GameState,PlayerController,PlayerState,HUD和Default Panw,Spectator进行绑定

void UWorld::InitializeNewWorld(const InitializationValues IVS)
{
	if (!IVS.bTransactional)
	{
		ClearFlags(RF_Transactional);
	}

	PersistentLevel = NewObject<ULevel>(this, TEXT("PersistentLevel"));
	PersistentLevel->Initialize(FURL(nullptr));
	PersistentLevel->Model = NewObject<UModel>(PersistentLevel);
	PersistentLevel->Model->Initialize(nullptr, 1);
	PersistentLevel->OwningWorld = this;

	// Create the WorldInfo actor.
	FActorSpawnParameters SpawnInfo; 

	// Mark objects are transactional for undo/ redo.
	if (IVS.bTransactional)
	{
		SpawnInfo.ObjectFlags |= RF_Transactional;
		PersistentLevel->SetFlags( RF_Transactional );
		PersistentLevel->Model->SetFlags( RF_Transactional );
	}
	else
	{
		SpawnInfo.ObjectFlags &= ~RF_Transactional;
		PersistentLevel->ClearFlags( RF_Transactional );
		PersistentLevel->Model->ClearFlags( RF_Transactional );
	}

#if WITH_EDITORONLY_DATA
	// Need to associate current level so SpawnActor doesn't complain.
	CurrentLevel = PersistentLevel;
#endif

	SpawnInfo.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
	// Set constant name for WorldSettings to make a network replication work between new worlds on host and client
	SpawnInfo.Name = GEngine->WorldSettingsClass->GetFName();
	AWorldSettings* WorldSettings = SpawnActor<AWorldSettings>(GEngine->WorldSettingsClass, SpawnInfo );

	// Allow the world creator to override the default game mode in case they do not plan to load a level.
	if (IVS.DefaultGameMode)
	{
		WorldSettings->DefaultGameMode = IVS.DefaultGameMode;
	}

	PersistentLevel->SetWorldSettings(WorldSettings);
	check(GetWorldSettings());
#if WITH_EDITOR
	WorldSettings->SetIsTemporarilyHiddenInEditor(true);
#endif

#if INCLUDE_CHAOS
	/*FChaosSolversModule* ChaosModule = FModuleManager::Get().GetModulePtr<FChaosSolversModule>("ChaosSolvers");
	check(ChaosModule);
	FActorSpawnParameters ChaosSpawnInfo;
	ChaosSpawnInfo.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
	ChaosSpawnInfo.Name = TEXT("DefaultChaosActor");
	SpawnActor(ChaosModule->GetSolverActorClass(), nullptr, nullptr, ChaosSpawnInfo);
	check(PhysicsScene_Chaos);*/
#endif

	// Initialize the world
	InitWorld(IVS);

	// Update components.
	UpdateWorldComponents( true, false );
}

在World内对PersistentLevel进行初始化,再对PersistentLevel中的WorldSetting进行设置,这里的WorldSetting设置只是Level与WorldSetting进行绑定,WorldSetting初始化还是在GameInstance里面

然后是GameMode,它负责什么呢?

1、Class登记:记录GameMode中各种类的信息

2、Spawn:创建Pawn和PlayerController等

3、游戏进度:游戏暂停重启的逻辑

4、过场动画逻辑

5、多人游戏的步调同步

GameState?

AGameState

AGameState用于保存游戏数据,如任务进度,打到了哪一个关卡什么的


10、sizeof与strlen的区别

sizeof包括最后的'\0',所以为4,strlen不包括最后的'\0',所以为3

sizeof是字节个数,不止用在字符串上,而strlen只能用在字符串上,输出字符串个数 


11、重写与重载的区别

1、重写是子类覆盖父类名字相同的方法,对其进行重新实现

2、重载有两种情况,在同一个类中,同一个方法名拥有不同的参数个数,或者同一个方法名拥有参数个数相同的不同类型参数


12、构造函数和析构函数都能加Virtual吗?

虚函数

虚函数跟着对象走 

函数名后面加override没有任何功能性作用,只是开发规范要求写上。

override作用或C++语言哲学:将大多数错误暴露在编译阶段

普通函数属于编译期状态,虚函数属于运行期状态。

编译器是看代码人就知道答案,运行期是看代码也不能清楚答案。

基类析构函数都要加virtual

如果析构函数不加virtual,普通成员函数跟类走,那么delete p;就会去调用p的类型的析构函数即Animal的析构函数

加了情况就一不一样: 

构造函数是用来创建一个新的对象,而虚函数的运行是建立在对象的基础上,在构造函数执行时,对象尚未形成(普通函数属于编译期状态,虚函数属于运行期状态),所以不能将构造函数定义为虚函数,通常析构函数才会用virtual修饰(虚函数实际存放在对象的头部的虚函数表中的)

所以构造函数不能加virtual,析构函数子类必须加virtual


13、UCLASS、GENERATED_BODY以及为何要加 文件名.generated.h

1、GENERATED_BODY

通过当前文件ID以及行号来建立一个唯一的键值名称

2、UCLASS

与GENERATED_BODY是一样的 

3、xxx.generated.h

在Intermediate(中间生成文件)中生成,这个生成是在项目文件编译成功后它会自动生成xxx.generated.h以及xxx.gen.cpp

结合之前的UCLASS和GENERATED_BODY

.generated.h里面生成了这些文件,是通过UCLASS和GENERATED_BODY来生成的

例如GENRATED_BODY在18行,CURRENT_FILE_ID为first_Source_first_SCharacter_h

注意这个DECLARE_CLASS

下一张图引用:UE4 UObject系列之UClass(二) - 知乎

这里完成了对反射类型做了操作

同时还在里面对new进行了重载

最后new出来的对象在UClass内对类进行注册,构建了基础的反射系统

我遇到的反射的问题:

1、当你生成了Intermediate中的反射文件.gen和.generated文件后,GENERATED_BODY()这种宏不能挪位置因为已经标明了对应的行号了,必须重新Generate Visual Studio project files才能继续正常运行


14、UE4内存管理

内存管理机制的三种形式

1、垃圾回收

2、智能指针

3、C++内存管理(malloc realloc calloc new)

一、对非UObject类型进行TSharedPtr管理,不能用于UObject对象,不然等TSharedPtr释放后,UObject自带的GC机制再去进行垃圾回收就会引起两次free的异常

二、以及对UObject类型进行GC机制的回收

三、UE4中的C++内存管理通常通过FMalloc以及GMalloc进行管理

class CORE_API FMalloc  : 
 public FUseSystemMallocForNew,
 public FExec
{
public:
 virtual void* Malloc( SIZE_T Count, uint32 Alignment=DEFAULT_ALIGNMENT ) = 0;
 virtual void* TryMalloc( SIZE_T Count, uint32 Alignment=DEFAULT_ALIGNMENT );
 virtual void* Realloc( void* Original, SIZE_T Count, uint32 Alignment=DEFAULT_ALIGNMENT ) = 0;
 virtual void* TryRealloc(void* Original, SIZE_T Count, uint32 Alignment=DEFAULT_ALIGNMENT);
 virtual void Free( void* Original ) = 0

 为了在调用new/delete能够调用ue4的自定义函数,ue4内部替换了operator new。这一替换是通过IMPLEMENT_MODULE宏引入的

FMallocBinned使用freelist机制管理空闲内存。每个空闲块的信息记录在FFreeMem结构中,显式存储。

FMallocBinned使用内存池机制,内部包含POOL_COUNT(42)个内存池和2个扩展的页内存池;其中每个内存池的信息由FPoolInfo结构体维护,记录了当前FreeMem内存块指针等,而特定大小的所有内存池由FPoolTable维护;内存池内包含了内存块的双向链表。


15、情况一: UObject对象中有UObject成员

UObject成员加入UPROPERTY,由于UObject对象有肯定是被实例化的且UObject本身就存在垃圾回收,自己是实例化出来的,引用计数肯定大于等于1,在UObject对象中又有对UObject成员的引用,则不会被自动销毁

总结:UObject本身就在垃圾回收机制内,只需加入UPROPERTY就可以将UObject成员加入垃圾回收机制且有UObject对象对UObject成员的引用

      情况二: 非UObject对象中有UObject成员

方法一:由于非UObject对象并不具备垃圾回收机制,所以就必须手动将UObject对象加入引用,首先先继承自FGCObject,再重写AddReferenceObjects函数,使得UObject成员加入回收机制

class NotObject : public FGCObject {
public:
    UObject* CollectorObject;
    
    void AddReferencedObjects(FReferenceCollector& ReferenceCollector) override {
        ReferenceCollector.AddReferencedObject(CollectorObject);
    }
}

当NotObject被销毁时,CollectorObject的引用也会自动清除,引用计数为0即被销毁

方法二:

NotObject* notObject;
notObject->AddToRoot();

将对象AddToRoot,使得变量不会被自动GC,在析构函数调用notObject->RemoveFromRoot(),防止内存泄漏

总结:非UObject对象继承自FGCObject,然后重写AddReferencedObjects函数,将对象成员加入垃圾回收机制

          非UObject对象,将对象AddToRoot(),这样非UObject对象的UObject成员都加入垃圾回收机制,非UObject成员通过new/delete进行管理


16、什么时候会调用EndPlay事件

1、手动销毁Actor时

2、切换关卡时


17、UE4中Class与Struct有什么区别

1、对于C++而言,class变量函数默认为private,而struct变量函数默认为public

2、对于UE4而言,class可以将函数暴露给UE4编辑器,例如BlueprintCallable、BlueprintNativeEvent、BlueprintImplement等,而struct不能

3、对于UE4而言,class能够继承、struct不能继承,若class继承自uobject类,则class自带垃圾回收功能,就不能用智能指针,否则会造成double free,struct虽然是USTRUCT的宏修饰,但是它并不继承自uobject,且不能继承,所以它没有自带垃圾回收,可以与智能指针搭配调用


18、UE4中线程的种类

1、渲染线程

2、游戏线程

3、GPU线程


19、UE4的多线程有哪些?具体怎么使用?

1、FRunnable

2、AsyncTask

3、TaskGraph

一、FRunnable

首先它不是UObject类,记得手动delete掉,它内在函数有六个,其中五个是常用的:

1、Init(),返回值是一个bool,Run根据这个bool确定是否执行

2、Run(),若Init返回值会true且存在一个FRunnableThread线程,两者成立执行内部方法

3、Stop()

通常对Run中的while条件变为false例如:

递增了就不为1,Run的内部逻辑就停止运行

4、Exit()

唤起主线程

5、析构函数

通常对FRunnableThread指针等内容给清空

但想要真的能够让Run跑起来,还需要一个FRunnableThread

AysncTask:

UE并发-线程池和AsyncTask - 知乎 (zhihu.com)

【UE4 C++ 基础知识】<14> 多线程——AsyncTask - 砥才人 - 博客园 (cnblogs.com)

最简单的使用方法

但这个内部实现用的还是TaskGraph


// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Async/AsyncWork.h"
#include "HAL/ThreadManager.h"

class FAsyncTK : public FNonAbandonableTask
{
    friend class FAutoDeleteAsyncTask<FAsyncTK>;

    int32 ExampleData;
    float WorkingTime;

public:
    FAsyncTK(int32 InExampleData, float TheWorkingTime = 1)
        : ExampleData(InExampleData), WorkingTime(TheWorkingTime) { }

    ~FAsyncTK() {
        Log(__FUNCTION__);
    }

    // 执行任务(必须实现)
    void DoWork() {
        // do the work...
        //FPlatformProcess::Sleep(WorkingTime);
        Log(__FUNCTION__);
    }

    // 用时统计对应的ID(必须实现)
    FORCEINLINE TStatId GetStatId() const
    {
        RETURN_QUICK_DECLARE_CYCLE_STAT(ExampleAsyncTask, STATGROUP_ThreadPoolAsyncTasks);
    }

    void Log(const char* Action)
    {
        uint32 CurrentThreadId = FPlatformTLS::GetCurrentThreadId();
        FString CurrentThreadName = FThreadManager::Get().GetThreadName(CurrentThreadId);
        UE_LOG(LogTemp, Display, TEXT("%s[%d] - %s, ExampleData=%d"), *CurrentThreadName, CurrentThreadId,
            ANSI_TO_TCHAR(Action), ExampleData);
    }
};

TaskGraph:

虚幻4之TaskGraph:十分钟上手TaskGraph - 知乎 (zhihu.com)

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"

class TKGraph
{
    FString FileContent;
public:
    TKGraph(
        FString InFileContent) :
        FileContent(MoveTemp(InFileContent))
    {}

    FORCEINLINE TStatId GetStatId() const {
        RETURN_QUICK_DECLARE_CYCLE_STAT(FTaskCompletion_LoadFileToString,
            STATGROUP_TaskGraphTasks);
    }

    static ENamedThreads::Type GetDesiredThread() { return ENamedThreads::GameThread; }
    static ESubsequentsMode::Type GetSubsequentsMode()
    {
        return ESubsequentsMode::TrackSubsequents;
    }

    void DoTask(ENamedThreads::Type CurrentThread,
        const FGraphEventRef& MyCompletionGraphEvent) {
        check(IsInGameThread());
        GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Green, TEXT("TASKGRAPH"));
    }
};
TGraphTask<TKGraph>::CreateTask().
		ConstructAndDispatchWhenReady("pink");

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/476037.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

HCIP—BGP路由聚合

在大型网络中&#xff0c;路由条目通常多达成千上万条&#xff0c;甚至几十万条&#xff0c;这给路由设备带来的挑战是&#xff1a;如何存储并有效管理如此众多的路由信息&#xff1f; BGP是一种无类路由协议&#xff0c;支持CIDR、VLSM和路由聚合。路由聚合技术的使用…

【微服务】Nacos配置管理

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;微服务 ⛺️稳中求进&#xff0c;晒太阳 Nacos除了可以做注册中心&#xff0c;同样可以做配置管理来使用。 1.统一配置管理 当微服务部署的实例越来越多&#xff0c;达到数十、数百时&am…

JVM垃圾回收之内存分配,死亡对象判断方法

Java 堆是垃圾收集器管理的主要区域&#xff0c;因此也被称作 GC 堆。 堆划分为新生代 老生代 永久代。 下图所示的 Eden 区、两个 Survivor 区 S0 和 S1 都属于新生代&#xff0c;中间一层属于老年代&#xff0c;最下面一层属于永久代。 内存分配原则 对象优先在Eden区域分…

jupyter notebook设置代码提示方法

在命令行运行以下代码&#xff1a; pip install jupyter_contrib_nbextensionsjupyter contrib nbextension install --userpip install jupyter_nbextensions_configuratorjupyter nbextensions_configurator enable --user &#xff08;有时安装第一行后会自动执行第二行&a…

Redis监控工具

Redis 是一种 NoSQL 数据库系统&#xff0c;以其速度、性能和灵活的数据结构而闻名。Redis 在许多领域都表现出色&#xff0c;包括缓存、会话管理、游戏、排行榜、实时分析、地理空间、叫车、聊天/消息、媒体流和发布/订阅应用程序。Redis 数据集完全存储在内存中&#xff0c;这…

八部门联合打击涉税违法犯罪活动,企业合规经营刻不容缓

近期&#xff0c;国家税务总局、公安部、最高人民法院、最高人民检察院、中国人民银行、海关总署、市场监管总局、国家外汇管理局在北京召开全国八部门联合打击涉税违法犯罪工作推进会议。 会议强调八部门将持续深化完善联合打击工作机制&#xff0c;依法严厉打击涉税违法犯罪行…

借教室与差分

原题 题目描述 在大学期间&#xff0c;经常需要租借教室。 大到院系举办活动&#xff0c;小到学习小组自习讨论&#xff0c;都需要向学校申请借教室。 教室的大小功能不同&#xff0c;借教室人的身份不同&#xff0c;借教室的手续也不一样。  面对海量租借教室的信息&…

9.测试教程-性能测试概述

文章目录 1.常见的性能问题2.为什么要进行性能测试3.性能测试实施的流程4.概念和术语介绍5.性能测试模型6.性能测试方法介绍7.性能测试实施与管理8.性能测试前期准备9.测试工具引入10.性能测试方案11.性能测试设计与开发12.性能测试设计与管理13.性能测试设计与调优14.性能测试…

Python+Appium实现自动化测试的使用步骤

一、环境准备 1.脚本语言&#xff1a;Python3.x IDE&#xff1a;安装Pycharm 2.安装Java JDK 、Android SDK 3.adb环境&#xff0c;path添加E:\Software\Android_SDK\platform-tools 4.安装Appium for windows&#xff0c;官网地址Redirecting 点击下载按钮会到GitHub的下载…

广西开放大学电大搜题微信公众号,助你快速解题,轻松学习!

近年来&#xff0c;广西开放大学电大搜题微信公众号备受关注。作为一名电大学者&#xff0c;我有幸亲身体验了该公众号的功能&#xff0c;并深感其对广大学生学习的帮助之大。 广西开放大学作为一所具有百年历史的学府&#xff0c;一直致力于为学生提供优质的教育资源。而电大…

Uibot6.0 (RPA财务机器人师资培训第2天 )采购付款——网银付款机器人案例实战

训练网站&#xff1a;泓江科技 (lessonplan.cn)https://laiye.lessonplan.cn/list/ec0f5080-e1de-11ee-a1d8-3f479df4d981https://laiye.lessonplan.cn/list/ec0f5080-e1de-11ee-a1d8-3f479df4d981(本博客中会有部分课程ppt截屏,如有侵权请及请及时与小北我取得联系~&#xff0…

【Python + Django】启动简单的文本页面

前言&#xff1a; 为了应付&#xff08;bushi&#xff09;毕业论文&#xff0c;总要自己亲手搞一个像模像样的项目出来吧 ~ ~ 希望自己能在新的连载中学到项目搭建的知识&#xff0c;这也算是为自己的测试经历增添光彩吧&#xff01;&#xff01;&#xff01; 希望、希望大家…

09 事务和连接池

文章目录 properties文件连接池service层实现类dao层实现类dao层实现类 连接池类: 创建线程池静态常量&#xff0c;用于放连接。 创建Properties静态常量&#xff0c;用于解析properties文件 静态代码块中&#xff0c;解析properties文件&#xff0c;将解析结果用于创建连接池 …

Linux快速入门,上手开发 02.VMware的安装部署

倘若穷途末路&#xff0c;那便势如破竹 —— 24.3.21 一、VMware的作用 在Windows或IOS系统下&#xff0c;给本地电脑安装VMware虚拟机&#xff0c;用来在虚拟机上安装Linux系统&#xff0c;避免重复资源的浪费&#xff0c;可以在虚拟机上搭建Linux系统进行学习 二、VMware的安…

PCL点云处理之中值计算(二百三十三)

PCL点云处理之中值计算(二百三十三) 一、算法介绍二、算法实现1.代码2.结果一、算法介绍 读取的点云是无序散乱的,点云坐标包括xyz三个维度,以常用的z高程维度为例,计算其高程中值,获取对应的点。 主要涉及到根据高程对点云进行排序的操作,下面是具体的代码和结果。 …

视频号下载助手失效了?如何解决下载视频问题!

在刷短视频的时候难免会遇到部分的视频号视频下载不下来&#xff0c;那我们该如何解决视频号下载问题呢&#xff1f; 视频号下载助手解决方案 视频号下载助手失效分为两种情况! 1、可以解析&#xff0c;但不能下载 根据使用视频号下载助手常见的问题&#xff0c;我们发现会有…

C++进阶--哈希

哈希概念 哈希&#xff08;Hash&#xff09;是一种常见的密码学技术和数据结构&#xff0c;它将任意长度的输入通过散列算法转换成固定长度的输出&#xff0c;这个输出被称为散列值或哈希值。哈希函数是一种单向函数&#xff0c;即从哈希值无法反推出原始输入值。 哈希函数具有…

AJAX 前端开发利器:实现网页动态更新的核心技术

AJAX AJAX是开发者的梦想&#xff0c;因为你可以&#xff1a; 在不重新加载页面的情况下更新网页在页面加载后请求来自服务器的数据在页面加载后接收来自服务器的数据在后台向服务器发送数据 HTML页面 <!DOCTYPE html> <html> <body><div id"dem…

你要的个性化生信分析服务今天正式开启啦!定制你的专属解决方案!全程1v1答疑!

之前在 干货满满 | 给生信小白的入门小建议 | 掏心掏肺版 中有提到&#xff0c;如果小伙伴们真的想学好生信&#xff0c;那编程能力是必须要有的&#xff01;但是可能有些小伙伴们并没有那么多的时间从头开始学习编程&#xff0c;又或是希望有人指导或者协助完成生信分析工作&a…

Qt学习--界面知识点大杂烩

在开发过程中&#xff0c;通常需要打开或者保存上位机数据到本地&#xff0c;这时候就需要用到