Re: Fun with member-function pointers
Default User wrote:
Very interesting. Below will be a more complete example of what I'm
proposing to do in the real code. That is, the managing of the handlers,
storing the pointers, retrieving the correct one based on op code, and
calling of the function pointer, take place in the base class. All the
derived class has to do is set up the relationships between op codes and its
member function pointers to implement the operation set for that particular
module.
If this is still legal, then I'd be on pretty firm ground with my plan for
the actual code.
The code you have in your example is perfectly legal, with perfectly
defined behavior.
Again, beware of broken compilers that might not handle it correctly.
But for your specific example I don't expect any surprises from the
compiler.
Keep in mind though, that one restriction imposed on such use of
`static_cast` is that the base class should be unambiguous and
non-virtual in the derived class. (I was wrong to say earlier that
virtual inheritance in not a problem in this case).
For example, this code will not compile because the base class is ambiguous
struct B { };
struct D1 : B {};
struct D2 : B {};
struct X : D1, D2 { void foo(); };
int main() {
void (B::*p)() = static_cast<void (B::*)()>(&X::foo); // ERROR
}
And this code will not compile because the base class is virtual
struct B { };
struct D : virtual B { void foo(); };
int main() {
void (B::*p)() = static_cast<void (B::*)()>(&D::foo); // ERROR
}
As long as your base class is not involved in such inheritance contexts,
your code is fine. Note, again, that the above situations will fail to
compile (as opposed to compiling and producing undefined behavior later).
Introduction of VMT pointer late in the hierarchy (as in Marcel's
example) as well as multiple inheritance (aside from ambiguous
situations illustrated above) do not really break this functionality.
The compilers are required to make it work correctly.
--
Best regards,
Andrey Tarasevich