C++报错集合:

本文探讨了在C++中对于同一标识符分别以struct和class形式进行前向声明导致的链接器错误问题。通过具体案例分析了该错误产生的原因,并提供了相应的解决方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关闭
作为 按照设计

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(受限) 2008/12/26 -  
登录 发布 评论。
由  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

登录 发布 解决方法。
由  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
<<< 这个意思是,只声明了这个类,而没有定义这个类就去使用它了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值