943,520 Members | Top Members by Rank

Ad:
  • C++ Discussion Thread
  • Marked Solved
  • Views: 2759
  • C++ RSS
Apr 10th, 2009
1

Multiple Inheritance: Ambiguous Function

Expand Post »
Hey guys,

I was wondering, with this code:

main.cpp
cpp Syntax (Toggle Plain Text)
  1. #include <iostream>
  2. using namespace std;
  3.  
  4. class car {
  5. public:
  6. car (float speed) :
  7. speed(speed) {}
  8.  
  9. car () :
  10. speed(0) {}
  11.  
  12. void cruise(float speed) {
  13. this->speed = speed;
  14. cout << "New speed: " << getSpeed() << endl;
  15. }
  16.  
  17. void brake(float power) {
  18. this->speed -= power*power/4;
  19. }
  20.  
  21. float getSpeed() {
  22. return speed;
  23. }
  24.  
  25. private:
  26. float speed;
  27. };
  28.  
  29. class racer : public car {
  30. public:
  31. void boost(float power) {
  32. cout << "BOOST! ";
  33. cruise(getSpeed() + power*power/3);
  34. }
  35. };
  36.  
  37. class tank : public car {
  38. public:
  39. bool shoot(float aimTime) {
  40. cout << "Shot ";
  41. if (aimTime > 5.0) {
  42. cout << "hits!" << endl;
  43. return true; //hit!
  44. } else {
  45. cout << "misses!" << endl;
  46. return false; //miss!
  47. }
  48. }
  49.  
  50. };
  51.  
  52. class racetank : public racer, public tank {
  53. public:
  54. bool boostShoot(float power, float aimTime) {
  55. boost(power*2);
  56. return shoot(aimTime*2);
  57. }
  58. };
  59.  
  60. int main() {
  61. racetank mycar;
  62. mycar.car::cruise(50);
  63. mycar.boost(20);
  64. mycar.car::brake(5);
  65. mycar.boostShoot(35, 1.4);
  66.  
  67. return 0;
  68. }

MinGW's GCC gives me these errors:
C++ Syntax (Toggle Plain Text)
  1. D:\MyDocs\Code\InheritThis\main.cpp||In function `int main()':|
  2. D:\MyDocs\Code\InheritThis\main.cpp|62|error: `car' is an ambiguous base of `racetank'|
  3. D:\MyDocs\Code\InheritThis\main.cpp|64|error: `car' is an ambiguous base of `racetank'|
  4.  

How come the compiler still complains about ambiguity?

It knows the function is not overloaded (?)
It knows the function is not virtual.

Can't the compiler be sure that when I call the function like that, it's the same function?

Thanks in advance,

PS:
I know the solution to this is to use virtual inheritance, but I was wondering why C++ works like it does.
Reputation Points: 69
Solved Threads: 28
Posting Whiz
Clockowl is offline Offline
376 posts
since May 2008
Apr 10th, 2009
0

Re: Multiple Inheritance: Ambiguous Function

Replying to myself yeey.

Let a class in memory be resembled by:

[classname]

Class inheritance in memory looks like this, according to wiki.

class a;
class b : a;

class a looks like this:
[a]

b looks like this:
[a][b]

So if we'd have a class base and c, we can create a diamond inheritance:

class base;
class a : base;
class b : base;
class c : a, b;

Their memory-pictures are like this:

base: [base]
a: [base][a]
b: [base][b]
c: [base][a][base][b][c]

c, more specific, looks like this:
[a::base][a][b::base][b][c]

So, naturally, a::base and b::base data members can differ, but a::base::func() must be the same as b::base::func() given that a and b don't overload and func() is not virtual right? How else can they be different?
Reputation Points: 69
Solved Threads: 28
Posting Whiz
Clockowl is offline Offline
376 posts
since May 2008
Apr 10th, 2009
0

Re: Multiple Inheritance: Ambiguous Function

> How else can they be different?
Yep, they must be the same function.

It works if you pick a specific copy like this:
mycar.racer::cruise(50); or this
mycar.tank::cruise(50);
But "diamond inheritance" looks like something to avoid in general. Seems strange that the language wasn't designed to include only one copy in such a case.
Reputation Points: 163
Solved Threads: 91
Posting Pro in Training
nucleon is offline Offline
476 posts
since Oct 2008
Apr 10th, 2009
0

Re: Multiple Inheritance: Ambiguous Function

Quoting myself:
I know the solution to this is to use virtual inheritance, but I was wondering why C++ works like it does.

The correct solution is to virtual inherit the class cars in race and tank class. This way, the compiler creates only one car inside of racetank, and 2 vtables to be able to still call the functions.

Basically, I was just wondering why GCC doesn't just pick one of the functions and give me a warning instead of 2 errors.

--Edit, a bit later:

So the compiler asks me what this pointer to give to the function, that of class a or b? It doesn't matter if one only uses class c, but when one degrades class c to class a, b or base, the data members may have different values then what was expected if the compiler chose instead of the programmer. Say function modifies int value, how would the programmer know what value it was modified, that of a or b? Therefore a name must be presented if one wants to call functions like this.

The "proper" solution, in most cases, is to go by virtual inheritance.

This was helpful research. Multiple Virtual Inheritance seems a nice and powerful tool, albeit a bit tricky.
Last edited by Clockowl; Apr 10th, 2009 at 9:33 pm.
Reputation Points: 69
Solved Threads: 28
Posting Whiz
Clockowl is offline Offline
376 posts
since May 2008
Apr 10th, 2009
0

Re: Multiple Inheritance: Ambiguous Function

Quote ...
Basically, I was just wondering why GCC doesn't just pick one of the functions and give me a warning instead of 2 errors.
I have compiled your mentioned source by the microsoft C++ compiler too. the same error message is there.

C++ Syntax (Toggle Plain Text)
  1. error C2385: 'racetank::car' is ambiguous

So it's not a compiler bug or compiler specific thing , it should be something that clearly defined on the C++ language specification.

Let this thread open may be later some expertise see this thread and reply.


Quote ...
The correct solution is to virtual inherit the class cars in race and tank class. This way, the compiler creates only one car inside of racetank, and 2 vtables to be able to still call the functions.
and using virtual doesn't slove this problem. I used the Microsoft C++ compiler.I think it's not the reason.

yes there is a correct solution for this ,, see this ,
http://msdn.microsoft.com/en-us/libr...2f(VS.71).aspx

anyway why this happen is not still clear. so please keep this
thread open.
Last edited by NicAx64; Apr 10th, 2009 at 9:42 pm.
Reputation Points: 86
Solved Threads: 43
Posting Pro
NicAx64 is offline Offline
532 posts
since Mar 2009
Apr 10th, 2009
0

Re: Multiple Inheritance: Ambiguous Function

C++ Syntax (Toggle Plain Text)
  1. #include <iostream>
  2. using namespace std;
  3.  
  4. class car {
  5. public:
  6. car (float speed) :
  7. speed(speed) {}
  8.  
  9. car () :
  10. speed(0) {}
  11.  
  12. void cruise(float speed) {
  13. this->speed = speed;
  14. cout << "New speed: " << getSpeed() << endl;
  15. }
  16.  
  17. void brake(float power) {
  18. this->speed -= power*power/4;
  19. }
  20.  
  21. float getSpeed() {
  22. return speed;
  23. }
  24.  
  25. private:
  26. float speed;
  27. };
  28.  
  29. class racer : public car {
  30. public:
  31. void boost(float power) {
  32. cout << "BOOST! ";
  33. cruise(getSpeed() + power*power/3);
  34. }
  35. };
  36.  
  37. class tank : public car {
  38. public:
  39. bool shoot(float aimTime) {
  40. cout << "Shot ";
  41. if (aimTime > 5.0) {
  42. cout << "hits!" << endl;
  43. return true; //hit!
  44. } else {
  45. cout << "misses!" << endl;
  46. return false; //miss!
  47. }
  48. }
  49.  
  50. };
  51.  
  52. class racetank : public racer, public tank {
  53. public:
  54.  
  55. using tank::cruise ;
  56. using racer::brake ;
  57. bool boostShoot(float power, float aimTime) {
  58. boost(power*2);
  59. return shoot(aimTime*2);
  60. }
  61. };
  62.  
  63. int main() {
  64.  
  65.  
  66. racetank mycar;
  67. mycar.cruise(50);
  68. mycar.boost(20);
  69. mycar.brake(5);
  70. mycar.boostShoot(35, 1.4);
  71.  
  72. return 0;
  73. }
This code compiles nicely , so this is the solution , but the problem is
still unclear.
Reputation Points: 86
Solved Threads: 43
Posting Pro
NicAx64 is offline Offline
532 posts
since Mar 2009
Apr 10th, 2009
0

Re: Multiple Inheritance: Ambiguous Function

No, that's not the proper solution to this.

This is

cpp Syntax (Toggle Plain Text)
  1. #include <iostream>
  2. #include <string>
  3. using namespace std;
  4.  
  5. class car {
  6. public:
  7. car (float speed) :
  8. speed(speed) {}
  9.  
  10. car () :
  11. speed(0) {}
  12.  
  13. void cruise(float speed) {
  14. this->speed = speed;
  15. getSpeed(true);
  16. }
  17.  
  18. void brake(float power) {
  19. this->speed -= power*power/4;
  20. getSpeed(true);
  21. }
  22.  
  23. float getSpeed(bool verbose = false) {
  24. if (verbose) {
  25. cout << "New speed: " << getSpeed() << endl;
  26. }
  27. return speed;
  28. }
  29.  
  30. private:
  31. float speed;
  32. };
  33.  
  34. class racer : virtual public car {
  35. public:
  36. void boost(float power) {
  37. cout << "BOOST! ";
  38. cruise(getSpeed() + power*power/3);
  39. }
  40. };
  41.  
  42. class tank : virtual public car {
  43. public:
  44. bool shoot(float aimTime) {
  45. cout << "Shot ";
  46. if (aimTime > 5.0) {
  47. cout << "hits!" << endl;
  48. return true; //hit!
  49. } else {
  50. cout << "misses!" << endl;
  51. return false; //miss!
  52. }
  53. }
  54.  
  55. };
  56.  
  57. class racetank : public racer, public tank {
  58. public:
  59. bool boostShoot(float power, float aimTime) {
  60. boost(power*2);
  61. return shoot(aimTime*2);
  62. }
  63. };
  64.  
  65. int main() {
  66. racetank mycar;
  67. mycar.cruise(50);
  68. mycar.boost(20);
  69. mycar.brake(5);
  70. mycar.boostShoot(35, 1.4);
  71.  
  72. return 0;
  73.  
  74. return 0;
  75. }

This way, racetank only has one base object car, not two. Virtual Inheritance
Reputation Points: 69
Solved Threads: 28
Posting Whiz
Clockowl is offline Offline
376 posts
since May 2008
Apr 11th, 2009
0

Re: Multiple Inheritance: Ambiguous Function

....
Reputation Points: 10
Solved Threads: 5
Newbie Poster
stumpy798 is offline Offline
18 posts
since Apr 2009

This thread is solved

Either the thread starter or a moderator has marked this thread as solved. You can most likely trust the responses and answers given. There is most likely no reason for any further responses to be posted here. If you have a related question, please start a new thread in this forum instead.

This thread is more than three months old

No one has posted to this discussion for at least three months. Please let old threads die and do not reply to them unless you feel you have something new and valuable to contribute that absolutely must be added to make the discussion complete. Otherwise, please start a new thread in this forum instead.
Message:
Previous Thread in C++ Forum Timeline: can someone PLZ help me with my homework!
Next Thread in C++ Forum Timeline: file not recognized: File format not recognized





About Us | Contact Us | Advertise | Acceptable Use Policy
Forum Index | Build Custom RSS Feed


Follow us on Twitter


© 2011 DaniWeb® LLC