在C 中没有与此等效的方法,尝试在C
中进行Java编程毫无意义。话虽如此,我将从尝试尽可能模仿陈述的赋值特征和精神的角度来探讨这一问题。我建议的每种方式都有缺点和局限性。前两个不是真正的惯用C
++,但是了解它们很重要,以了解后两个解决了哪些问题。
1. C样式的void指针。
让我从最基本,最有用的空指针开始:
void* foo = new Foo();
可以从new运算符将任何东西分配给void指针,因为new,placement
new等总是返回void指针。缺点应该是显而易见的:丢失有关所指向对象的类型信息。首先,C
++缺少反射或任何查询对象的方法。您必须将类型信息放在脑海中,并使用来回转换来实际使用它。由于没有任何类型安全的方法可以从void指针进行强制转换,因此可能会引起欢喜。
如果这是函数的返回类型:
void* foo = some_function( _arg0 );
使用您的代码的任何作者都需要弄清楚 应该 怎么做。不幸的是,通常情况下它们应该发生什么,而您(作者)认为应该从函数返回的结果却大不相同。
2. C型联合
如果你想自己限制其支持的,而不是无限类型java.lang.Object中可以处理则有N种类型的工会。
只要它们是POD数据类型,它们就可以
在同一存储空间上保存一组预定义的值类型。工会缺乏两个非常重要的事情:知道分配哪个值的能力和持有非POD类型的能力。这将它们完全排除在具有任何功能(例如)的任何对象中
std::string。
为了澄清以上内容的实际含义:
union myType{ int a; char b[4];};如果我在“ myType”的实例的“ b”部分中设置了第一个字符,那么我还将int的第一个字节设置为相同的值。在C
中,它们实际上仅对内存黑客和极低级别的编程(例如嵌入式等)有用。它们不是惯用的C 。
3. Boost :: Any
现在,如果您真正想要“我可以拿任何东西”,请使用Boost ::
Any。这可以容纳任何对象而不会破坏很多有用的类型信息。Boost文件的目的比我要好。取自Any的简介部分:
有时需要泛型(从一般意义上来说,与基于模板的编程相反):真正可变的变量,可容纳许多其他更特定类型的值,而不是C ++的常规严格和静态类型。
可以考虑解决与空指针相关的许多问题,例如丢失有关所包含对象的信息以及安全地转换为正确类型的能力。
4. Boost :: Variant
Boost ::
Variant解决了与union相同类型的问题,而不会丢失对象信息。此外,它可以与非POD类型的对象一起使用。如文档所述,最好:
典型的解决方案以动态分配对象为特征,这些对象随后通过一个通用的基本类型(通常是虚拟基本类Hen01或更危险的是void
*)进行操作。然后可以通过多态下垂构造(例如dynamic_cast,boost :: any_cast等)来检索具体类型的对象。但是,由于以下原因,此类解决方案极易出错:
- 在编译时无法检测到向下转换错误。因此,不正确使用向下构造会导致仅在运行时才能检测到错误。
2.
新的混凝土类型的添加可以忽略。如果将新的具体类型添加到层次结构中,则现有的向下转换代码将继续按原样工作,而完全忽略了新类型。因此,程序员必须在多个位置手动定位和修改代码,这通常会导致难以找到运行时错误。
编辑:
重新整理以显示我回答OP时的想法和原因。我也在下面谈到了评论。



