0
votes

I'm getting an undeclared identifier error (C2065 on vs2013) on my project, I managed to replicate the problem in the example code below:

foo.h:

#pragma once

#include "bar.h"

class Foo
{

public:
    inline void doStuff() { someFunction(); }

};

bar.h:

#pragma once

#include <map>

#include "foo.h"

extern std::map<const char*, Foo> myMap;

void someFunction();

bar.cpp:

#include "bar.h"

std::map<const char*, Foo> myMap;

void someFunction()
{

}

main.cpp:

#include "foo.h"

int main()
{
    Foo foo;
    foo.doStuff();
    return 0;
}

When building on Visual Studio Express 2013, it gives these errors:

error C2065: 'Foo' : undeclared identifier

error C2923: 'std::map' : 'Foo' is not a valid template type argument for parameter '_Ty'

error C3861: 'someFunction': identifier not found

What is the problem here and how can it be solved?

2

2 Answers

1
votes

The problem is caused by circular dependency between foo.h and bar.h. It can be resolved using any of the following methods that I can think of.

Method 1

  1. Use forward declaration of the class Foo in bar.h.
  2. Don't use #include "foo.h" in bar.h.

foo.h:

#pragma once

#include "bar.h"

class Foo
{

public:
    inline void doStuff() { someFunction(); }

};

bar.h:

#pragma once

#include <map>

// #include "foo.h"
class Foo;

extern std::map<const char*, Foo> myMap;

void someFunction();

Method 2

  1. Create foo.cpp and add it to the project.
  2. Move the implementation of Foo::doStuff() to foo.cpp.
  3. Don't use #include "bar.h" in foo.h.

foo.h:

#pragma once

class Foo
{

public:
    void doStuff();

};

bar.h:

#pragma once

#include <map>

#include "foo.h"

extern std::map<const char*, Foo> myMap;

void someFunction();

foo.cpp:

#include "foo.h"
#include "bar.h"

void Foo::doStuff(){ someFunction(); }

Method 3

Use both Method 1 and Method 2.

foo.h:

#pragma once

class Foo
{

public:
    void doStuff();

};

bar.h:

#pragma once

#include <map>

// #include "foo.h"
class Foo;

extern std::map<const char*, Foo> myMap;

void someFunction();

foo.cpp:

#include "foo.h"
#include "bar.h"

void Foo::doStuff(){ someFunction(); }

I strongly suggest using Method 3. As a general guide, it's better to use forward declarations in header files if you don't need the full definition of a class.

5
votes

You have a circular definition problem. Note that foo.h includes bar.h and bar.h includes foo.h. This cannot work, because it means that neither definition can be completed until the other definition is completed first. The only way you can really fix this problem is to change your structure so that one of the headers does not #include the other header.