Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX

Tip of the Day
Language: C++
Expertise: Intermediate
Aug 20, 1999

Never Use Incompatible Pointers to Member Functions

A reader posted a message on one of the C++ newsgroups recently. He had to port a huge project from Borland C++ 5.0 to Visual C++ 6.0. The project uses the callback mechanism through pointers to member functions. Unfortunatly, these pointers are assigned member functions with incompatible signatures. For example:

class Base;
  //a pointer to a member function that takes no arguments and returns bool
typedef bool (Base::*meth1)(); 
  //a pointer to a member function that takes long and returns bool
typedef bool (Base::*meth2)(long);

class Base{
  bool Base::perform(meth1 m, long param);

Due to a historical design mistake, the pointer to member m (the first argument of perform) is sometimes called with more than one argument, and sometimes it is called with no arguments. Of course, a brute force cast is needed to enable that, as in the line numbered 1:

bool Base::perform(meth1 m, long param)
 meth2 *p = (meth1 *)(&m); // 1.cast pointer to meth1 to pointer to meth2
 meth2  q = *p; 
// force m to take an argument, although it's not supposed to take any
 return (this->*q)(param);  //2

For some reason, the application built under Borland's compiler tolerated this hack. However, under Visual C++, it crashes when the line numbered 2 executes. The reader wanted to know if there was a simple way to make this code execute under Visual C++ without encountering a runtime crash and without having to make code corrections.

Whatever the answer may be (perhaps there is a way to tamper with the underlying code generation of Visual C++ and make this code somehow work), there is no escape from fixing the code so that it avoids incompatible casts of pointers to member functions. There are several reasons for that. First, even if there is a magic trick that will make this code run under Visual C++ 6.0 without a crash, that is only a temporary band-aid. There's no guarantee that this trick will work with future releases of Visual C++. Furthermore, the C++ Standard clearly says that using incompatible pointers to member functions yields undefined behavior. Founding an application on such shaky foundations -- clearly knowing that the code violates basic rules of the language -- is an ominous sign regarding the quality and the reliability of the software in question.

Danny Kalev
Comment and Contribute








