C++是什么?相当于 java.lang.Object x = new Foo()?
java.lang.Object x = new Foo()
的 C++ 等价物是什么?
What is the C++ equivalent of java.lang.Object x = new Foo()
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
C++ 中没有类似的东西,尝试用 C++ 编写 Java 程序是没有意义的。话虽这么说,我将从尝试尽可能多地模仿作业特征和声明精神的角度来处理这个问题。我建议的每种方法都有缺点和局限性。前两个并不是真正惯用的 C++,但了解它们以了解后两个解决了哪些问题很重要。
1. C 风格的 void 指针。
让我从最基本且最无用的 void 指针开始:
任何东西都可以从 new 运算符分配给 void 指针,因为 new、placement new 等总是返回一个 void 指针。缺点应该是显而易见的:丢失有关所指向对象的类型信息。其一,C++ 缺乏反射或任何询问对象的方法。您必须将类型信息牢记在心,并通过来回转换才能实际使用它。由于没有类型安全的方法可以从 void 指针进行转换,因此可能会引发欢闹。
如果这是函数的返回类型:
任何使用您的代码的作者都需要弄清楚应该发生什么。不幸的是,很多时候他们应该发生的事情和你,作者,认为应该从函数返回的东西是非常不同的。
2. C 风格联合
如果您想将自己限制为支持的 N 类型,而不是 java.lang.Object 可以处理的无限类型,那么有 联合。它们可以在同一内存空间上保存一组预定义的值类型,只要它们是 POD 数据类型即可。联合缺少两个非常重要的东西:知道分配了哪个值的能力以及保存非 POD 类型的能力。这完全排除了它们与具有任何功能的任何对象的使用,例如 std::string 。
为了澄清上面的实际含义:
如果我在“myType”实例的“b”部分中设置第一个字符,那么我还将 int 的第一个字节设置为相同的值。在 C++ 中,这些实际上只对内存黑客和极低级编程有用(想想嵌入式等)。它们不是惯用的 C++。
3. Boost::Any
现在,如果你真的想要“我可以容纳任何东西”,那么使用 Boost::Any。这可以保存任何对象,而不会破坏大量非常有用的类型信息。 Boost 文档比我更清楚地阐述了它们的目的。摘自 Any 的介绍部分:
考虑 Any 解决与 void 指针相关的许多问题,例如丢失有关所包含对象的信息以及安全地转换为正确类型的能力。
4. Boost::Variant
Boost::Variant 在不丢失对象信息的情况下解决与联合相同类型的问题。此外,它可以与非 POD 类型的对象一起使用。正如文档所述:
编辑:
重新组织以显示我回答OP时的想法和原因。我还在下面发表了评论。
There is no equivalent of this in C++ and it would be pointless to attempt to program Java in C++. That being said, I will approach this from a perspective of attempting to mimic as much of the assignment characteristics and spirit of the statement as possible. Each way I will suggest has downsides and limitations. The first two are not truly idiomatic C++ but it's important to know about them to see what problems the last two solved.
1. C-style void pointers.
Let me start with the most basic and least useful, a void pointer:
Anything can be assigned to a void pointer from the new operator as new, placement new and the like always return a void pointer. The downsides should be obvious: loss of type information about the object pointed at. For one, C++ lacks reflection or any means of interrogating the object. You'd have to keep the type information in your head and use casting back and forth to actually use it. Since there's no type-safe way to cast from a void pointer, hilarity could ensue.
If this were a return type from a function:
any author using your code would need to figure out what should happen. Unfortunately, often times what they thing should happen and what you, the author, think should be returned from a function are very different.
2. C-style Unions
If you want to restrict yourself to N types which are supported instead of infinite types that java.lang.Object can handle then there are unions. These can hold a set of pre-defined value types on the same memory space as long as they are POD datatypes. Unions lack two very important things: the ability to know which value was assigned and the ability to hold non-POD types. This completely rules them out for use with any object with any sort of functionality such as
std::string
.To clarify what the above actually means:
If I set the first char within the "b" portion of an instance of "myType" then I also am setting the first byte of the int to that same value. In C++ these are really only useful for memory hacks and extremely low level programming (think embedded and the like.) They are not idiomatic C++.
3. Boost::Any
Now, if you truly want a "I can hold anything" then use a Boost::Any. This can hold any object without destroying a lot of type information which is so useful. The Boost documents state better than I in their purpose. Taken from the introduction section of Any:
Think of Any solving many of the problems associated with a void pointer, such as loss of information about the contained object and the ability to safely cast to proper types.
4. Boost::Variant
Boost::Variant solves the same type of problem of that of a union without losing object information. Moreover it can be used with non-POD type objects. As the documentation states it best:
Edit:
Reorganized to show the what and the why of my thoughts when I answered the OP. I've also addressed comments below.
不存在与 java.lang.Object x = new Foo() 等价的直接,因为在 C++ 中,并非所有东西都是对象。但是根据您想要如何使用这些
对象
,您可以实现相同的目标。C++ 中与
java.lang.Object x = new Foo()
最接近的等效项是使用抽象基类
(ABC
)。 ABC 是一个被设计为其他类的基类的类。您可以通过为班级提供至少一个 纯虚拟成员来创建 ABC函数,并使用以下语法指定:纯虚拟成员函数通常在基类中没有实现(请参见脚注 *1)。不可能创建 ABC 的实例:
为了使用 ABC,您必须创建它的子类并实现派生类中的每个纯虚成员函数:
现在您可以创建
的实例Foo
,同时获取指向基类的指针:通常的免责声明适用于上面关于使用智能指针等的代码。为了清楚起见,我省略了这一点,但从现在开始我将使用
shared_ptr
。您还可以获得对
Foo
的Object
引用,而不必担心切片
关于析构函数和 ABC 的重要说明。当您实现 ABC 时,您通常需要在基类中拥有一个虚拟析构函数(脚注 *2)。如果您没有在基类中实现虚拟析构函数,那么当您尝试通过基类指针
删除
对象时,您将引发未定义的行为,这很糟糕。事实上,在我实现 ABC 的实际经验中,我经常发现我真正想要成为纯虚拟的唯一成员函数是析构函数。我设计的 ABC 经常有许多非纯虚拟方法,然后是一个虚拟析构函数。 IMO(有争议),这是设计 ABC 时的一个很好的起点:使 dtor 纯,并在基类中保留最少数量的非纯虚拟成员函数,并在基类中提供纯虚拟 dtor 的实现班级。当您以这种方式设计时,您会发现在实际代码中无法执行的操作,这就是您偏离此设计的时候。
脚注:
*1)基类可以为基类中的纯虚成员函数提供定义。但这不是常态,您可能这样做的原因在某种程度上超出了本文的范围。请注意,当您这样做时,标准中有一条特殊规则,规定您不得随声明一起提供定义;他们必须是分开的。像这样:
*2) 关于虚拟析构函数的规则也有例外。超出了本文的范围,但更好的经验法则是“基类析构函数应该是公共和虚拟,或受保护和非虚拟”
There is no direct equivalent to
java.lang.Object x = new Foo()
because in C++, not everything is an object. But depending on how you want to use theseObject
s, you can accomplish the same goal.The closest equivalent to
java.lang.Object x = new Foo()
in C++ is the use ofAbstract Base Classes
(ABC
). An ABC is a class that is designed to be a base class to other classes. You create an ABC by giving your class at least one pure virtual member function, and you specify that by using this syntax:A Pure Virtual member function typically has no implementation in the base class (See footnote *1). It is not possible to create an instance of an ABC:
In order to use an ABC, you must create a subclass of it and implement each and every pure virtual member function in the derived class:
Now you can create an instance of
Foo
, while getting a pointer to the base class:The usual disclaimers apply in the above code about using smart pointers etc. I omitted this for clarity, but from now on I'll use
shared_ptr
.You can also get an
Object
reference toFoo
without having to fearslicing
An important note about destructors and ABCs. When you implement an ABC, you often need to have a virtual destructor in the base class (Footnote *2). If you don't implement a virtual destructor in the base class, then when you try to
delete
an object through the base class pointer, you'll evoke undefined behavior, and this is bad.In fact, in my real-world experience in implementing ABCs I often find that the only member function that I really want to be pure virtual is the destructor. ABCs I design often have many virtual methods that are not pure and then one virtual destructor. IMO (debatable), this is a good starting point when designing an ABC: Make the dtor pure, and keep a minimal number of non-pure virtual member functions in the base class, and provide an implementation for the pure virtual dtor in the base class. As you design this way you'll find things you can't do in your actual code, and that's when you deviate from this design.
Footnotes:
*1 ) Base classes can provide a definition for a pure virtual member function in the base class. But this is not the norm, and the reasons you might do this are somewhat beyond the scope of this post. Note that when you do this there is a special rule in the Standard that says you may not provide the definition along with the declaration; they must be seperate. Like this:
*2) There are exceptions to the rule about having virtual destructors. Beyond the scope of this article, but a better rule of thumb is "A base class destructor should be either public and virtual, or protected and nonvirtual"
没有等效的,因为 Java 从托管堆中分配对象,而 C++ 在非托管内存中分配它们。 Java 中的对象由 JVM 使用标记和清除来跟踪自动垃圾回收,而 C++ 则需要显式释放所有内存。
运行时环境根本不同,由于相似的语法而进行类比是一个陷阱。
There is no equivalent because Java allocates objects from a managed heap, C++ allocates them in unmanaged memory. Objects in Java are tracked by the JVM for automatic garbage collection using mark-and-sweep, whereas C++ requires explicit release of all memory.
The runtime environments are fundamentally different, drawing analogies due to similar looking syntax is a trap.