【问题标题】:Different class version with same name in different files不同文件中具有相同名称的不同类版本
【发布时间】:2011-10-06 12:56:47
【问题描述】:

我在两个不同的文件(A.cpp、A.h、B.cpp、B.h)中有同一个类的两个版本,在所有文件中,该类具有相同的名称但内部实现不同。

我的想法是从一个版本切换到另一个版本,只需在#include 处更改 .h 文件的名称,因此我不必更改代码中的任何其他内容(两个版本的方法具有相同的签名和相同的属性)

A.h 和 B.h 永远不会同时包含。

问题是无论我使用什么包含文件总是执行一个版本。我知道当我包含 B.h 时,至少它会被编译(通过放置一些代码错误,它们会在编译时显示)

这可以吗?或者这违反了 C++ 的一些规则?我认为这不应该违反一个定义规则,因为我没有同时使用 A.h 和 B.h。

【问题讨论】:

  • 问题是如何链接目标文件?仅仅调整包含是行不通的。
  • 如果你包含 B.h 并链接到 B.o,你应该没问题。你怎么链接?但是如果类的 api 是一致的,那么 A.h 和 B.h 应该是相同的;为什么它们不同?
  • 你包含的头文件并不像你链接的实际代码那么重要。
  • 你这样做很辛苦,我会定义一个抽象类并从中继承两个类。

标签: c++ file class


【解决方案1】:

解决方案是不要将旧文件链接到最终的可执行文件中。这样只有新的实现可用。

【讨论】:

    【解决方案2】:

    我经常做的是将版本修改为命名空间,然后使用它。 大致如下:

    namespace Xyz_A {   //  In A.h
    //  Define version A
    }
    
    namespace Xyz = Xyz_A;
    

    ;在B.h 中,请改用_B

    这样,你会在你的程序中写Xyz::...,但是外部 符号将包含Xyz_AXyz_B。但在我的 选项,这实际上更像是一种防止错误的保护。我会安排 我的 makefile 中的东西,以便在 A.hB.h 之间切换 还会导致可执行文件链接到适当的库,并且 不反对对方。

    【讨论】:

    • 确实,将两个版本放在不同的名称空间中可以让您将两个版本的类编译成同一个可执行文件。除了简化构建过程之外,它还允许您编写版本之间的运行时切换(这对于根据配置文件或命令行中的设置选择类版本可能很有用)。
    • @AndréCaron 您不能在运行时在命名空间之间切换。命名空间纯粹是一种编译和链接时间解析。 (我使用不同的命名空间来检测错误:针对一个版本进行编译,然后动态或以其他方式针对另一个版本进行编译。)
    • 当然不能。但是,您可以编写一个简单的开关,例如return (use_version_A?:new Xyz_A::Foo():new Xyz_B::Foo());。如果您在构建过程中将它们切换出来,则无法做到这一点。
    【解决方案3】:

    如果头文件相同,只有一个头文件和两个不同的实现文件会更容易。这会将您的问题减少到仅与正确的目标文件链接。如果您的标头出现分歧,这也减少了出现细微错误的机会。

    当然,更好的解决方案是不依赖于构建系统,而是使用语言工具在编译时更改代码,例如模板。

    【讨论】:

    • 为什么模板会更好?版本管理是最好由构建系统管理的典型案例。
    • @James 我不认为他有两个不同的版本,但实际上只是接口的两个不同实现。
    【解决方案4】:

    您需要加载正确的库以匹配头文件。

    我建议研究代理设计模式,这样您就可以同时包含 A 类和 B 类。然后您可以使用代理来选择在运行时使用哪个类函数。

    http://en.wikipedia.org/wiki/Proxy_pattern

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-11
      • 1970-01-01
      • 2020-03-30
      • 1970-01-01
      相关资源
      最近更新 更多