Announcement

Collapse
No announcement yet.

Battery Collector Tutorial: Question about include statement (Unreal Framework and Inheritence)

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Battery Collector Tutorial: Question about include statement (Unreal Framework and Inheritence)

    Hello Unreal-ites (I'm sorry this is long, but I like to provide detail, not filler),

    [My C++ Experience Level]
    Now that I have enough Blueprint experience under my belt and I am content with what I have created, I began to delve into Unreal C++. I have some standard C++ experience and understand what and how to use pointers, dereferences, address-of, forward declarations, includes and why we need them, const, among other things.


    [My Request]
    I'd like to know if my assertion of something is true or not (below)

    [Reference Content]
    In the Battery Collector tutorial series (https://www.youtube.com/watch?v=EIpt..._dGiM4&index=3), we begin to define and implement a BatteryCollector class. This series was made many Unreal versions ago, and so, many things have changed. One thing that changed was at 12:05, the author types "RootCompoent = PickupMesh" in Pickup.cpp in the class default constructor.

    [Things Have Changed]
    Back then, this statement did not make Visual Studio question the assignment. However, somewhere between then and now, the assignment operator contains a squiggly under it stating: "A value of type "UStaticMeshComponent*" cannot be assigned to an entity of type "USceneComponent* " ".

    A commenter suggested; some years after this video, UStaticMeshComponent became a distance child of USceneComponent, and the squiggly can be safely ignored. I'm not happy with that because there is no answer as to why. My guess is because this is not a syntax error and will allow to start compilation, and, after compilation, the linker links, though the hierarchy, a UStaticMeshComponent type to a USceneComponent Type. IS THIS A CORRECT UNDERSTANDING?

    [My Assertion]
    If we use the include statement #include "Components/StaticMeshComponent.h" in Pickup.cpp, as another commenter suggested, this makes the squiggly go away. Here is my why assertion, am I correct?

    1. The variable in Pickup.h called PickupMesh is a type of UStaticMeshComponent AND is declared using a FORWARD declaration, hence why #include "Components/StaticMeshComponent.h" statement was not necessary in Pickup.h.

    2. StaticMeshComponent.h states the class inherits from UMeshComponent.

    3. MeshComponent.h states the class inherits from UPrimitiveComponent.

    4. PrimitiveComponent.h states the class inherits from USceneComponent

    Since the linker is able to successfully link a UStaticMesh type up to USceneComponent type, (PickupMesh type up to a RootComponent type), the include statement is NOT necessary because the linker establishes the link [upward]. IS THIS A CORRECT UNDERSTANDING?

    If we place the include statement in the Pickup.CPP file, somehow, Visual Studio is able to use some pre-compile/pre-linker determination, that, yes, a UStaticMeshComponent IS a USceneComponent (which makes the squiggly go away). Is that fair?

    I do understand that two reasons to use forward declarations is to speed up compile times and help break dependencies created by include statements. If this is true, then I don't understand why use forward declarations if you need to use an #include statement in the CPP file anyway. What am I possibly missing?

    Thank you,

    -Erol
    Last edited by erol_demirci; 12-24-2019, 06:16 PM.

    #2
    So. Header files can be included in many other classes. That's the purpose of them, to define the prototype for said class/struct, etc. This information is valuable to the compiler to determine what said class has, ie properties/functions. CPP Files on the other hand are just "tack on", say to speak. You can quite easily have 5 headers and one massive CPP file (they are not tied (in normal c++ anyway)). Now if you break this down, Header files being included in other header files, etc can lead to issues where say Class B includes Class A and Class A includesClass B. This is a circular dependency. To mitigate this, you forward declare to reduce the amount of includes inside a header.

    You may also notice or will come to notice, UE4 (and other developers) often create a "Types" header file, which has things like structs/enums, etc. This allows for including in the header without worrying about possible circular dependencies. The reason you need to include the header of the class you want to use, is because the compiler doesn't know what the class contains. When you forward declare, you are just telling the compiler what type it is, not what it contains. As soon as you access or deference, the compiler needs to know what that class actually contains. So in the CPP file, (or anywhere where you deference/access a specific class/struct), you must have a include. The CPP file makes sense for this, as A: It doesn't get included into other headers (avoiding circular dependencies) and B: This is where you normally do the bulk of your work with said include.

    So in a nutshell:
    Forward Declare doesn't tell the compiler what the class/struct/enum contains, just that it IS a class/struct or enum.
    Including in header files, can lead to circular dependencies, and increased compile times.

    When you include a header, the compiler (even intellisense compiler) can work out all the parent classes from it, and resolve squiggles (tho in UE4 squiggles are quite normal, and should not be relied upon).
    Game Programmer - Working for a Indie Studio.

    Visit my blog: TheGamesDev

    InterKaos Games

    PC Specs:
    ​​​​​​​

    Comment


      #3
      Originally posted by erol_demirci View Post
      [Reference Content]
      In the Battery Collector tutorial series (https://www.youtube.com/watch?v=EIpt..._dGiM4&index=3), we begin to define and implement a BatteryCollector class. This series was made many Unreal versions ago, and so, many things have changed. One thing that changed was at 12:05, the author types "RootCompoent = PickupMesh" in Pickup.cpp in the class default constructor.

      [Things Have Changed]
      Back then, this statement did not make Visual Studio question the assignment. However, somewhere between then and now, the assignment operator contains a squiggly under it stating: "A value of type "UStaticMeshComponent*" cannot be assigned to an entity of type "USceneComponent* " ".

      A commenter suggested; some years after this video, UStaticMeshComponent became a distance child of USceneComponent, and the squiggly can be safely ignored. I'm not happy with that because there is no answer as to why. My guess is because this is not a syntax error and will allow to start compilation, and, after compilation, the linker links, though the hierarchy, a UStaticMeshComponent type to a USceneComponent Type. IS THIS A CORRECT UNDERSTANDING?
      I just followed the tutorial and it doesn't give me any squiggly lines.

      Note that Pickup.cpp includes BatteryCollector.h which Includes EngineMinimal.h which includes "Components/StaticMeshComponent.h" so this is how intellesense knows StaticMeshComponent IsA SceneComponent.

      Comment


        #4
        Originally posted by GarnerP57 View Post

        I just followed the tutorial and it doesn't give me any squiggly lines.

        Note that Pickup.cpp includes BatteryCollector.h which Includes EngineMinimal.h which includes "Components/StaticMeshComponent.h" so this is how intellesense knows StaticMeshComponent IsA SceneComponent.
        Most classes include CoreMinimal.h, not EngineMinimal.h.
        Game Programmer - Working for a Indie Studio.

        Visit my blog: TheGamesDev

        InterKaos Games

        PC Specs:
        ​​​​​​​

        Comment


          #5
          Hi TheKaosSpectrum , I sincerely appreciate the additional information you've taken the time to provide. So what do you feel is happening under the hood during compilation (and/or linking) that makes the implicit casting operation for us, which is why we can safely ignore the squiggly under the assignment operator as one commenter suggested?

          For me, I do not like to see squigglies. I trust Visual Studio to tell me something is wrong... I will never know what I can safely ignore, and not. The way I see it, if there is a squiggly, and it compiles, and things work as expected, there must some implicit work happening during compilation, no?

          You did state that we can expect some squigglies when developing with UE4 framework. May I ask why you state this? Is that a matter of experience or does it state that somewhere in the documentation that I may have missed? Is it just a lot of implicit casting that we can safely ignore?

          Hi GarnerP57 ,What version of Unreal Engine are you using? TheKaosSpectrum is correct: Pickup.h includes CoreMinimal.h, which, does not include anything I can see that links back to USceneComponent, or further down, UStaticMeshComponent. Could you recheck and post back what you meant?


          Thanks for you guys taking the time to reply. I hope both of you had a Merry Christmas, or, if you celebrate another holiday, I hope you had a Merry other holiday!

          Comment


            #6
            I am using 4.23. Am I looking at a different tutorial? The Pickup.cpp includes BatteryCollector.h right?

            Comment


              #7
              Hey GarnerP57 ; You stated in your first post: "
              Note that Pickup.cpp includes BatteryCollector.h which Includes EngineMinimal.h which includes "Components/StaticMeshComponent.h" so this is how intellesense knows StaticMeshComponent IsA SceneComponent.
              "

              But, BatteryCollector.h does not include EngineMinimal.h as TheKaosSpectrum mentioned, and, I also checked, it includes CoreMinimal.h, not EngineMinimal.h. I checked CoreMinimal.h (just incase you made a typo and meant CoreMinmal.h), and that does not include Components/StaticMeshComponent.h.

              My question is: Where did you see that Components/StaticMeshComponent.h is included that helps intellisense understand that a UStaticMeshComponent is a USceneComponent type?

              I am using 4.22 currently. Did 4.23 start including EngineMinmal.h in a new project header file?

              -Erol

              Comment


                #8
                Timecode 3:32 of that tutorial EngineMinimal.h or am I imagining things?

                It is not something engine specific it is what I am seeing in the tutorial. I normally never include EngineMinimal.h as I never need all that stuff at once.
                Last edited by GarnerP57; 12-26-2019, 06:29 PM.

                Comment


                  #9
                  Originally posted by GarnerP57 View Post
                  Timecode 3:32 of that tutorial EngineMinimal.h or am I imagining things?

                  It is not something engine specific it is what I am seeing in the tutorial. I normally never include EngineMinimal.h as I never need all that stuff at once.
                  Ah, I see where the disconnect is; you were implicitly referring to the video in your original post. I didn't realize that and I"m sure the other poster didn't realize that either based on the response.

                  In 4.22, EngineMinimal.h is not included by default within the project header. Instead CoreMinimal.h is included. So I'm back to square one. However, I am content.
                  No sense in clogging up the forum when people have real issues that need to be taken care of.

                  Thank you guys for the input!
                  -Erol

                  Comment

                  Working...
                  X