use*_*130 3 c++ gcc scope initialization visual-studio
这个问题是密切相关的先前问了一个问题在这里.
为了使Visual Studio 2010 C++调试器能够解析类内初始化的const变量,必须提供变量的全局定义.
例如
这是类定义:
class B{
public:
static const int m_b=100;
};
Run Code Online (Sandbox Code Playgroud)
以下是该成员的全局范围定义:
const int B::m_b;
Run Code Online (Sandbox Code Playgroud)
没有全局定义代码可以工作,但调试器在B的方法中看不到m_b.
然而,这导致另一个问题.在非平凡的头文件包含安排(下面给出的完整代码)中,Visual Studio产生此链接错误:
error LNK2005: "public: static int const B::m_b" (?m_b@B@@2HB) already defined in a.obj
1>a.exe : fatal error LNK1169: one or more multiply defined symbols found
Run Code Online (Sandbox Code Playgroud)
但是,GCC成功编译,链接和运行代码.
这是有问题的代码:
文件a.cpp:
#include <iostream>
#include "a.h"
const int B::m_b;
int main()
{
B b;
std::cout << b.m_b;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
档案啊:
#pragma once
#include "b.h"
Run Code Online (Sandbox Code Playgroud)
文件b.cpp:
#include "b.h"
Run Code Online (Sandbox Code Playgroud)
文件bh:
#pragma once
class B {
public:
static const int m_b = 100;
};
Run Code Online (Sandbox Code Playgroud)
以下是链接器选项(默认VS10控制台程序):
/OUT:"a.exe"
/NOLOGO "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib"
/MANIFEST
/ManifestFile:"Debug\a.exe.intermediate.manifest"
/ALLOWISOLATION
/MANIFESTUAC:"level='asInvoker' uiAccess='false'"
/DEBUG
/PDB:"Debug\a.pdb"
/PGD:"Debug\a.pgd"
/TLBID:1 /DYNAMICBASE /NXCOMPAT /MACHINE:X86 /ERRORREPORT:QUEUE
Run Code Online (Sandbox Code Playgroud)
以下是编译器选项(默认VS10控制台程序):
/ZI /nologo /W3 /WX- /Od /Oy- /D "_MBCS" /Gm /EHsc /RTC1 /GS /fp:precise /Zc:wchar_t
/Zc:forScope /Fp"Debug\sndbx.pch" /Fa"Debug\" /Fo"Debug\" /Fd"Debug\vc100.pdb" /Gd
/analyze- /errorReport:queue
Run Code Online (Sandbox Code Playgroud)
同样,这与GCC(g ++ a.cpp b.cpp)成功构建,链接和运行.我提供的代码已经完成,因此可以复制,粘贴和运行.
您不应将非模板定义的数据放在头文件中,因为在链接时会出现多个定义错误.变量是成员变量还是静态成员变量或const静态成员变量都不会改变它.
将定义放在一个编译单元中,就像您对任何其他单例一样.
这实际上看起来像一个Visual C++错误.如果您已经显示完整的错误消息,那将会有很大帮助
b.obj:错误LNK2005:已在a.obj a.exe中定义的"public:static int const B :: m_b"(?m_b @ B @@ 2HB):致命错误LNK1169:找到一个或多个多重定义的符号
如果编译器工作正常,则不会在b.obj中的任何位置定义该符号.
此外,尝试使用__declspec(selectany)告诉我们编译器知道这不是一个定义:
r:\ 16404173\bh(3):错误C2496:'B :: m_b':'selectany'只能应用于具有外部链接的数据项
最后,Visual C++显然正在定义符号(错误地):
R:\ 16404173> dumpbin/symbols b.obj Microsoft(R)COFF/PE Dumper Version 10.00.40219.01版权所有(C)Microsoft Corporation.版权所有.
Run Code Online (Sandbox Code Playgroud)Dump of file b.obj File Type: COFF OBJECT COFF SYMBOL TABLE 000 00AB9D1B ABS notype Static | @comp.id 001 00000000 SECT1 notype Static | .drectve Section length 2F, #relocs 0, #linenums 0, checksum 0 003 00000000 SECT2 notype Static | .debug$S Section length 64, #relocs 0, #linenums 0, checksum 0 005 00000000 SECT3 notype Static | .rdata Section length 4, #relocs 0, #linenums 0, checksum B4446054, selection 2 (pick any) 007 00000000 SECT3 notype External | ?m_b@B@@2HB (public: static int const B::m_b)
此外,我们看到它已被标记为selectany已经存在.但在具有实际定义的编译单元中:
Run Code Online (Sandbox Code Playgroud)Section length 4, #relocs 0, #linenums 0, checksum B4446054 229 00000000 SECTB9 notype External | ?m_b@B@@2HB (public: static int const B::m_b)
该(pick any)注释不见了.哪个是正确的,这是变量的权威定义.
变量完全出现是错误的b.obj.编译器通过使用selectany注释使得简单的情况(头文件内部的初始化)起作用,但是当提供真实的定义时,这种hackish的解决方法就会崩溃.
最后,__declspec(selectany)在a.cpp中添加实际定义可解决链接错误.但我担心这个符号仍会被链接器优化掉,在调试过程中不可用.你可以暂时使用它/OPT:NOREF来避免这种情况(但它会使你的可执行文件膨胀,所以在发货前再关闭该选项).
| 归档时间: |
|
| 查看次数: |
1182 次 |
| 最近记录: |