3

I'm using Visual Studio 2015 Update 2. I have two headers called Error.h and Game.h.

Error.h:

#ifndef _Error_H
#define _Error_H

#include "Main.h"
#include "Core.h"
#include <Log.h>
#include <CWindows.h>

// ErrorIDs
enum
{
    ErrUnknownID = 0,
    blah,
    blah2,
    blah3
};

struct ErrInfo
{
    unsigned int  eiID;
    String        strCaption; // String is another class which implemented from std::string which works fine!
    String        strText;
    bool          bFixable = false;
};

// Static errors
extern ErrInfo WinNotSupported;
// blah blah

class Error
{

public:
    void Initialize();
    bool ShowError(ErrInfo ErrorInfo);
    BOOL FixError(unsigned int uiErrorID);

    // -----------------------------------------
    // --------------- Singleton ---------------
    // -----------------------------------------
public:
    static Error& Instance()
    {
        static Error instance;
        return instance;
    }

    static Error *InstancePtr()
    {
        return &Instance();
    }
private:
    Error()
    {

    }

public:
    Error(Error const&) = delete;
    void operator=(Error const&) = delete;
};

#endif // !_Error_H

And Game.h:

#ifndef _Game_H
#define _Game_H

#include "Main.h"
#include "Error.h"
#include "Core.h"
#include <CWindows.h>
#include <AFile.h>

struct missingfileSt
{
    String    strFileURL;
    String    strDLFileName;
    String    strFileName;
    String    strChecksum;
    long long llSize;
    ErrInfo   errError; // Many errors here <-
};

struct deletablefileSt
{
    String  strFileName;
    ErrInfo errError; // Many errors here too
};

#define siMissingFiles   7
#define siDeletableFiles 5

class Game
{
public:

    void ValidateFiles();
    DWORD dwGamePID;
    missingfileSt   mfMissingFiles[siMissingFiles];
    deletablefileSt dfDeletableFiles[siDeletableFiles];

    // -----------------------------------------
    // --------------- Singleton ---------------
    // -----------------------------------------
public:
    static Game& Instance()
    {
        static Game instance;
        return instance;
    }

    static Game *InstancePtr()
    {
        return &Instance();
    }
private:
    Game()
    {
        dwGamePID = 0;
    }

public:
    Game(Game const&) = delete;
    void operator=(Game const&) = delete;
};

#endif // !_Game_H

Now, when I compile I get many errors from Game.h and all of them are:

Error C3646 'errError': unknown override specifier
Error C4430 missing type specifier - int assumed. Note: C++ does not support default-int

I got really confused, why errors!? Also I must say, in header Core.h it will include Error.h again but it mustn't be problem!

Toby Speight
  • 27,591
  • 48
  • 66
  • 103
rez
  • 316
  • 1
  • 3
  • 18
  • `String` should be `string`, are you `using namespace std` ? If not then you should declare the strings as `std::string`. Could you edit your post by giving the full contents of both files ? – KostasRim Aug 22 '16 at 08:30
  • @KostasRim Don't get confused with std::string, String is another class of mine which works fine! – rez Aug 22 '16 at 08:31
  • 3
    Two things (but unrelated to your problem): First of all don't use any symbols with leading underscore followed by an upper-case letter, those are reserved in all scopes ([see here for reference](http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier)). Secondly, unless you are forced to, or it's part of a school assignment, don't use custom string classes. Either use `std::string` or some other string class from the framework you're using (e.g. `QString` from Qt or the MFC `CString` class). Don't reinvent the wheel, it will only end in sorrow. – Some programmer dude Aug 22 '16 at 08:31
  • @AssassiN please edit the post and provide more details of the two files – KostasRim Aug 22 '16 at 08:34
  • @JoachimPileborg Thank you for tips, String is a class implemented from std::string. – rez Aug 22 '16 at 08:34
  • 1
    @JoachimPileborg `Don't reinvent the wheel, it will only end in sorrow` If I could thumbs up to infinity I would ! – KostasRim Aug 22 '16 at 08:34
  • @AssassiN The issue is that you have circular dependencies with your headers. As i can conclude with the error u posted, please do share more details – Keshan Nageswaran Aug 22 '16 at 08:35
  • `_Foo_H` is a reserved name, don't use it. Anything with leading underscore followed by uppercase letter as well as any name containing double underscore "__" is reserved for the implementation and should not be used in user code. – Jesper Juhl Aug 22 '16 at 08:36
  • As for your problem, is any of the "required header files" possibly `Bar.h`? Or does any of them include `Bar.h`? You need to check that for both `Foo.h` and `Bar.h`. – Some programmer dude Aug 22 '16 at 08:37
  • @kesh Edited, it's all of it. – rez Aug 22 '16 at 08:43
  • @JesperJuhl Yes, I know what you are talking about but I'm gonna fix it later – rez Aug 22 '16 at 08:44
  • @KostasRim Edited, check again, thanks. – rez Aug 22 '16 at 08:44
  • @JoachimPileborg Edited. – rez Aug 22 '16 at 08:44
  • @AssassiN Why are you using the `extern ErrInfo WinNotSupported` ? It should only be placed inside a source file. – KostasRim Aug 22 '16 at 08:58
  • @AssassiN hey i found a post related to your error and answer is there too hope this will help u [http://www.cplusplus.com/forum/beginner/171185/] – Keshan Nageswaran Aug 22 '16 at 09:02
  • @KostasRim I'm using them inside other .cpp files so I need something static, it's defined on Error.cpp and it's fine – rez Aug 22 '16 at 09:17
  • @AssassiN No, it is not fine. Extern means external linkage, it should be placed on a source file and not in a header. – KostasRim Aug 22 '16 at 09:22
  • @AssassiN btw where and how `extern ErrInfo WinNotSupported` is defined? – KostasRim Aug 22 '16 at 09:23
  • In Error.cpp like this: ErrInfo WinNotSupported; – rez Aug 22 '16 at 09:26
  • Problem solved/twisted, see the post. – rez Aug 22 '16 at 09:39
  • Please don't edit your post with "Solved" - instead, please accept the answer you found most helpful. I've rolled back your edit for you this time. – Toby Speight Aug 22 '16 at 14:58
  • @TobySpeight Okay, thanks. – rez Aug 23 '16 at 11:31

2 Answers2

7

An old question already but a useful answer is missing for all C++ newbies or those who are forced to understand (very) bad C++ compiler messages.

If you get "missing type specifier", "unknown override", "undefined type/class", "syntax error: (" (for a beginning function parameter list) although you included the proper header file then it indicates that there is some circular reference in your include-hierarchy. This is also true if you have a forward declaration and the type is still "unknown".

The only solution with the old include-system in C++ is to avoid circular references between #includes. It's achieved by moving #includes from a header file A.h to the A.cpp and by forward declaring the types (or methods) in A.h. If you don't move the #include to A.cpp it still can fail despite forward declaration.

Let A.h be a circular include in B.h because B.h would already be included by A.h. Instead of

#include "A.h"

class B {
    A a;
}

you can write

class A;

class B {
    A a;
}

and include A.h in your CPP file(s).

You can avoid the need for method forward declarations if you only define methods in CPP files.

ChrisoLosoph
  • 459
  • 4
  • 8
  • 1
    You can only use forward declaration of classes to use them in pointers or references. The compiler needs to know how big is your class really is in order to correctly map the members to the correct offset otherwise. – rez Oct 09 '21 at 18:03
1

I just moved ErrInfo struct to another header with the same include guard and it compiled and worked without problem, I think it's compiler failure, if it isn't please explain.

rez
  • 316
  • 1
  • 3
  • 18
  • Weird. I would have expected that particular include guard to be problematic, and global types named ErrInfo and Error to have a high chance of conflict with something, but just moving them to a different header while keeping the include guard name solving the problem is strange. – Sebastian Redl Aug 23 '16 at 10:49
  • @SebastianRedl Yes, I also tried "#pragma once" but it didn't work out, sometimes Visual Studio goes crazy – rez Aug 23 '16 at 10:53