Link Error 2005 Function already declared after changing it?

I’m trying to override a few C++ functions in blueprints by making them Blueprint Implementable Events. I learned that for ufunctions to be overridden in blueprint they can’t be virtual, which I find super strange. So I removed the keyword virtual from my ufunctions and now I only get link errors when I compile. I tried cleaning and rebuilding in visual studio; no result. I tried commenting them out, compile successful, uncommented them, and compile failed as before. I even tried renaming them and compilation still failed. I removed the BlueprintImplementablEvent field from the macro and it compiled correctly. So okay there’s something weird with that I guess. But I even tried BlueprintNativeEvent and I get teh same failed results. So I’m not sure what to do next.


1>PastryPanzerPanic.generated.cpp.obj : error LNK2005: "public: void __cdecl UBuff::OnCreation(void)" (?OnCreation@UBuff@@QEAAXXZ) already defined in Buff.cpp.obj
1>PastryPanzerPanic.generated.cpp.obj : error LNK2005: "public: void __cdecl UBuff::OnDestroy(void)" (?OnDestroy@UBuff@@QEAAXXZ) already defined in Buff.cpp.obj
1>PastryPanzerPanic.generated.cpp.obj : error LNK2005: "public: void __cdecl UBuff::OnTick(void)" (?OnTick@UBuff@@QEAAXXZ) already defined in Buff.cpp.obj
1>     Creating library S:\DysanianDawnWorkspace\PastryPanzerPanic\Intermediate\Build\Win64\UE4Editor\Development\UE4Editor-PastryPanzerPanic.lib and object S:\DysanianDawnWorkspace\PastryPanzerPanic\Intermediate\Build\Win64\UE4Editor\Development\UE4Editor-PastryPanzerPanic.exp
1>S:\DysanianDawnWorkspace\PastryPanzerPanic\Binaries\Win64\UE4Editor-PastryPanzerPanic.dll : fatal error LNK1169: one or more multiply defined symbols found
1>ERROR : UBT error : Failed to produce item: S:\DysanianDawnWorkspace\PastryPanzerPanic\Binaries\Win64\UE4Editor-PastryPanzerPanic.dll
1>  Total build time: 53.19 seconds
1>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V140\Microsoft.MakeFile.Targets(46,5): error MSB3073: The command ""D:\UnrealEngine\Epic Games\4.14\Engine\Build\BatchFiles\Rebuild.bat" PastryPanzerPanicEditor Win64 Development "S:\DysanianDawnWorkspace\PastryPanzerPanic\PastryPanzerPanic.uproject" -waitmutex" exited with code -1.
========== Rebuild All: 0 succeeded, 1 failed, 0 skipped ==========



// Buff.h

#pragma once

#include "../Tank.h"

#include "UObject/NoExportTypes.h"
#include "Buff.generated.h"

UCLASS(Blueprintable)
class PASTRYPANZERPANIC_API UBuff : public UObject
{
	GENERATED_BODY()

public:
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Buff", Meta=(ExposeOnSpawn=true))
	float lifeSpan;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Buff", Meta=(ExposeOnSpawn=true))
	float timeCreated;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Buff", Meta=(ExposeOnSpawn=true))
	float tickRate;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Buff", Meta=(ExposeOnSpawn=true))
	float timeActive;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Buff", Meta=(ExposeOnSpawn=true))
	bool bCanExpire;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Buff", Meta=(ExposeOnSpawn=true))
	class ATank *owningTank;

public:

	UBuff();

	UFUNCTION(BlueprintNativeEvent, Category="Buff")
	void OnCreation();

	UFUNCTION(BlueprintNativeEvent, Category="Buff")
	void OnTick();

	UFUNCTION(BlueprintNativeEvent, Category="Buff")
	void OnDestroy();


};




// Buff.cpp

#include "PastryPanzerPanic.h"
#include "Buff.h"

UBuff::UBuff(){

}

void UBuff::OnCreation(){

   // FTimerHandle buffTimer;
   //
   // if(tickRate > 0.f){
   //    GetWorldTimerManager().SetTimer(buffTimer, this, &UBuff::OnTick, tickRate, true);
   // }
   //
   // owningTank->activeBuffs.Add(this);
   //
   // GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor:Blue, "Buff Created.");
}

void UBuff::OnTick(){
   // GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor:Yellow, "Buff Ticking.");
   // timeActive += tickRate;
   // if(timeActive > lifeSpan){
   //    this->OnDestroy();
   // }
}

void UBuff::OnDestroy(){
   // GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor:Red, "Destroy Called.");
   // GetWorldTimerManager().ClearTimer(buffTimer);
   // owningTank->activeBuffs.Remove(this);
   // Destroy();
}


Move the #include “…\Tank.h” to you source file.


	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Buff", Meta=(ExposeOnSpawn=true))
	class ATank *owningTank;

Due to the keyword [class] it is a forwarded declaration. That means that the compiler knows the class exist, only not what it means.
If you include the header for ATank in a header, the compilers tries to declare ATank everytime it meet that file. It complains: I know that one already.
So don’t add the header, it works already due to the forwarded declaration.
When the compiler starts to work on the definitions of the declarations it must know the source of ATank.
Include it there at the source files.

Also, search at google for the error number, i.e. LNK2005, and you are redirected to Microsoft’s docs with possible solutions. Always the first result.

Your UFUNCTIONs are BlueprintNativeEvents therefore you need to define the functions with an _Implementation suffix like so.

.cpp


void UBuff::OnCreation_Implementation()
{
}

void UBuff::OnTick_Implementation()
{
}

void UBuff::OnDestroy_Implementation()
{
}

Doesn’t this class need the header for that class reference? This object will eventually be accessing properties from ATank.

EDIT:
Actually nevermind. You’re right. Moving that header include to the source file solved my circular dependency problem in another thread. Thanks.

That’s exactly what I needed. I honestly would not have guessed. I’ve spent hours trying to google this and search unreal’s doc.

The source needs the header. The header of UBuff is content with the forwarded declaration.

Since I am new to UE can’t say much about BlueprintNativeEvents but basically it is the same thing. Just move the include to the source and it is a better fit. You have declared ATank due to the keyword class.