【问题标题】:Is it safe to write non-virtual conditional member functions?编写非虚拟条件成员函数是否安全?
【发布时间】:2012-07-26 07:21:39
【问题描述】:
  1. 这样做[二进制]安全吗?

    struct Foo {
    
        #if __cplusplus > 199711L
            Foo( std::initializer_list<int> & list ) {
                /* ... */
            }
        #endif
    
    };
    

    我见过this topic, 但是没有回答 OP 原始问题。

  2. 有没有更好的方法来实现这种行为?

【问题讨论】:

  • “二进制安全”是什么意思?您当然必须使用完全相同的宏定义编译所有代码。
  • @KerrekSB 使用 -std=c++11 编译的库,仅在条件内联成员函数中使用 c++11 功能,如果用户未使用 - 编译其应用程序,则该库将不起作用 - std=c++11 ?
  • 就语言标准而言,它肯定是不正确的。这是关于该主题的related question of mine
  • 就语言标准而言,我认为它的格式不正确,因为语言标准根本没有解决它。如果标头的内容仅根据__cplusplus 而改变,那么就标准而言,标头的内容根本不会改变,因为__cplusplus 的值不会改变。与其他语言(包括早期版本的 C++)的互操作性超出了标准的范围。

标签: c++ oop c++11 c-preprocessor


【解决方案1】:

我假设你:

  • 已将此类代码编译到库中,一直在升级您的编译器,现在想要使用 C++11 编译您的代码(或者因为您没有代码而无法编译),或者,

  • 在 C++11 之前的库中已有代码,现在您已经升级了编译器,您希望使用上述代码并与旧库“兼容”,或者,

  • 想要在没有 C++11 的情况下编译代码并将其与使用相同编译器使用 C++11 编译的代码链接。

在每种情况下,答案都不是 C++ 问题,而是编译器 ABI 问题,因为它涉及 (i) 链接阶段是否有效以及 (ii) 类的运行时形式等. 在编译器/版本/编译器设置之间仍然有效。

因此,您需要检查您正在使用的编译器的文档,以确定它是否“二进制安全”。

注意 #1: 如果您的编译器已经(/已经)以任何方式更改了异常处理发出的代码设计、类的 RTTI 布局和/或名称修改方案,那么你的回答是,“不,这不安全。”但这些可能不是唯一的情况。

注意 #2: 如果它使用相同的编译器和不同的设置(例如,使用和不使用 C++11),那么当您排除时,从技术上讲,您违反了 ODR(一个定义规则)假设为某些模块编写代码,并在同一程序中为其他模块编写代码。在这种情况下,结果在技术上是实现定义的,但是,由于它不是虚拟的,因此它非常、非常、非常有可能与大多数编译器一起工作,前提是只使用一个编译器的一个版本。

【讨论】:

    【解决方案2】:

    它可能很好,DirectX 结构以这种方式实现,但它已经支持 C 和 C++。

    【讨论】:

    • 不确定binary 部分。
    猜你喜欢
    • 1970-01-01
    • 2021-01-31
    • 2014-01-04
    • 2012-09-27
    • 1970-01-01
    • 1970-01-01
    • 2012-09-09
    • 2018-03-18
    • 2019-04-29
    相关资源
    最近更新 更多