C2079中的C ++程序

时间:2017-05-15 07:56:54

标签: c++ header include

我试着理解C ++中的编译/链接是如何工作的。所以我创建了一个简单的测试项目,它具有以下形式:

A.H

class A {
  public:
   int a;
   A() { a = 3; }
};

B.h

#include "A.h"
class B {
   private:
     A myA;
};

Main.cpp的

#include <iostream>
#include "A.h" 
#include "B.h"
using namespace std;
int main() {
  A myA;
  B myB;
  cout << myA.a;
}

如果我尝试编译这个,我得到一个C2011(类类型重新定义)。这对我来说很清楚,因为B.h也包括A.h,而我的Main会看起来像:

class A { ...} // through include of A.h in Main.cpp 
class A { ...} 
// through include of B.h in Main.cpp which includes A.h as.    
// well causes the redefinition error

int main() { ... }

但为什么也是C2079错误

'B::myA' uses undefined class 'A' 
在B.h?因此,如果我包含A.h,则应插入A的类定义,B.h应该看起来像

class A { ... }  
class B {
   private:
     A myA;  
};

为什么A类没有在B.h中定义?应该通过包括A.h来提供类(如果我在Main.cpp中删除了A.h的包含它没有问题)

3 个答案:

答案 0 :(得分:0)

主要包括A和B. B包括A =&gt;主要包括A两次。使用ifndef。其中_UNIQ_FILE_NAME_A_HB_H

#ifndef _UNIQ_FILE_NAME_
#define _UNIQ_FILE_NAME_
// Content here
#endif // _UNIQ_FILE_NAME_

答案 1 :(得分:0)

  

如果我尝试编译这个,我得到一个C2011(类类型重新定义)。这对我来说很明显,因为B.h也包括A.h

所以,如果你清楚为什么你有错误,为什么不修复它?通常您应该使用header guards来确保它们只包含一次:

if let fontUsage = font.fontDescriptor.fontAttributes["NSCTFontUIUsageAttribute"] as? String {
    if fontUsage == "CTFontHeavyUsage" {
        print("It's Heavy")
    }
    else if fontUsage == "CTFontBlackUsage" {
        print("It's Black")
    }
}
  

但为什么还有C2079错误#ifndef A_h_ #define A_h_ class A { public: int a; A() { a = 3; } }; #endif /* A_h_ */

正如你所指出的那样,没有标题保护你的'B::myA' uses undefined class 'A'看起来像这样:

Main.cpp

这显然是一个错误,因为你定义了两个相同的类A.从这一点来看,其余的编译是没有意义的,因为Main.cpp不会编译,但编译器可能会忽略与{相关的错误} {1}}并尝试编译文件的其余部分以显示任何其他可能的错误。因为class A { ... } class A { ... } class B { ... } ... 有两个定义,所以它无法知道哪一个是正确的,因此微软编译器可能会将剩余的编译视为没有定义class A。这就是你获得class A的原因。

gcc for example won't report errors与使用class A有关,只会告诉您有'B::myA' uses undefined class 'A'并会显示之前定义的位置。

答案 2 :(得分:0)

要回答实际问题&#34;但为什么[还有] C2079错误B::myA使用未定义的类A&#34; :

编译器通常会尝试提供帮助并一次检测多个错误。为此,他们必须对第一个错误的性质做出一些假设。这可能并不总是很好,这似乎是其中一个案例。 即使A被标记为有问题,编译器仍继续编译,然后因使用A

而跳闸

事后看来,错误可能更好,因为&#34;&#39; B :: myA&#39;使用多重定义的类&#39; A&#39;&#34;。