【问题标题】:Is there a way to prevent usage of unimplemented functions during compile time?有没有办法防止在编译时使用未实现的函数?
【发布时间】:2012-11-28 15:57:39
【问题描述】:

我经常遇到像

这样的黑客攻击
//lets say this is some class that still doesnt support...
//...all the functionality that it should based on the design docs
void MyClass::MyFunction()
{
  throw std::exception("not implemented");
}

我想这是一个不好的做法,但除此之外:
有没有办法在编译期间做同样的事情,但前提是使用该函数(也就是如果它未使用,编译应该成功)。

编辑:我也对虚拟内存功能感兴趣。

【问题讨论】:

  • 如果一个函数未实现(如未声明但未定义),那么您将收到链接时间错误。在这种情况下,您的函数已实现,并且具有明确定义的行为。

标签: c++ compile-time


【解决方案1】:

如果你完全删除实现并且只有函数声明,就会出现链接器错误,这基本上是编译时间。不幸的是,链接器错误往往很丑陋且难以追踪,但在调用尚未实现的函数的情况下,我认为它们非常易于管理。

【讨论】:

  • 链接器错误基本上不是编译时。现在是链接时间。
  • 如果函数是虚函数并且某些基类有实现怎么办?
【解决方案2】:

如果是非虚函数,可以简单的把定义注释掉。

如果它是在基类中声明的虚函数,那么您无法在编译时控制调用,那么您唯一的选择就是一些运行时错误或异常。

【讨论】:

    【解决方案3】:

    老问题,但仍然...

    我为此使用了几个简单的助手。它会给出一个相当可读的错误链接时间:

    // Not implemented is not implemented :-)thing, it'll break:
    struct NotImplHelper { static void notimplemented(); };
    #define notimplemented() NotImplHelper::notimplemented();
    #if defined(DEBUG) || defined(_DEBUG)
    #define notimplementedvirtual() throw std::exception();
    #else
    #define notimplementedvirtual() static_assert(false, "You should implement virtual function calls before moving to production.");
    #endif
    

    用法:

    //lets say this is some class that still doesnt support...
    //...all the functionality that it should based on the design docs
    void MyClass::MyFunction()
    {
        notimplemented();
        // or notimplementedvirtual() if MyFunction() is virtual... 
    }
    

    理由:

    恕我直言,如果您在程序中使用了一个函数,它应该是可用的。当您尝试编译尚未实现的东西时,它应该给出编译时或链接时错误。

    F.ex.,在 MSVC++ 中,这将给出:

    1>Test.obj : error LNK2019: unresolved external symbol "public: static void __cdecl NotImplHelper::notimplemented(void)" (?notimplemented@NotImplHelper@@SAXXZ) referenced in function "[blahblahblah]"
    

    请注意,“引用函数”在 MSVC++ 中。我还没有在其他编译器中测试过它。

    对于未实现的虚函数调用,唯一的选择就是抛出异常。在开发时没有在调试器中实现这些是可以的 - 但是,当事情变得严重时,这些可能会被您的程序调用,因此它们应该可用。 static_assert 确保后者。 (所以:结合任何持续集成包,它基本上都会失败。)

    显然大多数人会不小心混淆notimplementednotimplementedvirtual。实际上这不是什么大问题:一个简单的解决方案是始终使用前者,除非您想摆脱错误,因为它是 WIP。

    【讨论】:

      【解决方案4】:

      我能想到的最简单的解决方案是注释未实现的函数。

      也许不是你想的那样,但是如果有任何东西试图使用它,这样做会产生一个编译时错误,并且生成的代码应该与一个通常被优化掉的空函数相同。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-02-15
        • 1970-01-01
        • 1970-01-01
        • 2023-03-15
        • 2020-10-10
        • 1970-01-01
        相关资源
        最近更新 更多