C++报错集合:

来源:互联网 发布:大话数据结构是c语言吗 编辑:程序博客网 时间:2024/05/16 04:50

class vs struct in forward declaration leads to linker error 填写者 Yevgen Muntyan

关闭
作为 按照设计

1
0
登录
进行投票
 
 
 
 类型:错误代码:389738打开日期:2008/12/26 16:52:24访问限制:公开
   
1
解决方法
1
用户可以重现此错误
 
 
 
 
Please see attached test case. What happens there is roughly this: 

// parser.h
struct ErrorInfo { // note it's struct
};
void func(ErrorInfo *foo);

// worksheet-p.h
class ErrorInfo; // and now it's class

// worksheet.cpp
#include "worksheet-p.h" // 'class' first
#include "parser.h"
// use func(ErrorInfo*); here

Linker complains it can't find definition of that func(ErrorInfo*), even though it does get compiled. It appears that struct vs class is the problem. The file where the function is defined (parser.obj in the test project) has this:

0ED 000001D0 SECT35 notype ()    External     | ?parse@parser@ggap@@YA?AW4Result@12@ABVQStringList@@PAUText@12@PAV?$QList@UErrorInfo@parser@ggap@@@@@Z (enum ggap::parser::Result __cdecl ggap::parser::parse(class QStringList const &,struct ggap::parser::Text *,class QList<struct ggap::parser::ErrorInfo> *))

and the file which uses it (worksheet.obj) has this:

32F 00000000 UNDEF notype ()    External     | ?parse@parser@ggap@@YA?AW4Result@12@ABVQStringList@@PAUText@12@PAV?$QList@VErrorInfo@parser@ggap@@@@@Z (enum ggap::parser::Result __cdecl ggap::parser::parse(class QStringList const &,struct ggap::parser::Text *,class QList<class ggap::parser::ErrorInfo> *))

The difference is the last argument - struct ggap::parser::ErrorInfo versus class ggap::parser::ErrorInfo. If you change the forward declaration from class to struct then the error goes away.

Now, I couldn't reproduce it with a small project, so I trimmed down mine instead. Also, the pieces of object files above are from the real project (so you can see QStringList and whatnot there); the test project doesn't have any external dependencies, and I put the build log in there too, just in case. Please let me know if you need my object files too.
详细信息 
Product Language
English

Version

Visual Studio 2008
Operating System
Windows XP Home Edition
Operating System Language
English
Steps to Reproduce
1. Unpack attached zip file with the test project.
2. Open bug/VS/GGAP.sln.
3. Build Solution.
Actual Results
Linker error (see bug/BuildLog.htm):

ggaplib.lib(worksheet.obj) : error LNK2019: unresolved external symbol "enum ggap::parser::Result __cdecl ggap::parser::parse(class std::vector<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::allocator<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > > const &,struct ggap::parser::Text *,class std::vector<class ggap::parser::ErrorInfo,class std::allocator<class ggap::parser::ErrorInfo> > *)" (?parse@parser@ggap@@YA?AW4Result@12@ABV?$vector@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@std@@PAUText@12@PAV?$vector@VErrorInfo@parser@ggap@@V?$allocator@VErrorInfo@parser@ggap@@@std@@@5@@Z) referenced in function "public: void __thiscall ggap::Worksheet::processInput(class std::vector<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::allocator<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > > const &)" (?processInput@Worksheet@ggap@@QAEXABV?$vector@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@std@@@Z)
Expected Results
No errors should occur, the code is fine. The aforementioned function is indeed defined in parser.cpp, and it is present in resulting parser.obj.
TAP Code (if applicable)
 
      You can indicate your satisfaction with how Microsoft handled this issue by completing this quick 3 question survey. [Details]

 

文件附件
文件名提交者提交时间文件大小 bug.zip(受限)Yevgen Muntyan2008/12/26- 
  • 评论 (4)
  • 解决方法 (1)
登录 发布 评论。
由 Yevgen Muntyan 在 2010/2/18 10:56 发送
VS folks have confirmed that it is indeed a bug, but it won't be fixed because of backwards compatibility stuff.
由 Yevgen Muntyan 在 2009/1/14 23:27 发送
I do not think ODR matters here. The bug is about declarations, not multiple definitions. I claim that the following code is good C++:

class A;
struct A {
};

Both occurrences of identifier 'A' here refer to the same structure A. Note that this simple code doesn't cause an error in Visual Studio.
由 Microsoft 在 2009/1/6 10:33 发送
This is an error in the source code. C++ has what is known as the one-definition-rule (ODR), which states that each uniquely named type must use the same definition in all places. Defining ErrorInfo as a class in one set of sources and as a struct in other sets of sources violates the ODR.

In this case, the unresolved external is an indication of the ODR violation. The correct thing to do would be to change the sources to use a consistent definition of ErrorInfo everywhere.

Mark Levine
Dev Lead - Visual C++
由 Microsoft 在 2008/12/28 22:51 发送
Thanks for your feedback. We are escalating this bug to the product unit who works on that specific feature area. The team will review this issue and make a decision on whether they will fix it or not for the next release.

Thank you, 
Visual Studio Product Team

  • 解决方法 (1)
登录 发布 解决方法。
由 Yevgen Muntyan 在 2008/12/26 16:54 发送
Workaround is obvious, listen to the warning C4099 and use class/struct 
consistently both in class definitions and forward declarations.


编译下来有个问题。就用我写的appfl下的说,在A.h里我定义了struct info(注意是struct ),在B.h里又声明了class info(注意是class ),在B.cc里含有#include “A.h”。结果编译的时候,报错说是B.h:25: error: forward declaration of 'struct info'。就是说info不能重复声明为不同的struct 和class类型。那怎么改?
 
forward declaration
<<< 这个意思是,只声明了这个类,而没有定义这个类就去使用它了

原创粉丝点击