eta*_*ion 6 c c++ architecture software-design featuretoggle
关于功能标志/切换以及为什么要使用它们存在相当多的讨论,但大多数关于实现它们的讨论都围绕(网络或客户端)应用程序进行。如果您的产品/工件是 C 或 C++ 库,并且您的公共标头受标志影响,您将如何实现它们?
“天真的”做法并没有真正起作用:
/// Does something
/**
* Does something really cool
#ifdef FEATURE_FOO
* @param fooParam describe param for foo
#endif
*/
void doSomethingCool(
#ifdef FEATURE_FOO
int fooParam = 42
#endif
);
Run Code Online (Sandbox Code Playgroud)
您不会想运送这样的东西。
#define相同的功能标志来使事情正常工作在文件上运行预处理器来获取要分发的标头实际上并不起作用,因为这不仅会作用于功能标志,还会执行预处理器执行的所有其他操作。
没有这些缺陷的技术解决方案是什么?
由于版本控制,这种粘性最终会出现在代码库中。话题广泛,但很少有令人满意的答案。但你当然希望避免让事情变得更加困难。专注于您想要提供的兼容性类型。
仅当您需要二进制兼容性时才需要代码片段中建议的语法。它使库与客户端代码中的 doSomethingCool() 调用(不传递参数)兼容,而无需编译该客户端代码。换句话说,客户端程序员除了复制更新的 .dll 或 .so 文件之外什么都不做,不需要任何更新的标头,并且正确获取功能标志完全是您的负担。二进制兼容性很难可靠地实现,除了标志争论之外,很容易犯错误。
但您实际上谈论的是源兼容性,您确实为用户提供了更新的标头,并且他重建了代码以使用库更新。在这种情况下,您不需要功能标志,C++ 编译器本身会确保传递一个参数,它将是 42。无论是您端还是用户端,根本不需要标志。
另一种方法是提供重载。换句话说,doSomethingCool() 和 doSomethingCool(int) 函数。客户端程序员继续使用原始重载,直到他准备好继续前进。当函数体必须改变太多时,您也喜欢重载。如果这些功能不是虚拟的,那么它甚至提供链接兼容性,在某些特定情况下可能很有用。不需要功能标志。