Java 的 instanceof 的 C++ 版本是什么? : 检查,而不是铸造
what is the C++ version of Java's instanceof? : checking, not casting
我目前正在进行一个学校项目,我必须将 "translate" 一个 Java 程序转换为 C++。
该程序模拟媒体库并使用继承。基本上,您有一个可以向其中添加项目的媒体库。您可以添加的不同种类的项目是书籍、电影和音乐专辑。
我有一个 class 库,它主要创建了一个实例,并且有一个容器来容纳我的所有项目。 Item 是 superclass,Book、Movie 和 MusicAlbum 是其派生的 classes.
这里是我在从 Java 转换为 C++ 时遇到问题的地方:
我的导师提供了 "Main.cpp",我必须以此为基础编写程序的其余部分。我不允许修改它或分配无效。但是,"Main.cpp" 呼叫
cout << item << endl;
每次将项目添加到媒体库时。因此,这当然会将其发送到 Item.cpp ,我已经在其中覆盖了 << 运算符。
现在,在编写输出数据的代码之前,我必须能够弄清楚 "item" 是书、电影还是 MusicAlbum,因为这些东西中的每一个都需要打印不同。
在我的 Java 程序中,我写了这样的东西:
if(item instanceof Book){
System.out.println((Book) item); // I overrode "toString" in Book.Java
}
elseif(item instanceof Movie){
System.out.println((Movie) item); // overwrode "toString" in Movie.java
}
else
{
System.out.println((MusicAlbum) item; // overrode "toString" in MusicAlbum.java
如您所见,我使用 instanceof 来确定它是哪种类型的项目,然后在覆盖所有派生的 class' 之后将项目转换为该派生类型,然后将其传递给 println s "toString" 方法。
我不知道如何在 C++ 中执行此操作。我在 Whosebug 和其他论坛上查看了大量类似的问题,他们要么建议我尝试过但没有用的东西,要么告诉你如何将项目转换为派生类型,而不是如何 -check - 它是哪个派生类型而不首先实际更改它。
如果有人了解这在 C++ 中的工作原理,我将不胜感激。谢谢。
您会倾向于使用 dynamic_cast
运算符。
Book* book = dynamic_cast<Book*>(item);
if (book != nullptr) {
cout << book->toString() << endl;
}
还有 typeid(item)
会给你一个 type_info
结构,你可以在其中进行比较,但更有效的方法是执行类型转换。即使您要求不进行类型转换,C++ 也不是 Java - 您不应期望使用相同的编程方法。类型转换只是在 C++ 中执行此操作所需的方式。
通过使用 dynamic_cast<T>
,您可以尝试转换为派生的 class 指针。如果它成功了,那就是正确的类型。如果它失败了,那么它就不是。
if( dynamic_cast<Book*>(item) ) { // stuff }
C++ 确实提供了有限的编译时间方法来检查某些事情。例如,您可以检查某物是否是派生的 class
std::is_base_of<base, derived>
还有std::is_same<type1, type2>
问题是这些是编译时分辨率。运行时多态性自然意味着在 运行 之前你无法真正知道你的具体类型是什么。
编辑:添加一些可能对您的情况更有用的信息。
第 cout << item << endl;
行,据我所知,您所做的并不能解决您的问题。动态类型识别无论如何都是糟糕的设计,你应该避免它。
不,在这种情况下您需要利用多态性。您需要将 operator<<
设为虚拟。您的子classes 将有自己的打印数据的方式。
当cout << item << endl;
被调用时,你不需要弄清楚类型。将为您进行 vtable 查找,您将获得所需的行为。
唯一的问题是您可能需要一个介于超载和免费 operator>>
之间的中间人。本质上你会有一个像我提到的虚拟运算符,但你需要一个重载来确保它被正确调用,因为它是一个 class 成员而不是一个自由函数。
Look here for details
我目前正在进行一个学校项目,我必须将 "translate" 一个 Java 程序转换为 C++。
该程序模拟媒体库并使用继承。基本上,您有一个可以向其中添加项目的媒体库。您可以添加的不同种类的项目是书籍、电影和音乐专辑。
我有一个 class 库,它主要创建了一个实例,并且有一个容器来容纳我的所有项目。 Item 是 superclass,Book、Movie 和 MusicAlbum 是其派生的 classes.
这里是我在从 Java 转换为 C++ 时遇到问题的地方:
我的导师提供了 "Main.cpp",我必须以此为基础编写程序的其余部分。我不允许修改它或分配无效。但是,"Main.cpp" 呼叫
cout << item << endl;
每次将项目添加到媒体库时。因此,这当然会将其发送到 Item.cpp ,我已经在其中覆盖了 << 运算符。
现在,在编写输出数据的代码之前,我必须能够弄清楚 "item" 是书、电影还是 MusicAlbum,因为这些东西中的每一个都需要打印不同。
在我的 Java 程序中,我写了这样的东西:
if(item instanceof Book){
System.out.println((Book) item); // I overrode "toString" in Book.Java
}
elseif(item instanceof Movie){
System.out.println((Movie) item); // overwrode "toString" in Movie.java
}
else
{
System.out.println((MusicAlbum) item; // overrode "toString" in MusicAlbum.java
如您所见,我使用 instanceof 来确定它是哪种类型的项目,然后在覆盖所有派生的 class' 之后将项目转换为该派生类型,然后将其传递给 println s "toString" 方法。
我不知道如何在 C++ 中执行此操作。我在 Whosebug 和其他论坛上查看了大量类似的问题,他们要么建议我尝试过但没有用的东西,要么告诉你如何将项目转换为派生类型,而不是如何 -check - 它是哪个派生类型而不首先实际更改它。
如果有人了解这在 C++ 中的工作原理,我将不胜感激。谢谢。
您会倾向于使用 dynamic_cast
运算符。
Book* book = dynamic_cast<Book*>(item);
if (book != nullptr) {
cout << book->toString() << endl;
}
还有 typeid(item)
会给你一个 type_info
结构,你可以在其中进行比较,但更有效的方法是执行类型转换。即使您要求不进行类型转换,C++ 也不是 Java - 您不应期望使用相同的编程方法。类型转换只是在 C++ 中执行此操作所需的方式。
通过使用 dynamic_cast<T>
,您可以尝试转换为派生的 class 指针。如果它成功了,那就是正确的类型。如果它失败了,那么它就不是。
if( dynamic_cast<Book*>(item) ) { // stuff }
C++ 确实提供了有限的编译时间方法来检查某些事情。例如,您可以检查某物是否是派生的 class
std::is_base_of<base, derived>
还有std::is_same<type1, type2>
问题是这些是编译时分辨率。运行时多态性自然意味着在 运行 之前你无法真正知道你的具体类型是什么。
编辑:添加一些可能对您的情况更有用的信息。
第 cout << item << endl;
行,据我所知,您所做的并不能解决您的问题。动态类型识别无论如何都是糟糕的设计,你应该避免它。
不,在这种情况下您需要利用多态性。您需要将 operator<<
设为虚拟。您的子classes 将有自己的打印数据的方式。
当cout << item << endl;
被调用时,你不需要弄清楚类型。将为您进行 vtable 查找,您将获得所需的行为。
唯一的问题是您可能需要一个介于超载和免费 operator>>
之间的中间人。本质上你会有一个像我提到的虚拟运算符,但你需要一个重载来确保它被正确调用,因为它是一个 class 成员而不是一个自由函数。
Look here for details