43

It's been a while since I have had to write C++ code and I'm feeling kind of stupid. I've written code that is similar to, but is not exactly, the code below:

class Parent { ... }; class Child : public Parent { ... }; class Factory { static Parent GetThing() { Child c; return c; } }; int main() { Parent p = Factory::GetThing(); Child c1 = p; // Fails with "Cannot convert 'Parent' to 'Child'" Child c2 = (Child)p; // Fails with "Could not find a match for 'TCardReadMessage::TCardReadMessage(TCageMessage)'" } 

I know this is supposed to be simple but I'm not sure what I'm doing wrong.

3
  • I don't understand what Factory is doing. It looks like it's returning a local variable. Is that object valid? Commented Nov 3, 2010 at 17:24
  • 4
    @John: it's returning a copy of a local object. The return is by value, so it doesn't matter whether the original dies afterwards (and of course, it does). Nothing wrong with that, other than that it's not appropriate for a factory function... Commented Nov 3, 2010 at 17:26
  • Yeah the GetThing method on the Factory class is returning a local variable. Which apparently won't do what I want. I should be using pointers instead. At least according to the answers below. Commented Nov 3, 2010 at 17:28

8 Answers 8

37

A Parent object returned by value cannot possibly contain any Child information. You have to work with pointers, preferably smart pointers, so you don't have to clean up after yourself:

#include <memory> class Factory { // ... public: static std::unique_ptr<Parent> GetThing() { return std::make_unique<Child>(); } }; int main() { std::unique_ptr<Parent> p = Factory::GetThing(); if (Child* c = dynamic_cast<Child*>(p.get())) { // do Child specific stuff } } 
Sign up to request clarification or add additional context in comments.

8 Comments

Firstly, Child *c in the cast expression. You missed the *. Secondly, a downcasting dynamic_cast requires a polymorphic type. The OP's types are not known to be polymorphic. If Parent is not polymorphic, your code won't compile.
Why would they not be polymorphic? Child inherits from Parent using the public modifier.
@Andrey: Why would someone name two non-related classes Parent and Child? @James: You missed a colon there, public static is C#, not C++ ;-)
@Mykroft: if Parent has no virtual functions, then they are not polymorphic in the sense that's relevant to dynamic_cast.
@Steve ahh that makes sense. Not that it matters to my question but the actual code I'm writing does have virtual functions.
|
10

Refer to the code snippet below:

Child* c = dynamic_cast<Child*>(parentObject); 

where, parentObject is of type Parent*

Ensure, that the "parentObject" is actually of "Child" type, otherwise undefined-behavior.

Refer for More Info

Comments

4

You can't, really. Your factory has returned a Parent object, which was constructed from the Child object c[*]. The Child part of it has already been sliced away, as it's returned to the main function. There's no way to recover it.

Perhaps you want to use pointers?

[*] Except that, Child c(); declares a function, it doesn't define an object. But this isn't your real code, and I guess your real class has constructor parameters.

1 Comment

Yeah sorry that's a correct assumption about the constructor.
1

I think the problem isn't with how your trying to do the cast, but with why you want to cast in the first place. The code makes no sense -- even if it was syntaxically valid. You;re trying to cast a "fruit" into an "apple" in a context where it's easy to prove that you don't actually have an apple. Dynamic casts and similar are only useful when you have a pointer to a "fruit" that you have reasons to thing is also an "apple".

1 Comment

This code is just an example to show the relevant parts of how my code is put together. It is not my actual production code.
0

You cannot cast the actual objects, but you can cast pointers to the objects.

To cast pointers use code like this:

Child* c = reinterpret_cast<Child*>(p); 

6 Comments

Agreed with max - reinterpret_cast could be seen as "last resort cast" :)
Why would I use dynamic_cast or reinterpret_cast instead of just saying Child *c = (child*)p;
Certainly don't use reinterpret_cast, that will give the wrong result for certain inheritance hierarchies (anywhere that multiple inheritance is involved, basically). You can use static_cast if you know that the object really is a Child (which in this case it isn't, because of the return by value), and you can use dynamic_cast if you want to test whether it is or not as part of the cast.
@Myk: Because the (type)expression syntax carried over from the C language does not make clear why you are casting. Value conversion? Some bit-magic? Going down an inheritance hierarchy? These are very different scenarios, and C++ provides different syntax to make the programmer's intent clear.
-1: To get the correct result, you need to use static_cast or dynamic_cast, as @Steve describes in his comment. It is 100% wrong to use reinterpret_cast for this.
|
0

You cannot cast an object of parent class to child class type. An object of parent class is... well, an object of parent class. Child class extends parent class, meaning that an object of parent class is generally "smaller" than an object of child class. For this reason casting (or reinterpreting) parent class as child class makes no sense whatsoever.

Explain what is it you are trying to do. Without an explanation, your question simply makes no sense.

Comments

0

You probably don't want to be casting here at all. If Parent has any abstract methods you just call them and the derived class will automatically handle them correctly.

There are times where you link relatively unrelated items together just so you can store them in a collection, either variant types or situations where different state leads to unrelated objects which are handled differently, and on those occasions you might want to cast.

I am quite surprised, by the way, that you didn't get a compiler error on GetThing() because you have declared c as a function so you are not returning a Parent.

In addition, by the way, if you copy by value you will "slice" thus:

Child c; Parent p(c); Child & c2 = dynamic_cast< Child& >(p); // throws bad_cast 

Comments

0

You can cast using Single Argument Constructor: i.e. (A parent works, A child Studies) as follows:

#include <iostream> using std::cout; class Parent { public: void goToWork() { cout<<"working\n"; // only parents work } }; class Child : public Parent { public: Child(const Parent& parentAddr){} void goToSchool() { cout<<"studying\n"; // only children studies } }; int main(void) { Child child(*(new Parent())); // here's a child working child.goToWork(); return 0; } 

you pass an child class address as parent's constructor parameter and you can use a child obj to do parent's stuff

1 Comment

Child already is a Parent, since it publicly inherits from it. There's no need to construct a Parent and pass it in Child's constructor (which in this code does nothing).

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.