0

How does one correctly typecast a parent class as a child class in C++?

For example, if I have two classes,

  Atom   ->   Cu
(Parent)    (Child)

and I've identified that I have an Atom a that is actually an instance of Cu, then how to I typecast a to a Cu object?


What I've tried so far:

Cu c = (Cu) a
-> No matching conversion for C-style cast from 'Atom' to 'Cu'

Cu c = Cu (a)
-> No matching conversion for functional-style cast from 'Atom' to 'Cu'

Cu c = static_cast<Cu>(a)
-> No matching conversion for static_cast from 'Atom' to 'Cu'

Cu c = dynamic_cast<Cu*>(&a)
-> 'Atom' is not polymorphic

Edit: A (rough) solution

Here's a piece of working code that accomplishes what I needed:

// Overrides Atom::equals(Atom* other)
bool Cu::equals(Atom* a) {
    // checks to see if a is a Cu pointer
    if(other->getID() == "Cu") {
        // If so, typecasts it
        Cu* c = (Cu*) a;
        // Checks functions specific to Cu atoms
        ...
    }
}

Edit 2

I've marked this question as a duplicate because 1) The best solution I've read involves "virtual functions", and 2) The question that this question now redirects to mentions them and explains why they are useful.

NcAdams
  • 2,521
  • 4
  • 21
  • 32
  • 1
    "'Atom' is not polymorphic" makes me curious -- can you include declarations of Atom and Cu? – Matt Olson Jul 14 '15 at 20:22
  • 3
    I'm curious as to why you do not [learn the language](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list)? – Lightness Races in Orbit Jul 14 '15 at 20:25
  • That solution is a very bad idea. Very very bad idea. Even if `other` is `a`. – user4581301 Jul 14 '15 at 20:45
  • @user4581301 Can you explain why? What should I do instead? – NcAdams Jul 14 '15 at 20:52
  • 1
    Also, I have decided to mark this as a duplicate as suggested because the answers given to the other question were as/more helpful than the ones I've found here. The best answer seems to involve virtual functions. – NcAdams Jul 14 '15 at 20:58
  • Rats. Too slow. There's a neat trick you can pull with [std::shared_ptr](http://en.cppreference.com/w/cpp/memory/shared_ptr) and [std::dynamic_pointer_cast](http://en.cppreference.com/w/cpp/memory/shared_ptr/pointer_cast) that does almost what you want and gives you Java-like scope. I suggest looking them up. – user4581301 Jul 14 '15 at 21:23
  • But yes, virtual functions is best. It keeps the client from knowing too much about the subclasses. But really do look at shared_ptr. Save you a lot of grief. – user4581301 Jul 14 '15 at 21:24

4 Answers4

3

I've identified that I have an Atom a that is actually an instance of Cu

This is literally never true in C++.

So…

how [do] I typecast a to a Cu object?

…you can't.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • 1
    It's possible in Java, which is similar. What's different? Clarification – NcAdams Jul 14 '15 at 20:27
  • 2
    @NcAdams: Aside from almost everything about the language? Nothing. Instead of trying to write Java in C++, I propose [learning C++](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). Good luck! – Lightness Races in Orbit Jul 14 '15 at 20:27
  • 1
    @NcAdams It's possible in Java because the great secret of Java is damn near everything is actually a pointer. This is not true in C++. C++ gives you the choice of using a pointer or not. `Atom a` does not define a pointer, therefore a cannot be anything but an instance of Atom. To define a pointer to Atom, you need `Atom * a` Then you can assign a pointer to Cu to a. Then you can use dynamic_cast to get your Cu back from a. – user4581301 Jul 14 '15 at 20:40
3

Dynamic casts from parent to child are only valid at the pointer level. Since a variable declared as Cu var; allocates exactly enough space for a Cu object, it can't fit a Atom or something else. However, a Cu* var; allocates room for a pointer object, which could technically be a pointer to anything, so after verifying that an object of type Atom* is in fact a pointer to a Cu, you can safely dynamic_cast<Cu*> the value. You can read about dynamic_cast in detail here, in particular the part about what happens if the cast fails.

Silvio Mayolo
  • 62,821
  • 6
  • 74
  • 116
1

You can only cast pointers to derived class objects. Not the object types themselves.

Your last try is the closest to this (you effectively cast a pointer to the parent class to a pointer to the child class) but I guess the compiler detects that the object cannot be polymorphic (which is the case if you declare Atom a on the heap)

Atom * a = new Cu;
Cu * c = dynamic_cast<Cu*>(a);
galinette
  • 8,896
  • 2
  • 36
  • 87
  • Ew, no, don't manually allocate things and assign them to raw pointers. – Lightness Races in Orbit Jul 14 '15 at 20:26
  • I'm suppose you are mentionning smart pointers... But this would make the examples more complicated and this is not related to the question. – galinette Jul 14 '15 at 20:28
  • It's 100% "related". When you write an answer, you are _teaching_ and, as such, you have a certain responsibility. We are in 2015, not 1970: you are doing people a disservice by starting them off with error-prone, unsafe, antiquated mechanisms that are only required for expert fine tuning. Start with smart pointers, teach raw crap later. – Lightness Races in Orbit Jul 14 '15 at 20:30
  • If you want smart pointers everywhere and no fine tuning, use python. – galinette Jul 14 '15 at 20:35
  • 2
    TIL writing sensible code that makes the most of standard features and is as provably correct as possible .... is only allowed in Python. – Lightness Races in Orbit Jul 14 '15 at 20:40
0

A dog is always an animal,but the animal is not always a dog. a child class can have variables and/or methods that parent class doesn't have.I believe you could cast this using pointers.

ESipalis
  • 381
  • 4
  • 17
  • Yes you can cast it with pointers. If you use the right kind of cast, the compiler won't even complain. That doesn't mean it will do any good. As you noted, the animal doesn't have the dog parts and accessing dog parts on an animal will certainly end in disaster. – user4581301 Jul 14 '15 at 20:32