命名空间和静态类成员链接

pak*_*ako 11 c++ linker gcc g++

可以说我有两个文件:

/**
 * class.cpp
 */ 
#include <stdio.h>
class foo 
{
private:
        int func();
};

int foo::func(void)
{
        printf("[%s:%d]: %s\n", __FILE__, __LINE__, __FUNCTION__);
        return -1; 
}
Run Code Online (Sandbox Code Playgroud)

/**
 * main.cpp
 */ 
#include <stdio.h>
namespace foo 
{
        int func(void);
}
int main(void)
{
        int ret = foo::func();
        printf("[%s:%d]: ret=%d\n", __FILE__, __LINE__, ret);
        return 0;
}
Run Code Online (Sandbox Code Playgroud)

汇编如下:

g++ -o a.out main.cpp class.cpp 
Run Code Online (Sandbox Code Playgroud)

可执行文件有一个输出:

[class.cpp:15]: func
[main.cpp:14]: ret=-1
Run Code Online (Sandbox Code Playgroud)

最后我的问题是:

为什么这个示例代码编译没有任何错误,我们能够调用类foo的私有方法?

用gcc 4.6.3编译但不仅如此.我知道,编译器并不区分这两个符号(FUNC从空间中的函数foo的和私有函数FOO类Foo).nm的输出:

nm class.o
00000000 T _ZN3foo4funcEv
00000017 r _ZZN3foo4funcEvE12__FUNCTION__
         U printf

nm main.o
         U _ZN3foo4funcEv
00000000 T main
         U printf
Run Code Online (Sandbox Code Playgroud)

我想问一下这种行为是否正确?恕我直言这是不正确的行为,它根本不安全(打破封装).

我想提一下,visual studio 2008中的编译器不会链接这两个符号.

Jon*_*ter 2

因为您已foo()在 main.cpp 中定义为命名空间的成员,所以编译器就是这样处理它的。类/结构/命名空间公共/私有等之间的区别取决于编译器是否了解函数的定义 - 在这里你故意欺骗它。

链接器不知道这种区别,它只是解析符号名称,并且在编译器的情况下,函数名称的修饰结果是相同的。C++ 中未指定符号名称的修饰方式,因此这是完全有效的行为。