如何解决这个未声明的标识符

时间:2015-06-27 21:02:36

标签: c++ linker extern

我的项目中出现了未声明的标识符错误(vs2013上的C2065),我设法在下面的示例代码中复制了该问题:

foo.h中:

select t.name,
       count(*) as num_managers
  from employees m
  join addresses a
    on m.addressid = a.addressid
  join towns t
    on a.townid = t.townid
 where exists (select 1 from employees x where x.managerid = m.employeeid)
 group by t.name
 order by 2 desc

bar.h:

#pragma once

#include "bar.h"

class Foo
{

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

};

bar.cpp:

#pragma once

#include <map>

#include "foo.h"

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

void someFunction();

main.cpp中:

#include "bar.h"

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

void someFunction()
{

}

在Visual Studio Express 2013上构建时,会出现以下错误:

错误C2065:'Foo':未声明的标识符

错误C2923:'std :: map':'Foo'不是参数'_Ty'的有效模板类型参数

错误C3861:'someFunction':找不到标识符

这里有什么问题,如何解决?

2 个答案:

答案 0 :(得分:5)

您有循环定义问题。请注意,foo.h包括bar.h bar.h包括foo.h.这不起作用,因为这意味着在第一个完成其他定义之前,两个定义都不能完成。您可以真正解决此问题的唯一方法是更改​​您的结构,以便其中一个标题不会{{1}}另一个标题。

答案 1 :(得分:1)

问题是由foo.h和bar.h之间的循环依赖引起的。它 可以使用我能想到的任何以下方法解决。

方法1

  1. 在bar.h中使用类Foo的前向声明。
  2. 请勿在bar.h中使用#include "foo.h"
  3. 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();
    

    方法2

    1. 创建foo.cpp并将其添加到项目中。
    2. Foo::doStuff()的实现移至foo.cpp。
    3. 请勿在foo.h中使用#include "bar.h"
    4. 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(); }
      

      方法3

      同时使用方法1 方法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(); }
      

      我强烈建议使用方法3 。作为一般指南,最好是 如果您不需要完整,请在头文件中使用前向声明 一个类的定义。