class SpaceShip {}; class ApolloSpacecraft : public SpaceShip {}; class Asteroid { public: virtual void CollideWith(SpaceShip&) { cout << "Asteroid hit a SpaceShip" << endl; } virtual void CollideWith(ApolloSpacecraft&) { cout << "Asteroid hit an ApolloSpacecraft" << endl; } }; class ExplodingAsteroid : public Asteroid { public: virtual void CollideWith(SpaceShip&) { cout << "ExplodingAsteroid hit a SpaceShip" << endl; } virtual void CollideWith(ApolloSpacecraft&) { cout << "ExplodingAsteroid hit an ApolloSpacecraft" << endl; } };
SpaceShip& theSpaceShipReference = theApolloSpacecraft; theAsteroid.CollideWith(theSpaceShipReference); theAsteroidReference.CollideWith(theSpaceShipReference);
From: 'David Feurle' via ISO C++ Standard - Future Proposals Sent: Sunday, October 16, 2016 1:44 PM To: ISO C++ Standard - Future Proposals Reply To: std-pr...@isocpp.org Subject: Re: [std-proposals] generic dynamic / runtime cast (cast to real runtime type) |
Hello Thiago,there are things that can not be done with virtual functions. For example double dispatch and the visitor.It is possible to simulate a dynamic call functionality with virtual functions. But it is a hazzle and several classes / functions need to be implemented to add this functionality.Imagine the following "standard" example for double dispatch:class SpaceShip {}; class ApolloSpacecraft : public SpaceShip {}; class Asteroid { public: virtual void CollideWith(SpaceShip&) { cout << "Asteroid hit a SpaceShip" << endl; } virtual void CollideWith(ApolloSpacecraft&) { cout << "Asteroid hit an ApolloSpacecraft" << endl; } }; class ExplodingAsteroid : public Asteroid { public: virtual void CollideWith(SpaceShip&) { cout << "ExplodingAsteroid hit a SpaceShip" << endl; } virtual void CollideWith(ApolloSpacecraft&) { cout << "ExplodingAsteroid hit an ApolloSpacecraft" << endl; } };SpaceShip& theSpaceShipReference = theApolloSpacecraft; theAsteroid.CollideWith(theSpaceShipReference); theAsteroidReference.CollideWith(theSpaceShipReference);This will not call the correct function even though we have a overload for it. Currently we need to employ a visitor / double dispatch to all classes.
In C# it is part of the language.The visitor pattern is often used and it would not be neccessary to implement it if we would have a runtime cast.
In C# it is part of the language.The visitor pattern is often used and it would not be neccessary to implement it if we would have a runtime cast.
Alternatively, we could just make visitation more reasonable to implement.
C++ is a statically typed language. What you're talking about requires dynamic dispatching of a kind that C++ as a language is simply not capable of. Not without adding a bunch of hacks to the language.
Take your specific case, for example: `dyn->fun()`, where `dyn` may be `A*` or `B*`. Because C++ is a statically typed language, it cannot have a type which may be one of two things. Therefore, it must be a type which is neither, like a `variant` or somesuch. This type will therefore have to synthesize replicas of all of the operations that could be performed on any of those types. Even "operator-dot" gymnastics don't permit that.
Plus, `A::fun` and `B::fun` are allowed to return different things. Even if they're both virtual functions inherited from the same base class, the derived class versions can differ in terms of return values. So what does `dyn->fun()` return? It would have to return a `variant` of the possible return values. Which makes it hard to use those return values.
This is far more complex than you give it credit for being. C# is a much more malleable language that C++.
C++ is a statically typed language. What you're talking about requires dynamic dispatching of a kind that C++ as a language is simply not capable of. Not without adding a bunch of hacks to the language.