1

I have this class structure where classD and classE grandparents are the same

classB : classA; classC : classA; classD : classB; classE : classC; 

then I have a function which requires to pass an object classF

classF : classA; function(classF *func); 

Is it possible to pass an object of type classD and classE to function which requires type classF? sample implementation as below: Is it possible to just cast both to their common grandparent?

classD *d = new classD(); classE *e = new classE(); classA *func = (classA*)d; function(func); func = (classA*)e; function(func); 
5
  • 1
    Show real code please. For casting you should use static_cast in this case. Commented Oct 4, 2016 at 7:58
  • 3
    If classF is required, you need to serve classF. If classA provides everything that is needed inside function(...), then change the parameter type accordingly. Commented Oct 4, 2016 at 8:00
  • it depends on what function does. It could call specific methods of classF. Commented Oct 4, 2016 at 8:00
  • If you want to cast classB* to classF* and use the result for anything, you are basically asking for undefined behavior. Commented Oct 4, 2016 at 8:01
  • Why not go with function(classA* func) instead? If you want it to process objects that are of classA or subclasses, then you write it to do so. If you don't want it, you don't give it objects of another type. That is basic OO. But actually I suspect that we got an XY-problem ( xyproblem.info ) here. What do you actually want to accomplish? Give us some names for your classes and the function. Whatever solution you need will have to be based on the idea and concept behind your classes. The answers talk about casting, which is of course correct, but we don't want (apple*) orange*. Commented Oct 4, 2016 at 8:26

2 Answers 2

3

No, no and another time no.

The line that simply doesn't pass muster is this:

function(func); 

This requires a downcast, i.e. - a cast from a parent class to its subclass. A downcast will not happen implicitly, which means the line will not compile (but had you provided compiling code, you would already know that). The following would compile:

function((classF*)func); 

but you shouldn't use it. A downcast's result is undefined unless that reference originally belonged to that type. So, this is okay:

classF *f = new classF(); func = (classA*) f; function((classF*)func); 

But this is not:

classB *b = new classB(); func = (classA*) b; function((classF*)func); 

Edited to add

If the downcast is performed using the dedicated C++ cast operator dynamic_cast, then the code, at run time, makes sure that the down cast is correct. So:

classF *f = new classF(); func = (classA*) f; classF *newf = dynamic_cast<classF *>(func); // Okay classB *b = new classB(); func = (classA*) b; newf = dynamic_cast<classF *>(func); // newf is now NULL 

This allows run time checking that you have not made a mistake.

Personally, I like never relying on this for actual design, only for verification. In such a case, it is better to dynamic cast references rather than pointer. Dynamic casting an incorrect pointer results in NULL. Dynamic casting an incorrect reference throws an exception:

classF *f = new classF(); func = (classA*) f; classF *newf = &dynamic_cast<classF &>(*func); // Okay classB *b = new classB(); func = (classA*) b; newf = &dynamic_cast<classF &>(*func); // Throws an exception 
Sign up to request clarification or add additional context in comments.

Comments

2

If you function want a classF pointer you should pass it a classF pointer. Your code should not even compile like this because of the function requiring a classF and you give it a classA

You can get this to compile with casting the class to classF but you should not do this. This will get you into undefined behavior land because you would basically be lying to your compiler and say "this other class is a classF pointer", which would not be true.

What you can always safely do it cast to a pointer of the base class (like you do in your example with casting to classA)

You should also switch from c-style casts to c++ style casts (like static_cast or dynamic_cast). This can also help you in your situation. With dynamic cast you can safely cast a class to a derrived class.

Like this:

class A {}; class B : public A {}; class C : public A {}; A* b-obj = new B; A* c-obj = new C; 

now both c-obj and b-objare pointers to A so we don't know anymore if they are B or C. You can check this with dynamic_cast

C* ptr = dynamic_cast<C*>(b-obj); //returns null because b-obj cannot be converted to C* C* ptr = dynamic_cast<C*>(c-obj); //does not return null 

Your code can look like that then:

func = static_cast<A*>(e); // cast to base class. //later then. classF* funcF = dynamic_cast<F*>(func); if(funcF != NULL) { function(func); } 

the c-style casts can have some side effects you may not like. So strongly recommend to familiarize yourself with c++ casts.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.