Ошибка forward declaration of class

I have an error that goes like this

    In file included from Level.hpp:12,
                 from main.cpp:4:
Corridor.hpp: In method `void Game::Corridor::update()':
Corridor.hpp:41: invalid use of undefined type `class Game::Level'
Corridor.hpp:13: forward declaration of `class Game::Level'
Corridor.hpp:42: invalid use of undefined type `class Game::Level'
Corridor.hpp:13: forward declaration of `class Game::Level'
Corridor.hpp:43: invalid use of undefined type `class Game::Level'
Corridor.hpp:13: forward declaration of `class Game::Level'
Corridor.hpp:44: invalid use of undefined type `class Game::Level'
Corridor.hpp:13: forward declaration of `class Game::Level'

Corridor and Level are …

  // Corridor.hpp

#ifndef GAME_CORRIDOR_HPP
#define GAME_CORRIDOR_HPP

#include <Moot/Math.hpp>

//#include <Level.hpp>
#include <GameWindow.hpp>

namespace Game
{
    class Level; // <-- LINE 13

    class Corridor
    {
        static const unsigned int defaultLevelDepth = 800;

        Moot::Math::Vector3D wp1, wp2, wp3, wp4;
        Moot::Math::Vector2D sp1, sp2, sp3, sp4;

        Level * p_level;

    public:

        Corridor(Moot::Math::Vector3D setFirstPoint, Moot::Math::Vector3D setSecondPoint) 
        {
            wp1 = setFirstPoint;
            wp2 = setSecondPoint;

            wp3 = setFirstPoint;
            wp3.z += defaultLevelDepth;

            wp4 = setSecondPoint;
            wp4.z += defaultLevelDepth;
        }


        void update() {

            sp1 = p_level->getLevelCamera().convert3DVectorWithScreenAlgorithm(wp1); // <- LINE 41 etc.
            sp2 = p_level->getLevelCamera().convert3DVectorWithScreenAlgorithm(wp2);
            sp3 = p_level->getLevelCamera().convert3DVectorWithScreenAlgorithm(wp3);
            sp4 = p_level->getLevelCamera().convert3DVectorWithScreenAlgorithm(wp4);


            //p_level->getLevelCamera();
        }

        void draw()//const
        {
            Moot::Color tempColor;

            windowInstance().graphics().drawQuad( sp1.x, sp1.y, tempColor,
                                                                                sp2.x,sp2.y, tempColor,
                                                                                sp3.x, sp3.y, tempColor,
                                                                                sp4.x,sp4.y, tempColor, 1);
        }


        void setLevel(Level* setLevel) {
            p_level = setLevel;
        }

    };
}

#endif

and

// Level.hpp

#ifndef GAME_LEVEL_HPP
#define GAME_LEVEL_HPP

#include <Moot/Forward.hpp>
#include <Moot/Window.hpp>
#include <Moot/Math.hpp>

#include <GameWindow.hpp>
#include <Camera.hpp>
#include <Corridor.hpp>
#include <Player.hpp>

#include <vector>


namespace Game
{
    class Level
    {

        typedef Corridor* p_corridor;
        typedef std::vector<p_corridor> CorridorList;
        typedef CorridorList::reverse_iterator ReverseCorridorItter;

        CorridorList m_map;
        Camera       m_camera;
        Player         m_player;


    public:

        Level()
        {
            m_player.setLevel(this);

            // Lots of vertices being defined into m_map.


            // Loop through and set camera
            ReverseCorridorItter rit;

            for(rit = m_map.rbegin(); rit != m_map.rend(); rit++)
                (*rit)->setLevel(this);


        }


        ~Level()
        {
            ReverseCorridorItter rit;

            for(rit = m_map.rbegin(); rit != m_map.rend(); rit++) 
                delete (*rit);

            m_map.clear();
        }


        void update() 
        {
            // Temp delete when input and player are implimented.
            if(pad[0].buttons & PAD_UP)
                m_camera.updateTargetOffsets(0, -2);

            if(pad[0].buttons & PAD_DOWN)
                m_camera.updateTargetOffsets(0, 2);

            if(pad[0].buttons & PAD_LEFT)
                m_camera.updateTargetOffsets(-2, 0);

            if(pad[0].buttons & PAD_RIGHT)
                m_camera.updateTargetOffsets(2, 0);

            m_player.update();


            ReverseCorridorItter rit;

            for (rit = m_map.rbegin(); rit != m_map.rend(); rit++)
                (*rit)->update();
        }


        void draw() // const // EH!!! wtf ReverseIter isn't a member
        {
            m_player.draw();


            ReverseCorridorItter rit;

            for (rit = m_map.rbegin(); rit != m_map.rend(); rit++)
                (*rit)->draw();

        }


        Camera& getLevelCamera() {
            return m_camera;
        }

    };
}

#endif

The pointer is being set as far as I can tell, but when I try to access a function from Level, BOOM!

Thanks.

PS: The compiler is gcc 2.95.2 if that makes a difference.

EDIT

Updated with complete code.

I have the following errors trying to use a TFT library function inside my library. My library uses the pointer to an instance of the TFT library in the constructor, as well described there:

Basic C++ programming, how to pass constructor argument into class?

The errors are:

error: invalid use of incomplete type 'class TFT'
_TFTscreen->background(0, 0, 0);

error: forward declaration of 'class TFT'
class TFT;

MESmenu.h:

#ifndef _MESMENU_H_
#define _MESMENU_H_

#include <SPI.h>
#include <SD.h>

class TFT;

class MESmenu{
public:
  MESmenu(TFT* pTFT) : _TFTscreen(pTFT) {};
  void start();
  void execute();
private:
  TFT* _TFTscreen;
};

#endif

MESmenu.cpp:

#include "Arduino.h"
#include "MESmenu.h"

void MESmenu::start(){
  _TFTscreen->background(0, 0, 0);
  _TFTscreen->text("starting menu...", 0, 0);
  //...
}

void MESmenu::execute(){
   //some code...  
}

The Arduino sketch is:

#include <SPI.h>
#include <SD.h>
#include <TFT.h>  // Arduino LCD library
#include <MESmenu.h>  // my library

// --------- TFT LCD ---------
// pin definition for the due
#define sd_cs  7
#define lcd_cs 10
#define dc     9
#define rst    8
TFT TFTscreen = TFT(lcd_cs, dc, rst);

// MES menu class
MESmenu *mainMenu = new MESmenu(&TFTscreen);

void setup() {
  // initialize TFT
  TFTscreen.begin();
  TFTscreen.background(0, 0, 0);
  // set the stroke color to white
  TFTscreen.stroke(255,255,255);
  TFTscreen.fill(255,255,255);
  TFTscreen.setTextSize(2);
  TFTscreen.text("TEST", 0, 0);

  // Start menu
  mainMenu->start();
}

void loop () {
  mainMenu->execute();      
}

The problem is related to the function:

_TFTscreen->background(0, 0, 0);

inside the MESmenu::start() in the .cpp file.

UPDATE:

As suggested by frarugi87 I’ve updated the question with the details of .h and .cpp files.
Those file are in the ArduinolibrariesMESmenu folder.

I try to change

class TFT;

with

#include <TFT.h>

and removed the #include from the main arduino sketch.

This leads to the following errors:

librariesMESmenuMESmenu.cpp.o: In function `Adafruit_GFX::image(PImage&, unsigned int, unsigned int)':
D:Softwarearduino-1.6.7librariesTFTsrc/utility/Adafruit_GFX.h:231: multiple definition of `Adafruit_GFX::image(PImage&, unsigned int, unsigned int)'
sketchtest_MESmenu_lib.ino.cpp.o:D:Softwarearduino-1.6.7librariesTFTsrc/utility/Adafruit_GFX.h:231: first defined here

librariesMESmenuMESmenu.cpp.o: In function `Adafruit_GFX::image(PImage&, unsigned int, unsigned int)':
D:Softwarearduino-1.6.7librariesTFTsrc/utility/Adafruit_GFX.h:231: multiple definition of `PImage::read16(SDLib::File)'
sketchtest_MESmenu_lib.ino.cpp.o:D:Softwarearduino-1.6.7librariesTFTsrc/utility/PImage.h:17: first defined here

librariesMESmenuMESmenu.cpp.o: In function `Adafruit_GFX::image(PImage&, unsigned int, unsigned int)':
D:Softwarearduino-1.6.7librariesTFTsrc/utility/Adafruit_GFX.h:231: multiple definition of `PImage::read32(SDLib::File)'
sketchtest_MESmenu_lib.ino.cpp.o:D:Softwarearduino-1.6.7librariesTFTsrc/utility/PImage.h:17: first defined here

librariesMESmenuMESmenu.cpp.o: In function `Adafruit_GFX::image(PImage&, unsigned int, unsigned int)':
D:Softwarearduino-1.6.7librariesTFTsrc/utility/Adafruit_GFX.h:231: multiple definition of `PImage::loadImage(char const*)'
sketchtest_MESmenu_lib.ino.cpp.o:D:Softwarearduino-1.6.7librariesTFTsrc/utility/PImage.h:17: first defined here

Forward declarations and Invalid uses of incomplete type Init

Alright, I don’t know why I should have unresolved dependency issues here, but here goes:

And to think, I was just trying to build a simple class for initializing SDL facilities.

All the tutorials I’ve been doing (lazyfoo) seem really cluttered and have all this initialization data up-front in nested if-statements in main.cpp, and I thought it looked sloppy and that I’d do one better by encapsulating all that crap into a simple class for my own uses.

Having done thirty of them, I thought I knew enough to start screwing around on my own. Maybe not?

Init.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_ttf.h>
#include <stdio.h>

class Init()
{
    public:
    bool initAll();
    bool initVid();
    void initVSync();
    void initLinTextFilt();
    bool initWindow(SDL_Window* winArg);
    bool initRenderer(SDL_Window* winArg, SDL_Renderer* rendArg)
    bool initTTF();
    bool initIMG();
};

(Ignore the «magic consts» in the window creation function, they’re just placeholders for variables I have yet to declare.)
Init.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include "Init.h"

//calls all other Initialization functions
bool Init::initAll(SDL_Window* window, SDL_Renderer* renderer)
{
    initVid();
    initVSync();
    initLinTextFilt();
    initWindow(window);
    initRenderer(window, renderer);
    initTTF();
    initIMG();
}
//Initialize SDL Video subsystem
bool Init::initVid()
{
    bool success = true;
    if(!SDL_Init(SDL_INIT_VIDEO) < 0)
    {
        printf("SDL_INIT_VIDEO failed. SDL Error: %sn", SDL_GetError());
        success = false;
    }
    return success;
}
//Initialize vertical synchronization
void Init::initVSync()
{
    if(!SDL_SetHint(SDL_HINT_RENDER_VSYNC, "1"))
    {
        printf("Warning: VSync not enabled.");
    }
}
//initialize linear texture filtering
void Init::initLinTextFilt()
{
    if(!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1"))
    {
        printf("Warning: Linear texture filtering not enabled.");
    }
}
//initialize window
bool Init::initWindow(SDL_Window* winArg)
{
    bool success = true;
    winArg = SDL_CreateWindow("Default Title", SDL_WINDOWPOS_UNDEFINED,
                              SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_SHOWN);
    if(winArg == NULL)
    {
        printf("Window could not be created! SDL error: %sn", SDL_GetError())
        success = false;
    }
    return success;
}
//initialize renderer
bool Init::initRenderer(SDL_Window* winArg, SDL_Renderer* rendArg)
{
    bool success = true;
    rendArg = SDL_CreateRenderer(winArg, -1, SDL_RENDERER_ACCELERATED);
    if(gRenderer == NULL)
    {
        printf("Renderer could not be created! SDL error: %sn", SDL_GetError())
        success = false;
    }
    else
    {
        SDL_SetRenderDrawColor(rendArg, 0x00, 0x00, 0x00, 0xFF);
    }
}
//Initialize TrueType Font subsystem
bool Init::initTTF()
{
    bool success = true;
    if( TTF_Init() == -1 )
    {
        printf( "SDL_ttf could not initialize! SDL_ttf Error: %sn", TTF_GetError() );
        success = false;
    }
    return success;
}
//Initialize PNG loading subsystem
bool Init::initIMG()
{
    bool success = true;
    int imgFlags = IMG_INIT_PNG
    if (!(IMG_Init(imgFlags)&imgFlags))
    {
        printf("SDL_Image could not initialize! SDL_Image Error: %sn", IMG_GetError() );
        success = false;
    }
    return success;
}

main.cpp

1
2
3
4
5
6
7
8
9
10
11
#include "Init.h"

//global vars
SDL_Window* gWindow = NULL;
SDL_Renderer* gRenderer = NULL;

//main execution
int main(int argc, char* [] args)
{
    initAll(gWindow, gRenderer);
}

build messages (backspaced over long directory names for convenience)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
dirInit.h|6|error: expected unqualified-id before ')' token|
dirInit.cpp|4|error: invalid use of incomplete type 'class Init'|
dirInit.h|6|error: forward declaration of 'class Init'|
dirInit.cpp|15|error: invalid use of incomplete type 'class Init'|
dirInit.h|6|error: forward declaration of 'class Init'|
dirInit.cpp|26|error: invalid use of incomplete type 'class Init'|
dirInit.h|6|error: forward declaration of 'class Init'|
dirInit.cpp|34|error: invalid use of incomplete type 'class Init'|
dirInit.h|6|error: forward declaration of 'class Init'|
dirInit.cpp|42|error: invalid use of incomplete type 'class Init'|
dirInit.h|6|error: forward declaration of 'class Init'|
dirInit.cpp|55|error: invalid use of incomplete type 'class Init'|
dirInit.h|6|error: forward declaration of 'class Init'|
dirInit.cpp|70|error: invalid use of incomplete type 'class Init'|
dirInit.h|6|error: forward declaration of 'class Init'|
dirInit.cpp|81|error: invalid use of incomplete type 'class Init'|
dirInit.h|6|error: forward declaration of 'class Init'|
||=== Build finished: 17 errors, 0 warnings (0 minutes, 0 seconds) ===|

Look at line 14 of Init.h. There’s something missing…

A couple of things jump off the page:

— The brackets on line 6 of Init.h shouldn’t be there,
— The declaration and definition of initAll don’t match (one has no parameters, the other has two parameters)

Thanks a ton guys. Sometimes I just need a second pair of eyes that aren’t tired.

I gotta leave for work now, but I’ll take your advice when I get back!

Thanks in advance for any additional help.

Line 6 of Init.h:

1
2
3
4
5
6
7
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_ttf.h>
#include <stdio.h>

class Init //() <- you don't put parenthesis on class definitions.  Only for functions.
{

Also these are non-static members of a class, so you need to have an object to act on.

1
2
3
4
5
6
7
int main(int argc, char* [] args)
{
    // initAll(gWindow, gRenderer);  <- won't work because initAll isn't global

    Init obj;  // <- have to create an Init object
    obj.initAll( gWindow, gRenderer );
}

But of course… having an ‘Init’ object doesn’t really make much sense. Can you have multiple Inits? Does having the object actually do anything?

These functions are all global by nature. Rather than putting them in a class, maybe put them in a namespace:

1
2
3
4
5
6
7
8
9
10
11
12
namespace Init
{
   bool initAll();
   ...
}

//...

int main()
{
    Init::initAll( ... );
}

Or… if you don’t want a namespace… then make it a static class that can’t be instantiated (though that is more work for little gain).

Remember the whole point of a class is to represent a ‘thing’. They’re nouns.

Common examples of classes and what they represent:
std::string — represents a string
std::fstream — represents a file
std::list — represents a linked list of objects
etc

What exactly does an ‘Init’ represent? It’s not a ‘thing’, so it doesn’t really need to be a class.

Ah, thank you Disch. I wasn’t sure if classes NEEDED objects or not and I had forgotten about creating namespaces. I thought it was conventional to have objects of classes, but not mandatory. I had tried converting it to a struct before posting this thread, but obviously that didn’t work.

And I had thought about making an Init object (which would require me to write a constructor) but it occurred to me, like you said in your post, that it made no sense.

I’ll eventually remember all this if I fail enough times. :P

EDIT:

Disch! I noticed in your namespace example that you put the namespace Init member functions in main, is that truly necessary? The whole reason I decided to do this whole wrapper class thing was to keep excess stuff out of main. Should I define the functions inside the namespace, instead? Will that create problems because it’s inside a header?

Edit 2: Never mind the previous edit. Everything is in order now.

Last edited on

Topic archived. No new replies allowed.

In this guide, we will walk you through the process of troubleshooting and fixing C++ Invalid Use of Incomplete Type Errors. These errors usually occur when you try to use a class or structure that has been declared, but not yet defined or fully specified. Let’s dive into the details and learn how to fix these errors in your C++ code.

Table of Contents

  1. Understanding Invalid Use of Incomplete Type Errors
  2. Identifying the Causes of Invalid Use of Incomplete Type Errors
  3. Step-by-Step Guide to Fixing Invalid Use of Incomplete Type Errors
  4. FAQ
  5. Related Links

Understanding Invalid Use of Incomplete Type Errors

In C++, an incomplete type is a type that has been declared but not defined. This means that the compiler doesn’t have enough information about the type to determine its size or layout in memory. When you try to use an incomplete type in a way that requires the compiler to know its size or layout, you will encounter an «Invalid Use of Incomplete Type» error.

Here’s an example of an incomplete type error:

class MyClass; // Forward declaration

void myFunction(MyClass obj) {
  // Invalid use of incomplete type 'class MyClass'
  int x = obj.someFunction();
}

In this example, MyClass has been declared but not defined, so the compiler doesn’t know the size or layout of the class. When you try to use an object of type MyClass inside the myFunction function, the compiler generates an error.

Identifying the Causes of Invalid Use of Incomplete Type Errors

There are several common causes for Invalid Use of Incomplete Type Errors:

  1. Missing includes: If you forget to include the header file that contains the definition of a type, the compiler will only have access to its declaration and will treat it as an incomplete type.
  2. Forward declarations: When you use a forward declaration instead of including the header file, the type remains incomplete until it’s defined later in the code.
  3. Circular dependencies: If two types depend on each other, the compiler may not be able to determine their size and layout, which can result in an incomplete type error.

Step-by-Step Guide to Fixing Invalid Use of Incomplete Type Errors

  1. Check your includes: Make sure you’ve included the appropriate header files that contain the definitions of the types you’re using. If you’re unsure which header files to include, consult the documentation or source code of the library or module you’re using.
  2. Replace forward declarations with includes: If you’re using a forward declaration, consider replacing it with an include statement for the header file that contains the type’s definition. This will provide the compiler with the necessary information about the type.
  3. Resolve circular dependencies: If two types depend on each other, you may need to refactor your code to break the circular dependency. This can be done by using pointers or references instead of direct object instances, or by moving the common functionality to a base class or separate utility class.

FAQ

Why does forward declaration cause an incomplete type error?

Forward declaration is a technique used to inform the compiler about the existence of a class or structure without providing its full definition. This can be helpful in certain situations to avoid circular dependencies or reduce compile times. However, when you use a forward-declared type in a way that requires the compiler to know its size or layout, you will encounter an incomplete type error.

Can I use pointers or references to avoid incomplete type errors?

Yes, using pointers or references can help you avoid incomplete type errors because they don’t require the compiler to know the size or layout of the underlying type. Instead, the compiler only needs to know the size of the pointer or reference itself. This can be a useful technique when working with forward-declared types or circular dependencies.

How can I fix circular dependencies that cause incomplete type errors?

To fix circular dependencies, you can use one or more of the following techniques:

  • Use pointers or references instead of direct object instances, as they don’t require the compiler to know the size or layout of the underlying type.
  • Move common functionality to a base class or separate utility class, which can then be included by both dependent classes without creating a circular dependency.

Is it possible to use forward declarations and avoid incomplete type errors?

Yes, it is possible to use forward declarations without encountering incomplete type errors, as long as you only use the forward-declared type in ways that don’t require the compiler to know its size or layout. This typically means using pointers or references to the forward-declared type or only using the type in function declarations, not definitions.

What is the difference between a declaration and a definition in C++?

In C++, a declaration introduces a name and a type to the compiler, while a definition provides the complete information required to create an instance of the type. For example, a class declaration specifies the class name and any base classes or interfaces it inherits from, while the class definition includes the full list of member variables and member functions.

  • C++ Forward Declarations
  • C++ Incomplete Types
  • C++ Class Definitions
  • C++ Circular Dependency Solutions
  • C++ Headers and Includes

Solution 1

In order to define a class or struct, the compiler has to know how big each member variable of the class is. A forward declaration does not do this. I’ve only ever seen it used for pointers and (less often) references.

Beyond that, what you’re trying to do here cannot be done. You cannot have a class A that contains an object of another class B that contains an object of class A. You can, however, have class A contain a pointer to class B that contains an object of class A.

B.cpp

#include "B.h"

void B::SomeFunction()
{
}

B.h

#ifndef __B_h__  // idempotence - keep header from being included multiple times
#define __B_h__
#include "A.h"

class B
{
public:
    A a;
    void SomeFunction();
};

#endif // __B_h__

A.h

#ifndef __A_h__  // idempotence - keep header from being included multiple times
#define __A_h__
#include "B.h"

class B; // forward declaration

struct A
{
    B *b;  // use a pointer here, not an object
};

#endif // __A_h__

Two points. First, be sure to use some form of idempotence to keep the headers from being included multiple times per compilation unit. Second, understand that in C++, the only difference between classes and structs is the default visibility level — classes use private visibility by default while structs use public visibility by default. The following definitions are functionally equivalent in C++.

class MyClass
{
public: // classes use private visibility by default
    int i;
    MyClass() : i(13) { }
};

struct MyStruct
{
    int i;
    MyStruct() : i(13) { }
};

Solution 2

Forward declarations, like

struct A;

or

class A;

Introduce A as an incomplete type and it remains incomplete until end of type’s definition is reached. There are things you can do with incomplete types and things you can’t. You can

  1. Declare variables (or members) of type «pointer to A» and «reference to A»
  2. Declare functions which take arguments of type A or return type A

You can’t

  1. Declare variables (nor members) of type A
  2. Dereference pointers to A or access any members of references to A
  3. Define subclasses of A.

In your code you try to declare struct member of incomplete type. It’s illegal. Only pointers and references are allowed.

Solution 3

public:
    A a;

You are trying to create the object of A with only forward declaration. Compiler at this moment ( with only forward decl) cannot decide the size of the object A and hence, it cannot allocate memory required for A. So you cannot create objects with only forward decl.

Instead replace with:

A* a;

Pointer or reference to A without A’s class definition will work fine.

Solution 4

Two issues jump out at me here.

1: You’ve written Struct A instead of struct A; note the lower-case «s». Your compiler might consider the equivalent, but I don’t think it’s standard C++.

You have defined a circular reference between A and B. Each A object must contain a B object, but each B object must contain an A object! This is a contradiction, and will never work the way you want it to. The usual C++ way to solve that problem is to use pointers or references for A::b or B::a (or both).

Related videos on Youtube

ITERATORS in C++

17 : 09

Forward Declaration of Class C++

05 : 05

Forward Declaration of Class C++

C++ Header Files

15 : 10

Learning C++ STL - Forward List

10 : 14

Learning C++ STL — Forward List

C++/Game Tutorial 10: Parameters and Forward Declarations!

09 : 22

C++/Game Tutorial 10: Parameters and Forward Declarations!

C++ Class declaration | Part-1/2 | OOPs in C++ | Lec-13 | Bhanu Priya

15 : 41

C++ Class declaration | Part-1/2 | OOPs in C++ | Lec-13 | Bhanu Priya

Modern C++ CLASSES - Easy and In-depth explanation | All the basics you need with examples!

27 : 48

Modern C++ CLASSES — Easy and In-depth explanation | All the basics you need with examples!

C++ for C# and Java Developers

39 : 47

C++ for C# and Java Developers

C++11 Perfect Forwarding

17 : 24

UE4 C++ Tutorial - #Include and Forward Declarations - UE4 / Unreal Engine 4 Intro to C++

08 : 47

UE4 C++ Tutorial — #Include and Forward Declarations — UE4 / Unreal Engine 4 Intro to C++

C++ Forward Declaration Objects/Enums

02 : 19

C++ Forward Declaration Objects/Enums

Forward Declarations | Introduction to Programming with C++ | Part 43

04 : 09

Forward Declarations | Introduction to Programming with C++ | Part 43

Forward Declaration - Beginner C++ Tutorials

02 : 13

Forward Declaration — Beginner C++ Tutorials

Comments

  • The follwing code is compiled in VC++6. I don’t understand why I am getting the compilation error C2079: 'b' uses undefined class 'B' for the following code.

    Class B Source

    #include "B.h"
    
    void B::SomeFunction()
    {
    }
    

    Class B Header

    #include "A.h"
    
    struct A;
    
    class B
    {
        public:
            A a;
            void SomeFunction();
    };
    

    struct A Header

    #include "B.h"
    
    class B;
    
    struct A
    {
        B b;
    };
    

    If I changed class B header to the following, then there will be no error. But the header declaration won’t be at the top!

    Class B Header with weird header declaration

    struct A;
    
    class B
    {
         public:
            A a;
            void SomeFunction();
    };
    
    #include "A.h"
    

  • In the actual code, preprocessor macros are defined but it is not shown here to make the code simpler.

  • Double-underscores are reserved for the compiler. Use a different naming convention.

  • Double-underscores are reserved for the compiler. Use a different naming convention.

  • @GMan: I’ve always used this convention for my idempotence markings when the compiler doesn’t generate them automatically. Is this specific to a compiler or is it in the C++ spec?

  • @Matt, it is part of the C++ spec that such identifiers are reserved. I personally use «HEADER_PATH_TO_HEADER_H_INCLUDED» or «HEADER_PATH_TO_HEADER_INCLUDED» (if no «.h»).

Recents

Related

Понравилась статья? Поделить с друзьями:
  • Ошибка easyanticheat untrusted system file
  • Ошибка fortniteclient win64 shipping exe системная ошибка
  • Ошибка easyanticheat unknown file version
  • Ошибка fortnite vpn
  • Ошибка easyanticheat launch error