在C++类成员函数中使用#ifdef守卫是否安全?
实际上(使用GCC作为 g++ -O2 -fverbose-asm -S
查看生成的汇编代码),你提出的方法是安全的。理论上不应该这样做。
然而,还有另一种实用的方法(在
Qt和
FLTK中使用)。在“隐藏”的方法中使用一些命名约定(例如,记录所有这些方法的名称都应该像
int dontuseme(void)
那样带有
dontuse
),并编写
GCC插件以在编译时发出警告。或者在构建过程中(例如在您的
Makefile
中)使用一些聪明的
grep(1)。
另外,您的GCC插件可以实现新的#pragma
或函数属性,并警告不当使用这些函数。
当然,您也可以(巧妙地)使用private:
,最重要的是,在您的构建过程中生成C++代码(使用类似SWIG的生成器)。
实际上,你的#ifdef守卫可能是无用的。我不确定它们是否会使C++代码更易读。
如果性能很重要(使用GCC),请在编译和链接时同时使用-flto -O2标志。
另请参见GNU autoconf-它使用类似的基于预处理器的方法。
或者使用其他预处理器或C++代码生成器(GNU m4、GPP、自己使用ANTLR或GNU bison制作的)来生成一些C++代码。就像Qt使用其moc一样。
所以我的观点是你想做的事情是无用的。
你没有说出来的目标可以通过许多其他方式实现。例如,生成类似于_5yQcFbU0s
(在RefPerSys中完成)的“随机”C ++标识符(或C标识符,或ObjectiveC ++名称等),那么名称的意外碰撞就非常不可能。
在评论中,您说:
“否则,我必须在头文件中对所有Objective-C类型使用void *,但这样我会失去强类型”
不,您可以
生成一些
inline
C ++函数(使用
reinterpret_cast
),以再次获得强类型。 Qt也这样做!
FLTK或
FOX或
GTKmm也会生成C ++代码(因为GUI代码很容易生成)。
我的想法是使用OBJC宏来保护带有Objective-C类型的方法。如果您使用这些宏生成一些C++或C或Objective C代码,这将非常有意义。
我怀疑如果使用成员函数指针或虚函数,这很可能会出现问题。实际上,如果您生成看起来随机的C++标识符,它不会出错。或者只需在生成的C++代码(或生成的Objective C++代码或生成的C代码)中记录命名约定(如
GNU bison或
ANTLR所做的),请注意,像
GCC这样的编译器今天(2021年)内部使用多个C++代码生成器。因此,生成C++代码是一种常见的做法。实际上,如果您小心地生成“随机”标识符(可以在构建时将它们存储在某个
sqlite数据库中),名称冲突的风险很小。
还必须在代码中添加不美观的静态转换
如果生成的代码是丑陋的,则这些转换并不重要。
例如,RPCGEN 和 SWIG - 或者 Bisoncpp- 会生成丑陋的 C 和 C++ 代码,但它们非常有效(也许还有一些专有的 ASN.1 或 JSON 或 HTTP 或 SMTP 或 XML 相关的内部代码生成器)。
头文件包含在纯C++和Objective C++的翻译单元中。
另一种方法是生成两个不同的头文件......
一个用于C ++,另一个用于Objective C ++。 SWIG 工具可能会启发您。当然,您的(C或C ++或Objective C)代码生成器将发出随机的标识符....就像我在Bismon中做的那样(生成随机的C名称,例如moduleinit_9oXtCgAbkqv_4y1xhhF5Nhz_BM
)和RefPerSys(生成随机的C ++名称,如rpsapply_61pgHb5KRq600RLnKD
...); 在两个系统中,意外的名称冲突非常不可能发生。
当然,原则上使用#ifdef
守卫不安全,正如这个答案中所解释的那样。
PS. 几年前,我曾经在GCC MELT上工作,为一些旧版本的GCC编译器生成了数百万行的C++代码。今天-2021年-您几乎可以直接使用asmjit或libgccjit来生成机器码。部分求值是一个很好的概念框架。
private:
不可以做到吗?你要把它们隐藏在谁的视线之外,因为拥有该文件的任何人都可以读取它? - Aganju