首页 > 解决方案 > 在 C++ 中本地重新定义全局函数的实现

问题描述

我正在为现有的 C++ 应用程序编写一些测试代码,方法是编写一个包含main()函数和一些辅助类的文件,并将其链接到应用程序其他类的目标文件。我无权访问源文件,只能访问我无法修改的标题和对象/库。

在我的测试代码中,我想输出一个巨大结构的字段子集。ostream& operator<<(ostream&, HugeStruct const&)不幸的是,现有代码中已经有一个全局函数,它会转储所有内容。该函数在HugeStruct的头文件中声明并在相应的源代码中实现。

有没有办法只在测试源中覆盖该函数而不让编译器和/或链接器抛出一个合适的?它是用 GCC 4.8.5 编译的。

编辑

是的,我可以使用一些解决方法。

我可以使用打印功能(如评论中所建议的那样),但我喜欢链接<<运算符的便利性。

我可以编写一个std::string out(HugeStruct const&)函数,将字段输出到字符串并使用os << out(hs). 这就是我目前所做的,但感觉像是一种迂回的方式。

不过,我觉得这个问题在一般情况下很有趣。

标签: c++c++03gcc4.8

解决方案


如果您可以修改标头,以真正覆盖实现,您可以:

  • 标记ostream& operator<<(ostream&, HugeStruct const&)为内联
  • ostream& operator<<(ostream&, HugeStruct const&)在 cpp 中实现
  • 确保你的新实现的 cpp 在链接命令中的旧目标文件之后

这是如何工作的:

  • inline告诉链接器在找到多个定义时不要抱怨
  • C++ 标准说,如果你按照我说的去做,这是未定义的行为。
    • 这意味着如果你这样做,程序员(你)不能期望一个正确的程序
    • 实际上,(全部?)链接器从左到右处理符号并覆盖实现

我不推荐这个:) 该out功能更安全。

我看到的另一种选择是使用重载解析:您必须确保您的本地operator<<比提供的库更匹配。

您可以通过例如从ostream您在测试文件中使用的派生来做到这一点。在这里,我将假设您使用std::cout.

struct TestCout: public std::ostream{
// ...
};

TestCout& operator<<(TestCout& os, HugeStruct const&);

TestCout tcout;
tcout << huge_struct;

推荐阅读