为什么可以向外部库添加函数来访问内部数据

Why is it possible to add functions to external library to access internal data

本周我需要在我们的内部静态库中添加一个功能,但我懒得重新编译该库,所以我只是修改了 header 文件并能够访问私有成员。当库是 Windows dll.

时,也可以这样做

示例 header 可能如下所示:

#pragma once

#ifdef DLL
#define DLL_INTERFACE __declspec(dllexport)
#else
#define DLL_INTERFACE
#endif

class DLL_INTERFACE foo
{
public:
    foo(); // init foo::a and foo::b to 0

    int getA() const;
    void setA(int a); // set foo::a to a and foo::b to a+2
private:
    int a;
    int b;
};

现在我将自己的函数添加到 header 中,允许我像这样访问其私有成员:

class DLL_INTERFACE foo
{
public:
    foo(); // init foo::a and foo::b to 0

    int getA() const;
    void setA(int a); // set foo::a to a and foo::b to a+2

    int getB() const
    {
        return b;
    }
    void setB(int b)
    {
        this->b = b;
    }
private:
    int a;
    int b;
};

在测试我的新功能并重新编译库(不依赖于那个 hack)时,我意识到这可能会危及 object.

的内部状态

为什么这个allowed/possible要更改已编译库(dll或静态库)的header文件? (我原以为编译器或链接器会抱怨库中的 object 与 header 中定义的 object 不匹配)

提前致谢

以这种方式更改 header 并使用更改后的 header 重新编译程序的一部分会导致违反 "One Definition Rule",因此是未定义的行为。

这种违规行为可能已经被 C++ 实现 检测到。这种检测在技术上不是很有挑战性。基本上,编译器计算它看到的所有定义的哈希值,并将 names-to-hashes 字典存储在 object 文件中,然后 linker 检查它们是否全部匹配。该方法与现有实现所采用的 name-mangling 没有太大区别。但是,这需要更改 linker,可能还会更改 object 文件格式,并且还会增加编译和 link 时间。这就是为什么实现并不急于实现它,因此 C++ 标准不太可能强制执行它。所以它可能仍然是 no-diagnostic-required 违规行为。