gpt4 book ai didi

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

转载 作者:可可西里 更新时间:2023-11-01 15:24:27 26 4
gpt4 key购买 nike

假设我有两个文件:

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

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

/**
* 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;
}

编译如下:

g++ -o a.out main.cpp class.cpp 

可执行文件有输出:

[class.cpp:15]: func
[main.cpp:14]: ret=-1

最后是我的问题:

为什么这个示例代码编译没有任何错误,我们可以调用 class fooprivate 方法?

用 gcc 4.6.3 编译但不仅如此。我知道编译器不会区分这两个符号(func 函数来自命名空间 foo 和私有(private)函数 foo 来自 class foo). nm 的输出:

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

nm main.o
U _ZN3foo4funcEv
00000000 T main
U printf

请问这种行为是否正确?恕我直言,这不是正确的行为,而且根本不安全(破坏封装)。

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

最佳答案

为什么编译器不报错?

请注意,就编译器而言,“类”、“结构”和“命名空间”都定义了一个命名空间。所以编译器会相应地修饰符号。如果您在同一个文件中同时定义类和命名空间,它会报错,但这里不是这种情况。

为什么链接器不提示?

您编写代码的方式留下了 func()namespace foo 中定义弱于 func()class foo 中定义.基本上,func()namespace foo 中定义只是一个没有实现的签名。您可以看到它留给链接器在运行时解析符号,因为实现不在 main.cpp 中。 :

nm main.o
U _ZN3foo4funcEv
//Here^^^^

这样,由于命名空间和类名恰好相同(导致 foo::func 的符号相同),链接器在链接时解析符号,找到具有相同符号的强定义,并链接到它。

如果您要实现 func()namespace foo还有:

/**
* main.cpp
*/
#include <stdio.h>

namespace foo
{
int func(void) {
printf("NM_FOO [%s:%d]: %s\n", __FILE__, __LINE__, __FUNCTION__);
return -1;
};
}
int main(void)
{
int ret = foo::func();
printf("[%s:%d]: ret=%d\n", __FILE__, __LINE__, ret);
return 0;
}

您会看到链接器提示:

duplicate symbol foo::func()     in:
/var/folders/.../class.o
/var/folders/.../main.o
ld: 1 duplicate symbol for architecture x86_64

如果你这次查看 main.o,你会看到:

0000000000000064 T __ZN3foo4funcEv
0000000000000158 S __ZN3foo4funcEv.eh
00000000000000e0 s __ZZN3foo4funcEvE12__FUNCTION__
0000000000000000 T _main
0000000000000128 S _main.eh
U _printf

和class.o:

0000000000000000 T __ZN3foo4funcEv
00000000000000a0 S __ZN3foo4funcEv.eh
0000000000000080 s __ZZN3foo4funcEvE12__FUNCTION__
U _printf

两者都定义了同样强的相同函数符号,导致链接器错误。

请记住,链接器不知道命名空间和类之间的区别。它解析目标代码中的符号。如果发生强重新定义,它只会提示。一个或多个具有一个强定义的较弱定义在链接器世界中完全没问题。

关于c++ - 命名空间和静态类成员链接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15532745/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com