x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

PURE_VIRTUAL interface

I read that true C++ pure virtual functions are not supported in Unreal but that we can use the PURE_VIRTUAL macro instead. The interface documentation says that pure virtual functions are supported so I tried creating an interface and using the PURE_VIRTUAL macro:

     // Add interface functions to this class. This is the class that will be inherited to implement this interface.
 public:
     virtual void Test() PURE_VIRTUAL(ITestInterface::Test, );

Then I created a new Actor and made it also inherit from ITestInterface:

 ATestActor : public AActor, public ITestInterface

I didn't provide and implementation for Test() anywhere but it still compiles without giving me any kind of error or warning that I can see.

Where did I go wrong?

Product Version: UE 4.18
Tags:
more ▼

asked Feb 24 '18 at 08:46 PM in C++ Programming

avatar image

jr557
48 10 14 21

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

2 answers: sort voted first

From what I can tell, PURE_VIRTUAL is a way to detect when an interface function has not been overridden. It creates a stub function that will generate a warning at runtime (not compile time). It's more of a TODO marker than a modifier of a function declaration. Try running it.

more ▼

answered Feb 24 '18 at 09:02 PM

avatar image

Jin_VE
4.4k 32 79 42

avatar image jr557 Feb 24 '18 at 09:12 PM

I tried running it and even calling it in BeginPlay() but I don't see anything in the Output Log. The "Pure virtual not implemented" would show up in the Output Log at runtime?

avatar image jr557 Feb 24 '18 at 09:28 PM

Whoops, calling it was actually a crash once I made a blueprint from the actor and dragged it into the level. But I'm still checking for the warning message so I can see what the use of the macro is.

avatar image Jin_VE Feb 24 '18 at 10:10 PM

This is it:

 #if CHECK_PUREVIRTUALS
 #define PURE_VIRTUAL(func,extra) =0;
 #else
 #define PURE_VIRTUAL(func,extra) { LowLevelFatalError(TEXT("Pure virtual not implemented (%s)"), TEXT(#func)); extra }
 #endif

If CHECK_PUREVIRTUALS is 0 then you should get the message. If it's defined then you'd get the compile-time error. Note that with it enabled, you can only compile. If you run it, this code gets executed:

 #if CHECK_PUREVIRTUALS
     FMessageDialog::Open( EAppMsgType::Ok, *NSLOCTEXT("Engine", "Error_PureVirtualsEnabled", "The game cannot run with CHECK_PUREVIRTUALS enabled.  Please disable CHECK_PUREVIRTUALS and rebuild the executable.").ToString() );
     FPlatformMisc::RequestExit(false);
 #endif

It's disabled by default so if you don't see the log message then something else isn't right. And it shouldn't crash. That may be a clue as to what is wrong. You could show the log of the crash and you could show the full interface and usage.

avatar image Jin_VE Feb 25 '18 at 12:02 AM

MinimalAPI doesn't look like it's going to work well with interfaces. And I'm using interface-specific GENERATED_XXX macros. Try this way:

 UINTERFACE(BlueprintType)
 class MY_API UMyInterface : public UInterface
 {
     GENERATED_UINTERFACE_BODY()
 };
 
 
 class MY_API IMyInterface
 {
     GENERATED_IINTERFACE_BODY()
 ...


avatar image jr557 Feb 25 '18 at 12:27 AM

I can change to BlueprintType and build but when I try to use the interface-specific macros instead of GENERATED_BODY() I get linker error somehow involving the UMyInterface constructor:

 1>MyInterface.gen.cpp.obj : error LNK2019: unresolved external symbol "public: __cdecl UMyInterface::UMyInterface(class FObjectInitializer const &)" (??0UMyInterface@@QEAA@AEBVFObjectInitializer@@@Z) referenced in function "void __cdecl InternalConstructor<class UMyInterface>(class FObjectInitializer const &)" (??$InternalConstructor@VUMyInterface@@@@YAXAEBVFObjectInitializer@@@Z)
 1>D:\Unreal Projects\TestInterface\Binaries\Win64\UE4Editor-TestInterface.dll : fatal error LNK1120: 1 unresolved externals

I think that I will provide a default implementation for now because I'm not sure a simple log message is worth a lot of time and trouble.

avatar image Jin_VE Feb 25 '18 at 12:41 AM

Oh. Right. In the cpp file you need to implement the constructor. Like this:

 UMyInterface::UMyInterface(const class FObjectInitializer& ObjectInitializer)
     : Super(ObjectInitializer)
 {
 }

avatar image jr557 Feb 25 '18 at 12:53 AM

Builds now with BlueprintType and interface-specific macros but still not seeing anything. Oh well.

avatar image Jin_VE Feb 25 '18 at 01:07 AM

Weird. It should do more than log a message cuz it's calling LowLevelFatalError.

It's just a utility macro -- or, supposed to be hehe. You can write the message to the log yourself in the default implementation.

avatar image jr557 Feb 25 '18 at 01:29 AM

Ahh, I think I see how it works now. That crash that I mentioned before was the LowLevelFatalError. You have to call Test() and then it will crash the editor/game (if you launched it outside of Visual Studio from the Epic launcher) and the call stack will show:

LowLevelFatalError [File:d:\unreal projects\testinterface\source\testinterface\MyInterface.h] [Line: 28] Pure virtual not implemented (IMyInterface::Test)

But if you launch from Visual Studio (or attach to process I assume) then it will throw and exception and break.

Unless I'm debugging something I usually launch the project from the Epic launcher. So I will definitely notice if I forget to provide an implementation! But I think I would prefer to find out at compile time. :)

avatar image Jin_VE Feb 25 '18 at 02:51 AM

Aha! Mystery solved.

Unfortunately, the way UE4 uses its own pre-pre-processing and all their macro stuff, it's going to be hard to get that info at compile time. You can try using the C++ pure virtual format (`virtual void foo() = 0;`). That's what CHECK_PUREVIRTUALS does. But it would just be something that lets you check for anything that wasn't implemented. You'd have to change it back to be able to build anything for real. It'd be faster to just check it at runtime.

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

Try to declare your pure virtual function like this:

 virtual void Test() PURE_VIRTUAL(ITestInterface::Test, ;);

Please note that extra ; if you are returning void. If you are returning other value type, just provide default value or any value really. You need to pay attention to implement that function in derived class otherwise you will get message like this: "Pure virtual not implemented". Typical usage for this macro is if you want to make pure abstract base class.

more ▼

answered Jun 21 '19 at 08:26 PM

avatar image

Vertex Soup
288 4 22 16

(comments are locked)
10|2000 characters needed characters left
Viewable by all users
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question