| | |
Multiple Inheritance: Ambiguous Function
Please support our C++ advertiser: Intel Parallel Studio Home
Thread Solved |
Hey guys,
I was wondering, with this code:
main.cpp
MinGW's GCC gives me these errors:
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.
I was wondering, with this code:
main.cpp
cpp Syntax (Toggle Plain Text)
#include <iostream> using namespace std; class car { public: car (float speed) : speed(speed) {} car () : speed(0) {} void cruise(float speed) { this->speed = speed; cout << "New speed: " << getSpeed() << endl; } void brake(float power) { this->speed -= power*power/4; } float getSpeed() { return speed; } private: float speed; }; class racer : public car { public: void boost(float power) { cout << "BOOST! "; cruise(getSpeed() + power*power/3); } }; class tank : public car { public: bool shoot(float aimTime) { cout << "Shot "; if (aimTime > 5.0) { cout << "hits!" << endl; return true; //hit! } else { cout << "misses!" << endl; return false; //miss! } } }; class racetank : public racer, public tank { public: bool boostShoot(float power, float aimTime) { boost(power*2); return shoot(aimTime*2); } }; int main() { racetank mycar; mycar.car::cruise(50); mycar.boost(20); mycar.car::brake(5); mycar.boostShoot(35, 1.4); return 0; }
MinGW's GCC gives me these errors:
C++ Syntax (Toggle Plain Text)
D:\MyDocs\Code\InheritThis\main.cpp||In function `int main()':| D:\MyDocs\Code\InheritThis\main.cpp|62|error: `car' is an ambiguous base of `racetank'| D:\MyDocs\Code\InheritThis\main.cpp|64|error: `car' is an ambiguous base of `racetank'|
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.
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?
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?
> How else can they be different?
Yep, they must be the same function.
It works if you pick a specific copy like this:
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.
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.
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.
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.
•
•
•
•
Basically, I was just wondering why GCC doesn't just pick one of the functions and give me a warning instead of 2 errors.
C++ Syntax (Toggle Plain Text)
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.
•
•
•
•
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.
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.
Nothing like a kernel pannic !
C++ Syntax (Toggle Plain Text)
#include <iostream> using namespace std; class car { public: car (float speed) : speed(speed) {} car () : speed(0) {} void cruise(float speed) { this->speed = speed; cout << "New speed: " << getSpeed() << endl; } void brake(float power) { this->speed -= power*power/4; } float getSpeed() { return speed; } private: float speed; }; class racer : public car { public: void boost(float power) { cout << "BOOST! "; cruise(getSpeed() + power*power/3); } }; class tank : public car { public: bool shoot(float aimTime) { cout << "Shot "; if (aimTime > 5.0) { cout << "hits!" << endl; return true; //hit! } else { cout << "misses!" << endl; return false; //miss! } } }; class racetank : public racer, public tank { public: using tank::cruise ; using racer::brake ; bool boostShoot(float power, float aimTime) { boost(power*2); return shoot(aimTime*2); } }; int main() { racetank mycar; mycar.cruise(50); mycar.boost(20); mycar.brake(5); mycar.boostShoot(35, 1.4); return 0; }
still unclear.
Nothing like a kernel pannic !
No, that's not the proper solution to this.
This is
This way, racetank only has one base object car, not two. Virtual Inheritance
This is
cpp Syntax (Toggle Plain Text)
#include <iostream> #include <string> using namespace std; class car { public: car (float speed) : speed(speed) {} car () : speed(0) {} void cruise(float speed) { this->speed = speed; getSpeed(true); } void brake(float power) { this->speed -= power*power/4; getSpeed(true); } float getSpeed(bool verbose = false) { if (verbose) { cout << "New speed: " << getSpeed() << endl; } return speed; } private: float speed; }; class racer : virtual public car { public: void boost(float power) { cout << "BOOST! "; cruise(getSpeed() + power*power/3); } }; class tank : virtual public car { public: bool shoot(float aimTime) { cout << "Shot "; if (aimTime > 5.0) { cout << "hits!" << endl; return true; //hit! } else { cout << "misses!" << endl; return false; //miss! } } }; class racetank : public racer, public tank { public: bool boostShoot(float power, float aimTime) { boost(power*2); return shoot(aimTime*2); } }; int main() { racetank mycar; mycar.cruise(50); mycar.boost(20); mycar.brake(5); mycar.boostShoot(35, 1.4); return 0; return 0; }
This way, racetank only has one base object car, not two. Virtual Inheritance
![]() |
Other Threads in the C++ Forum
- Previous Thread: can someone PLZ help me with my homework!
- Next Thread: file not recognized: File format not recognized
| Thread Tools | Search this Thread |
api application array arrays based beginner binary bmp c++ c/c++ calculator char char* class classes code coding compile compiler console conversion convert count data database delete deploy developer dll download dynamiccharacterarray email encryption error file format forms fstream function functions game generator givemetehcodez graph gui homeworkhelp iamthwee ifstream image input int java lib library list loop looping loops map math matrix memory multiple newbie news number numbertoword output pointer problem program programming project python random read recursion recursive reference rpg simple sorting string strings temperature template text text-file tree url variable vector video visual visualstudio win32 windows winsock wordfrequency wxwidgets





