gpt4 book ai didi

c++ - 为什么链接器不保留封装?

转载 作者:太空狗 更新时间:2023-10-29 23:49:42 28 4
gpt4 key购买 nike

让我们假设以下头文件 foo.h:

class Foo {
private:
void print() const;
};

和以下 foo.cpp:

#include <iostream>

#include "foo.h"

void Foo::print() const {
std::cout << "Secret" << std::endl;
}

另一个头文件 foo1.h,与 foo.h 相同,除非方法 print 被声明为 public:

class Foo {
public:
void print() const;
};

这将是 main.cpp,它只是在 foo1.h 中调用 print:

#include "foo1.h"

int main() {
Foo f;
f.print();
return 0;
}

对我来说奇怪的是以下链接会起作用:

g++ foo.cpp -c -o foo.o
g++ main.cpp -c -o main.o
g++ main.o foo.o -o exec
./exec

最后一条命令会输出:

Secret

因此,在不知道类 Foo 的具体实现但知道它的声明和目标文件的情况下,我们可以创建可以使用其方法的情况,即使它们被声明为私有(private)。

我的问题是:

  1. 为什么有效?链接器不考虑私有(private)和公共(public)声明?

  2. 这种行为在实践中有用吗?如果是,它是如何使用的?我猜它可能对测试有用。

最佳答案

首先,因为您违反了“一个定义规则”(C++11 3.2/5“一个定义规则”说不同翻译单元中的单独类定义必须“由相同的标记序列组成”) ,就工具链而言,一切都可以。它可以诊断出一个错误,或者生成一个看起来可以工作的程序(就像在您的测试中一样)。

你的实验产生你所看到的结果的一个简单原因是编译器“强制”访问类成员,并且你已经告诉编译器访问成员 Foo::print () 是公开的。

它符合工具链对因其他原因(例如重载)执行的名称 mangle 中的成员的访问进行编码。但是,由于该标准不要求工具链强制执行它,因此实现者似乎决定他们不需要在链接时考虑访问控制。换句话说,我认为将访问控制编码到链接器使用的外部符号中是可行的,但这项工作尚未完成;可能是因为严格来说没有必要。

请注意,Microsoft C++ 确实在外部名称中合并了对成员的访问权限,因此您确实会遇到链接时错误:

testmain.obj : error LNK2019: unresolved external symbol "public: void __thiscall Foo::print(void)const " (?print@Foo@@QBEXXZ) referenced in function _main testmain.exe : fatal error LNK1120: 1 unresolved externals

这里是 g++ 生成的符号(连同 c++filt 解码):

D:\so-test>nm test.o | grep Foo
000000000000008c t _GLOBAL__sub_I__ZNK3Foo5printEv
0000000000000000 T _ZNK3Foo5printEv

D:\so-test>nm testmain.o | grep Foo
U _ZNK3Foo5printEv

D:\so-test>c++filt _ZNK3Foo5printEv
Foo::print() const

这里是 MS C++ 生成的符号(连同解码):

D:\so-test>dumpbin /symbols test.obj | grep Foo
22D 00000000 SECTBA notype () External | ?print@Foo@@ABEXXZ (private: void __thiscall Foo::print(void)const )

D:\so-test>dumpbin /symbols testmain.obj | grep Foo
009 00000000 UNDEF notype () External | ?print@Foo@@QBEXXZ (public: void __thiscall Foo::print(void)const )

关于c++ - 为什么链接器不保留封装?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37933470/

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