Multiple inheritance and cross-class type casting

Please support our C++ advertiser: Intel Parallel Studio Home
Reply

Join Date: Nov 2008
Posts: 21
Reputation: axfv is an unknown quantity at this point 
Solved Threads: 3
axfv axfv is offline Offline
Newbie Poster

Multiple inheritance and cross-class type casting

 
0
  #1
May 4th, 2009
I have classes A1, A2, B, and C. A2 inherits from A1. C inherits from A2 and B, and its constructor initializes all B, A2, and A1 variables.

As a tree, it looks like this:

  1. C
  2. / \
  3. B A2
  4. |
  5. A1

I have a function Foo that takes a parameter pointer P of type B*, but the only parameters passed will be of type C* (and thus their objects will have all B, A2, and A1 variables initialized)

Inside Foo, I can type cast my P into A2* or A1* pointers, and I'm able to use those functions. The A2 and A1 functions run without complaining, but none of the A2 or A1 variables get recognized (when I debug they're all uninitialized), which leads to bugs.

Can somebody explain why this happens and what I can do to fix it (I can't change Foo's parameter type), or direct me to a source where I can read more about it?

EDIT: when I say I'm explicitly casting my P into A2*, I mean I just do (A2*)P->bar(), so I may be using the wrong type of casting.
Last edited by axfv; May 4th, 2009 at 2:14 pm.
Reply With Quote Quick reply to this message  
Join Date: Sep 2004
Posts: 7,823
Reputation: Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute 
Solved Threads: 748
Team Colleague
Narue's Avatar
Narue Narue is offline Offline
Senior Bitch

Re: Multiple inheritance and cross-class type casting

 
2
  #2
May 4th, 2009
It's hard to say without seeing your code, but I'd wager your cast is wrong. Compare your code with this skeleton and tell me if you're doing something equivalent:
  1. #include <iostream>
  2.  
  3. class A1 {
  4. public:
  5. int a1;
  6. virtual ~A1() {}
  7. };
  8.  
  9. class A2: public A1 {
  10. public:
  11. int a2;
  12. virtual ~A2() {}
  13. };
  14.  
  15. class B {
  16. public:
  17. int b;
  18. virtual ~B() {}
  19. };
  20.  
  21. class C: public A2, public B {
  22. public:
  23. int c;
  24. };
  25.  
  26. void foo ( B* p )
  27. {
  28. C *cp = dynamic_cast<C*> ( p );
  29.  
  30. if ( cp != 0 ) {
  31. std::cout<< cp->a1 <<'\n'
  32. << cp->a2 <<'\n'
  33. << cp->b <<'\n'
  34. << cp->c <<'\n';
  35. }
  36. }
  37.  
  38. int main()
  39. {
  40. C c;
  41.  
  42. c.a1 = 1;
  43. c.a2 = 2;
  44. c.b = 3;
  45. c.c = 4;
  46.  
  47. foo ( &c );
  48. }
New members chased away this month: 3
Reply With Quote Quick reply to this message  
Join Date: Nov 2008
Posts: 21
Reputation: axfv is an unknown quantity at this point 
Solved Threads: 3
axfv axfv is offline Offline
Newbie Poster

Re: Multiple inheritance and cross-class type casting

 
0
  #3
May 4th, 2009
Unfortunately this code is for a proprietary application and the classes span several files, so the full code would be impractical to put up.

I was only using explicit type casting, but I started to use dynamic_cast, though it's returning type void*.

Also, I screwed up when I was describing my problem. Class B has a function Foo(), but it will only be used by objects type C. Inside Foo(), we attempt to cast the keyword this, so it's something like this:
  1. ...
  2. class B
  3. {
  4. void Foo()
  5. {
  6. C* thisC = dynamic_cast<C*>(this); //returns type VOID*
  7. }
  8. }
  9. ...
Last edited by axfv; May 4th, 2009 at 3:19 pm.
Reply With Quote Quick reply to this message  
Join Date: Sep 2004
Posts: 7,823
Reputation: Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute 
Solved Threads: 748
Team Colleague
Narue's Avatar
Narue Narue is offline Offline
Senior Bitch

Re: Multiple inheritance and cross-class type casting

 
2
  #4
May 4th, 2009
>Also, I screwed up when I was describing my problem.
Nice. How about you give me a bare bones example of your code, similar to the one I gave you. At least that way I'll have a better idea of what your hierarchy looks like.
New members chased away this month: 3
Reply With Quote Quick reply to this message  
Join Date: Nov 2008
Posts: 21
Reputation: axfv is an unknown quantity at this point 
Solved Threads: 3
axfv axfv is offline Offline
Newbie Poster

Re: Multiple inheritance and cross-class type casting

 
0
  #5
May 4th, 2009
ok, that was a good idea. I was able to narrow the problem down by creating a bare-bones example (took so long because I was hoping to find a fix myself):

stafx.h
  1. #pragma once
  2.  
  3.  
  4. #include <iostream>
  5. #include <tchar.h>
  6.  
  7. class A1
  8. {
  9. int a1var;
  10. public:
  11. A1() {};
  12. int getvar() { return a1var; };
  13. void setvar(int n) { a1var = n; };
  14. };
  15.  
  16. class A2 : public A1
  17. {
  18. public:
  19. A2() : A1() {setvar(5);};
  20. };
  21.  
  22. class B
  23. {
  24. public:
  25. B() {};
  26. void Foo (int n);
  27. virtual Bar() {}; // dummy function to make this a polymorphic class
  28. };
  29.  
  30. class C : public A2, public B
  31. {
  32. public:
  33. C() : A2() , B() {};
  34. };

InheritanceTest.cpp:
  1. #include "stdafx.h"
  2.  
  3. using namespace std;
  4.  
  5. void B::Foo (int n)
  6. {
  7. cout << (n==((C*)this)->getvar()) ? 1 : 0;
  8. cout << endl;
  9. cout << (n==((A2*)this)->getvar()) ? 1 : 0;
  10. };
  11.  
  12. int _tmain(int argc, _TCHAR* argv[])
  13. {
  14. C cVar = C();
  15. cVar.Foo(5);
  16. return 0;
  17. }

I had to split the function definition for B because it complained of referencing the non-yet-existent class C.

The output produced by cVar.Foo(5) is "1 \n 0", when I want it to be "1 \n 1". Casting inside B to (C*)this seems to preserve everything because it "casts up", but casting to (A2*)this messes up because it "casts across". I verified this in my real project and casting up did indeed preserve the object variables, while casting across no longer recognized their values.

In my real project, I'll need to cast across.
Last edited by axfv; May 4th, 2009 at 4:47 pm.
Reply With Quote Quick reply to this message  
Join Date: Jul 2008
Posts: 2,001
Reputation: ArkM has much to be proud of ArkM has much to be proud of ArkM has much to be proud of ArkM has much to be proud of ArkM has much to be proud of ArkM has much to be proud of ArkM has much to be proud of ArkM has much to be proud of ArkM has much to be proud of 
Solved Threads: 343
ArkM's Avatar
ArkM ArkM is offline Offline
Postaholic

Re: Multiple inheritance and cross-class type casting

 
0
  #6
May 4th, 2009
C-style casts are incorrect in that case: class B is_NOT_a C, A1 or A2.

It's impossible to use this construct in the definition of parent of C:
  1. class B {
  2. ...
  3. void foo()
  4. {
  5. C* p = dynamyc_cast<C*>(this);
  6. ...
  7. }
  8. ...
  9. };
Class B do not know its descendants. Incomplete C declaration can't help in that case (C* type var is invalid target type for dynamic_cast with incomplete declaration of C). However you can place B::foo() implementation after definition of C (what's a strange inheritance: the parent must know its descendant).

This sceleton works fine:
  1. class A1 {
  2. public:
  3. A1():i(1001) {}
  4. virtual ~A1() {}
  5. virtual char const* who() const { return "A1"; }
  6. protected:
  7. int i;
  8. };
  9. class A2: public A1 {
  10. public:
  11. A2():A1(),i(1002) {}
  12. char const* who() const { return "A2"; }
  13. protected:
  14. int i;
  15. };
  16.  
  17. class B {
  18. public: // must be polymorphic!
  19. virtual ~B() {}
  20. void foo() {
  21. C* pc = dynamic_cast<C*>(this);
  22. }
  23. };
  24. class C: public A2, public B {
  25. public:
  26. C() { A1::i = 1; A2::i = 2; }
  27. char const* who() const { return "C"; }
  28. void show() const {
  29. cout << A1::i << ':' << A2::i;
  30. }
  31. };
  32. void foo(const B* p)
  33. {
  34. const C* pc;
  35. pc = dynamic_cast<const C*>(p);
  36. if (pc) {
  37. cout << pc->who() << '\t';
  38. pc->show();
  39. cout << endl;
  40. const A1* pa1 = pc;
  41. cout << pa1->who() << endl;
  42. } else
  43. cout << "Don\'t know\n";
  44. }
  45.  
  46. int main()
  47. {
  48. C c;
  49. c.show(); cout << '\n';
  50. foo(&c);
  51. return 0;
  52. }
Last edited by ArkM; May 4th, 2009 at 5:13 pm.
Reply With Quote Quick reply to this message  
Reply

This thread is more than three months old.
Perhaps start a new thread instead?
Message:



Similar Threads
Other Threads in the C++ Forum
Thread Tools Search this Thread



Tag cloud for C++
About Us | Contact Us | Advertise | DaniWeb | Acceptable Use Policy | RSS Feed

©2003 - 2009 DaniWeb® LLC