user2747939
user2747939

Reputation: 43

C++ cast pointer to pointer to derived to pointer to pointer to base example

I have a table of pointers to derived classes. The program uses a lot of small classes that use entries in those tables. Periodically, all those small classes have to be exchanged, with purpose that they use data in a different class in the table, but they only use the base class data. So those small classes use pointers to entries of the table, but those pointers are actually pointers to pointers to the base class. In isolation, it's this, and the below works in gcc 4.8.2 (the real thing has complex classes; this is just an example)

#include <iostream>

class Base {public: int i;};
class Derived : public Base {public: int j;};

int main() {

  Base **b;
  Derived *table[2];

  table[0] = new Derived; table[0]->i = 1; table[0]->j = -2;
  table[1] = new Derived; table[1]->i = 4; table[1]->j = -5;

  b = reinterpret_cast<Base**>(&(table[0]));
  std::cout << "first: " << (**b).i << " " << "\n";
  b = reinterpret_cast<Base**>(&(table[1]));
  std::cout << "second: " << (**b).i << " " << "\n";

  {Derived *temp; temp = table[0]; table[0] = table[1]; table[1] = temp;}

  b = reinterpret_cast<Base**>(&(table[0]));
  std::cout << "first switched: " << (**b).i << " " << "\n";
  b = reinterpret_cast<Base**>(&(table[1]));
  std::cout << "second switched: " << (**b).i << " " << "\n";
}

There is no way that the table can ever get corrupted: it always will contain pointers all to exactly the same derived class type, so in theory they can all be exchanged. The classes that use the table will only ever use base class data. If reinterpret_cast is replaced by either dynamic_cast or static_cast then the compiler complains. Now, this is all fine, except for admonitions like this: "...which on most cases results in code which is system-specific, and thus non-portable", and other really scary and severe statements by opinionated experts who obviously know a lot.

Is the above a reasonable and safe use of reinterpret_cast?

Upvotes: 0

Views: 97

Answers (1)

John Dibling
John Dibling

Reputation: 101456

Neither safe nor reasonable.

First a bit of a rant. reinterpret_cast is a broadswoard. A weapon of last resort. It is not safe. It is not friendly. It will not protect you from yourself. It should not be your go-to tool of choice. You should not just bang reinterpret_cast in there if static_cast doesn't "work" and you don't understand what the compiler is telling you. Instead, you should first try to understand the compiler's error messages, and then fix the actual problem.

End of rant. Now in your case:

b = reinterpret_cast<Base**>(&(table[0]));

table is an array of pointer-to-Derived. So you are trying to cast from a pointer-to-pointer-to-Derived to a pointer-to-pointer-to-Base. What you should do instead is cast a pointer-to-Derived to pointer-to-Base, like this:

Base* b = static_cast<Base*>(table[0]);

And then use it:

std::cout << "first: " << (*b).i << " " << "\n";

But since Derived is a direct descendant of Base, you don't even need an explicit cast. This would work just fine:

Base* b = table [0];

Even better still, since you don't really need a pointer, why not just grab a reference instead?

  Base& b = *table[0];
  std::cout << "first: " << b.i << " " << "\n";

Upvotes: 4

Related Questions