Inheritance hierarchy causing crashes

I thought I’d hit upon a clever way to encapsulate my game’s functionality in self-contained components, but the fact it causes Unreal to crash whenever I use it leads me to suspect otherwise.

In short, every piece of functionality (attacks, taking damage, storing items) is contained in a subclass of IMorpheme, a virtual class that contains a stub for every single verb in the game:



UCLASS( ClassGroup=(Custom), abstract )
class CODEPROJECT_API UIMorpheme : public UActorComponent
{
	GENERATED_BODY()

public:	
	UIMorpheme();
	virtual void Attack() { check(0 && "Override this"); };
	virtual void GotHit() { check(0 && "Override this"); };
        //A bunch more virtual function decs follow
}

Any object that can use Morphemes gets a component named Lexicon, which has a function for each major action that reads identical to this:


void ULexicon::Attack(){
	for (UIMorpheme* myMorph : morphemeList){	
		if (myMorph!= nullptr){
			myMorph->Attack();
		}
	}
}

Thus, whenever I want an actor to take a game-specific action, like take damage, attack something, or display its contents, I just need to call AActor* someActor->Lexicon->SomeFunction();, and the Lexicon will iterate through its list of every morpheme component on that actor, and for any morpheme that contains functionality for one of lexicon’s verbs, it activates that functionality.

In theory this seems like a great idea, as it allows me to essentially play building-block character functionality and maintain a very clean codebase by strongly coupling to Lexicon, but not requiring any component to retain references to any other component in the entire game.

I was under the impression that since I had empty stubs in the base IMorpheme class, running myMorph->Attack() on a morpheme that didn’t have an Attack function would result in nothing, but every time that happens the game comes to a crashing halt. This is fixable by adding empty stubs for each verb into each morpheme subclass, but that turns a system designed to make adding new functionality trivial into one that becomes nightmarish to curate every time I add a new function.

This leads to two fairly closely-related concerns:

  1. Is there a super-simple way to prevent crashes when trying to execute a function that the parent class has, but the subclass does not?
  2. Is this even a good idea at all? It sounded great in my head, but I want to be sure that I’m not spending hours and hours trying to debug and improve a fundamentally unstable way of doing things.

You’ve made it “crash”. Just follow your code.
“check(expr)” is a macro (see AssertionMacros.h). If expr is false, FDebug::AssertFailed is called. When a debugger is present, this will trigger a breakpoint. Otherwise it prompts “for remote debugging”. The corresponding static function PromptForRemoteDebugging in FPlatformMisc is not always declared and defined via preprocessor #if !UE_BUILD_SHIPPING. Find out whether this is applies to your build or not.
In order to fix this double check your condition 0 && x (false && x) which is always false. You may want to replace the check(expr) with a simple warning or log message.

This is based on UE4.2.0. Hope it helps.

That explains a lot- thank you! :slight_smile: