C++ 与常量相关的错误

C++ 与常量相关的错误,c++,compilation,constants,C++,Compilation,Constants,在Visual Studio 2008中,将成功生成以下代码: void Foo (int x);//Prototype void Foo(const int x)//Implementation { } 但是,这将在链接期间生成错误(未解析的外部符号): void Foo (int x);//Prototype void Foo(const int x)//Implementation { } void Bar() { int x = 0; Foo(x); } 问

在Visual Studio 2008中,将成功生成以下代码:

void Foo (int x);//Prototype

void Foo(const int x)//Implementation
{

}
但是,这将在链接期间生成错误(未解析的外部符号):

void Foo (int x);//Prototype

void Foo(const int x)//Implementation
{

}

void Bar()
{
    int x = 0;
    Foo(x);
}
问题是因为Foo的函数实现指定整数参数为常量,而原型不需要常量


为什么会发生这种情况?为什么编译过程中没有检测到问题?

,因为你在C++中编译,所以编译器认为这两个函数(一个带有const PARAM和一个非conPARAM)是两个独立的函数(不同的修饰名)。只实现了其中一个,使用了另一个,因此出现了链接错误。

问题是,当您调用函数时,您调用了
foo
,但您已经定义了
foo
(大写F)。这两个Foo都(重新)声明了相同的函数,因为参数上的顶级常量对函数的签名没有贡献。如果声明不是定义,则忽略它们;如果声明是定义,则参数变量被视为函数中的常量。想想看——如果参数是作为副本(按值)传递的,那么函数是否会更改副本对调用方来说是完全无关的。这就是为什么只在参数的顶级常量上有所不同的函数声明被认为是声明同一个函数的原因。

为了绝对确保Armen没有疯:

#include <type_traits>

int main()
{
    static_assert( std::is_same<void(int ), void(const int )>::value, "...");
    static_assert(!std::is_same<void(int&), void(const int&)>::value, "...");
}
#包括
int main()
{
静态断言(std::is_same::value,“…”;
静态断言(!std::is_same::value,“…”);
}
这应该可以在任何符合标准的编译器上编译,并且至少支持C++0x。否则,编译器将被破坏。例如,g++4.5.1很好地接受了这段代码


顺便说一句,你的实际问题是你定义了一个
Foo
,但是调用了一个
Foo
(注意不同的情况)。

这是因为你的编译器坏了。损坏的编译器可以自己选择其行为。我知道有些编译器对那个案子的处理方式有点破绽


在MSDN上查看有关记录破坏行为的手册。它可以与兼容(在这方面没有损坏)编译器配合使用。

否!事实并非如此。参数上的顶级常量不构成函数的签名。它们是相同的功能@Armen Tsirunyan:这个(使用MSVC 2010构建)int func(int&x){return x;}int func(const int&x){return x;}void Text(){func(1);}@Edwin:int与const int是相同的。int vs const int&is不是,因为一个是对is的引用。int&vs const int&也不相同,因为const不是顶级的。参见C++标准重载chapter@ArmenTsirunyan:是的,我忘了&第一次(我编辑过,但你是)faster@Edwin:演示顶级:int*=int*const(顶级)int*!=const int*(非顶级)根据你的回答,这里应该没有问题。你实际上还没有回答这个问题:为什么链接器错误,为什么它在编译时没有被检测到?@Noah:我打赌有一个编译时错误。编译器不可能不发出foo是未声明标识符的诊断。除非它是一个扩展which允许在不声明的情况下调用函数,这将在查找foo定义时产生链接器错误。请删除下一票-对于顶级常量的解释,不需要+1-我不知道这一点。正如Johannes所建议的,实际问题可能是编译器损坏,但我很欣赏解释对问题中的“红鲱鱼”的解释。啊,Bar()中的调用foo(x)应该是foo(x)。您使用的是什么版本的Visual Studio?2002?2003?2005?2008?2010?现在是2008。我也会将其编辑到问题中。它确实编译得很好。@DeadMG:“它”是什么?Visual Studio 2008既不支持
也不支持
静态断言
。是的,当我将其放入VS2008中时,尝试包含不起作用。奇怪的是,MSDN上有此页面:@仅:如果安装,您将获得定义
。我认为这就是问题所在: