1

I'm currently in the middle of a project for school in which I have to "translate" a Java program into C++.

The program emulates a media library and uses inheritance. Basically, you have a media library which you can add items to. The different kinds of items you can add are Books, Movies, and MusicAlbums.

I have a class Library, which main creates an instance of, and which has a container to hold all of my items. Item is the superclass, and Book, Movie, and MusicAlbum are its derived classes.

Here's where I'm having problems translating from Java to C++:

My instructor provided "Main.cpp", and I have to write the rest of the program based off of that. I am not allowed to modify it or the assignment is invalid. However, "Main.cpp" calls

cout << item << endl;

every time that it adds an item to the media library. So, that of course sends it to Item.cpp , where I've overridden the << operator.

Now, I have to be able to figure out whether that "item" is a Book, Movie, or MusicAlbum before I write the code for outputting its data, because each one of those things needs to be printed differently.

In my Java program, I wrote something like:

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

As you can see, I used instanceof to determine which type of item it was, and then I cast the item to that derived type before passing it to println, after overriding all of the derived class's "toString" methods.

I don't know how to do this in C++. I've looked at tons of similar questions on stackoverflow and other forums, and they all either suggest things that I tried and didn't work, or they tell you how to cast the item to the derived type but not how to just -check- which derived type it is without actually changing it first.

If anyone has any insight into how this would work in C++ I would be very grateful. Thank you.

BabaSvoloch
  • 301
  • 3
  • 20
  • You could use [`dynamic_cast`!!](http://en.cppreference.com/w/cpp/language/dynamic_cast). Although casts are usually seen as indicative of poor design and come at an added runtime cost. – Paul Rooney Dec 11 '16 at 22:31
  • Checking `instanceof` od `item` and casting it to `Book` or `Movie` or `MusicAlbum` makes no sense in your Java example. `System.out.println(item)` would call overriden method anyway. – lexicore Dec 11 '16 at 22:37
  • Thank you P.R., and thank you too @lexicore for pointing that out. This class is kind of a java/c++ hybrid and is the first time I've ever used Java so I'm a total novice – BabaSvoloch Dec 11 '16 at 22:41

2 Answers2

2

By using dynamic_cast<T> you can attempt to cast to a derived class pointer. If it succeeds, then that's the right type. If it fails, then it's not.

if( dynamic_cast<Book*>(item) ) { // stuff }

C++ does offer limited compile time ways to check certain things. For example, you can check if something is a derived class with std::is_base_of<base, derived>

There is also std::is_same<type1, type2>

The problem is that these are compile time resolutions. Runtime-polymorphism means naturally you can't truly know before run-time what your concrete types are.

Edit: Adding some info that's probably more useful to your situation.

The line cout << item << endl;, what you're doing isn't going to solve your problem from what I can tell. Dynamic type identification is bad design anyways, you should avoid it generally.

No, instead you need to take advantage of polymorphism in this case. You'll want to make operator<< virtual. Your subclasses will have their own ways of printing data.

When cout << item << endl; is invoked, you won't need to figure out the type. The vtable lookup will happen for you, and you'll get the desired behaviour.

The only catch is you might need a middleman between your overload and the free operator>>. Essentially you'll have a virtual operator like I mentioned, but you'll want an overload to make sure that's invoked correctly since it's a class member and not a free function.

Look here for details

Community
  • 1
  • 1
0

You would tend to use the dynamic_cast operator.

Book* book = dynamic_cast<Book*>(item);
if (book != nullptr) {
    cout << book->toString() << endl;
}

There is also typeid(item) which will give you a type_info structure, where you could possibly do a comparison, but the more efficient way to do it is to perform the type cast. Even though you asked to not do the type cast, C++ is not Java - you shouldn't expect the same programming method. The type cast is simply the desired way to do it in C++.

Mitch
  • 1,839
  • 16
  • 23
  • It is worth noting that some compilers will need to have RTTI (runtime type information) turned on in order to use such functionality. – Mitch Dec 11 '16 at 22:32