Download

Split function definitions to multiple .cpp files

Hey. In normal .cpp projects you can easily get one header, include it in multiple .cpp files and actually define every function from header file in different .cpp file. It’s quite helpful to keep your code clear and avoid some big single cpp files. Making Unreal Engine projects you can’t do the same thing - apparently any function declared in UCLASS structure must be defined in associated .cpp file. I’m looking for a way to avoid it - if possible, not by #including some pure file (which is very dirty way to obtain this result), but by actually compiling and linking .cpp files not created in Unreal Engine editor.

Does someone have a solution to this problem?

I personally think splitting the code to multiple source files is not a good idea, but that is your own decision.

As you said, I don’t think this is possible to do with UClass implementations. You could however try to implement your logic in a “normal” C++ class, which you then use in your UClass. Kinda like the proxy pattern.

This isn’t true, UE4 doesn’t impose any such limitations. Maybe post some code and the errors you’re getting?

I thought that it happens only for core functions (like BeginPlay, Tick etc), but actually it happens also for all functions called from those core funtions. Example:

(MyActorA.h file)



#include "GameFramework/Actor.h"
#include "MyActorA.generated.h"

UCLASS()
class MYPROJECT_API AMyActorA : public AActor
{
	GENERATED_BODY()
	
public:	

	AMyActorA();
	void BeginPlay();
	void Tick(float DeltaTime);

	void functionA();


};

(MyActorA.cpp)


#include "MyProject.h"
#include "MyClass.h"
#include "MyActorA.h"

AMyActorA::AMyActorA() {
	MyClass *x = new MyClass;
}




void AMyActorA::Tick(float DeltaTime) {
	functionA();
}

void AMyActorA::BeginPlay() {

}

Now - when I make [FONT=Courier New]void AMyActorA::functionA() definition inside AMyActorA.cpp file or similar AMyActorB.cpp file, everything works. I could of course create auxiliary files with empty actors, but I rather would not choose this option, since it wouldn’t really help in organising files. Suppose I created some empty, non-inheriting class in UnrealEngine, like MyClass.h. If I create additional file, like Source.cpp and put definition of MyClass constructor here, I can call it from AMyActorA class (like showed in example above). But, when I put [FONT=Courier New]void AMyActorA::functionA() in Source.cpp instead of MyActorA.cpp file, like this:



#include "MyClass.h"
#include "MyActorA.h"

MyClass::MyClass() {

}

void AMyActorA::functionA() {

}


I get the following error:


Severity	Code	Description	File	Project	Line	Suppression State
Error	LNK2019	unresolved external symbol "public: void __cdecl AMyActorA::functionA(void)" (?functionA@AMyActorA@@QEAAXXZ) referenced in function "public: virtual void __cdecl AMyActorA::Tick(float)" (?Tick@AMyActorA@@UEAAXM@Z)	C:\UE4 Projects\MyProject\Intermediate\ProjectFiles\MyActorA.cpp.obj	MyProject	1	


(also, I tried to make some friend functions operating on class - no success, i still get linking errror)

I don’t quite follow exactly what you’re saying, but I don’t see an issue with the code. Are you certain Source.cpp is being compiled? Sometimes UBT fails to detect new source files until you force a rebuild by deleting the intermediate folder, touching the .build.cs file, or similar.

You can test by putting


#error foo

at the top of your Source.cpp and checking to see if the compiler prints the error.

UE4’s macros just cause some extra code to be added by UHT, but they don’t generally change existing code at the C++ level. So things like this should behave identically whether it’s a UCLASS or a regular class. I know I’ve spread UCLASS functions over multiple source files without any issue.

Ok, I know now what was the problem. After creating new file - Source.cpp in this case - VS editor put it into Intermediate folder, instead of Source folder. When I put it into Source/MyProject folder, it compiled whole code. I also ‘touched’ Build.cs file, but I’m not sure if it was necessary. Anyway, thanks for help - without you I wouldn’t be able to realize the mistake this fast!