Having trouble overriding base class's function from subclass

I have an actor component InteractionBase, some child of which goes on every object you can interact with in the world. InteractionBase has an empty Use function, declared thusly:

void Use(MCharacter* user);

My intent is to make a bunch of subclasses and override Use in a different way in each class, such that talking to a person, pressing a switch, and picking up loot can all be accomplished by calling that object’s InteractionSomeChild->Use(myActor); .

To test the functionality, I made a subclass of InteractionBase named InteractionSpeech and included the following declaration in the header:

virtual void Use(MCharacter* user);

To the best of my knowledge, this should let me add whatever functionality I wish, but it produces three linker errors that I’m having trouble deciphering:

Error InteractionSpeech.cpp.obj : error LNK2001: unresolved external symbol "private: virtual void __cdecl UInteractionSpeech::Use(class MCharacter *)" (?Use@UInteractionSpeech@@EEAAXPEAVMCharacter@@@Z)

Error MonsterSchool.generated.cpp.obj : error LNK2001: unresolved external symbol "private: virtual void __cdecl UInteractionSpeech::Use(class MCharacter *)" (?Use@UInteractionSpeech@@EEAAXPEAVMCharacter@@@Z)

Error C:\Users\ProjectFilePath\Binaries\Win64\UE4Editor-ProjectName-6828.dll : fatal error LNK1120: 1 unresolved externals

Is there an obvious klutz-up with how I declared my override?

Hello HInoue,

To be able to override a function, that function must be declared as virtual in the parent class, not the overriding child class. To make sure, that you are actually overriding a function, you can use the “override” keyword, like so:

// Parent Class
virtual void Use(MCharacter* User);

// Child Class
virtual void Use(MCharacter* User) override;

The “virtual” in the Child class is optional, since the function being virtual is inherited from the parent class. However it is considered good practice to re-declare the virtual, to make it clear, that this function is indeed virtual (even though that would be evident from the override-keyword anyway).

The “override”-keyword tells the compiler to throw a compile-time-error if the function does not actually override a parent function, and also clearly communicates the programmer’s intent, that he wants to override a parent function.

One last thing: It seems you get a Linker Error on UInteractionSpeech:Use. UInteractionSpeech is probably the parent class. You need to provide an implementation of the parent class’s method, even if it’s just empty or with an error-log-statement:

// Parent Class cpp
void ParentClass::Use(MCharacter* User) {
  // do nothing
}

// Child Class cpp
void ChildClass::Use(MCharacter* User) {
  Super::Use(User); // Depending on your class hierarchy you might want to call the parent class's Use-implementation as well
  // Specific Child logic here
}

Cheers,
Elewyth

2 Likes

Ooh, thank you for the detailed answer! To verify, is the following correct based on your explanation?

//Parent class .h:
virtual void Use(AMCharacter* User);
//Parent .cpp:
void Use(AMCharacter* User){
	GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Red, "I, a base class, have been used!");
}
//Child .h:
virtual void Use(AMCharacter* User) override;
//Child .cpp:
void UInteractionSpeech::Use(AMCharacter* User) {
	Super::Use(User);
	GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Red, "I, a speech class, have been used!");
}

I still get “unresolved external symbol” errors related to Use(), which makes me assume I messed up the syntax again:

Error InteractionBase.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl UInteractionBase::Use(class AMCharacter *)" (?Use@UInteractionBase@@UEAAXPEAVAMCharacter@@@Z)
Error InteractionSpeech.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl UInteractionBase::Use(class AMCharacter *)" (?Use@UInteractionBase@@UEAAXPEAVAMCharacter@@@Z)

You are missing the Class-name qualifier in the parent class .cpp. It should be

void UInteractionBase::Use(AMCharacter* User) {
  // Debug Message
}

Otherwise the compiler won’t know of which class this function is the implementation of. Or rather the function will be a global function, not part of any class. Everything else seems fine!

Oooh derp, this isn’t the first time I’ve made that mistake, either- everything works now, thank you very much for your patient and thorough explanations! :slight_smile:

since when does one need to add override ?wtf ?