There are cases when you need to define a constant pointer to a variable/object; for instance, when taking a function address, or when you want to protect a pointer from unintended modifications such as assignment of new address, pointer arithmetic, etc. In fact, an object’s this is a constpointer. A constant pointer is declared:

Although the syntax of pointers to members may seem a bit confusing at first, it is consistent and resembles the form of ordinary pointers, with the addition of the class name followed by the operator :: before the asterisk. For example, if an ordinary pointer to int looks like this:

Code:

int * pi;

you define a pointer to an int member of class A like this:

Code:

class A{/**/};
int A::*pmi; // pmi is a pointer to an int member of A

You can initialize a pointer to member:

Code:

class A
{
public:
int num;
int x;
};
int A::*pmi = &A::num; // 1

The statement numbered 1 defines a pointer to an int member of class A and initializes it with the address of the member num. Now you can use the pointer pmi to examine and modify the value of num in any object of class A:

Pointers to member functions consists of the member function's return type, the class name followed by ::, the pointer's name, and the function's parameter list. For example, a pointer to a member function of class A that returns int and takes no arguments is defined like this (note that both pairs of parentheses are mandatory):

Code:

class A {
public:
int func ();
};
int (A::*pmf) (); /* pmf is a pointer to some member
function of class A that returns int and takes no
arguments*/

In fact, a pointer to a member functions looks just like an ordinary pointer to function, except that it also contains the class's name immediately followed by the :: operator. You can invoke the member function to which pmf points like this:

A standard-compliant compiler should flag line #1 as an error. Let's examine it in further detail to see why. The expression A::f is called a qualified-id. A qualified-id denotes a member of a class. According to the C++ standard, there is no implicit conversion from a qualified-id denoting a member function to the type "pointer to member function". In other words, an ampersand must appear before the qualified-id if you want to take the address of the member function. For example:

Code:

void (A::*pm)(int) = &A::f; // now OK

Programmers who are new to the concept of pointers to members are often confused by this subtlety. After all, when dealing with ordinary functions, implicit conversion from a function type to the type "pointer to function" does exist:

Code:

void g();
void (*pf) () = g; // OK, implicit conversion of g to &g

However, there are many differences between a qualified-id and a plain function's name. Enabling implicit conversion of a qualified-id to a member function's address can therefore cause confusion and ambiguities. To avoid this, C++ requires that a class member's address be taken explicitly by preceding an ampersand to the qualified-id. Even if your compiler happens to accept the code in line #1, you should add an ampersand to avoid maintenance problems in the future, and to make your code more readable.

One of the new features in the recently approved C standard C99, is the restrict pointer qualifier. This qualifier can be applied to a data pointer to indicate that, during the scope of that pointer declaration, all data accessed through it will be accessed only through that pointer but not through any other pointer. The 'restrict' keyword thus enables the compiler to perform certain optimizations based on the premise that a given object cannot be changed through another pointer. Now you're probably asking yourself, "doesn't const already guarantee that?" No, it doesn't. The qualifier const ensures that a variable cannot be changed through a particular pointer. However, it's still possible to change the variable through a different pointer. For example:

In this example, both pci and pi point to the same variable, n. You can't change n's value through pci but you can change it using pi. Therefore, the compiler isn't allowed to optimize memory access for *pci by preloading n's value. In this example, the compiler indeed shouldn't preload n because its value changes three times during the execution of f(). However, there are situations in which a variable is accessed only through a single pointer. For example:

Code:

FILE *fopen(const char * filename, const char * mode);

The name of the file and its open mode are accessed through unique pointers in fopen(). Therefore, it's possible to preload the values to which the pointers are bound. Indeed, the C99 standard revised the prototype of the function fopen() to the following:

In low-level programming and hardware interfaces, you often need to assign a pointer to a specific physical address. To do that, you have to cast the address value using the reinterpret_cast operator. Here's an example that shows how this is done:

Many times, a program crashes due to multiple deletes on the same pointer. In some cases, this is due to a programming error that can be removed. There are situations, however, where it may be unclear whether to delete a pointer or not. Let's consider the code given below:

If everything works fine, pcMemory will be properly deleted at the end of the try block. But if one of the operations between allocation and deletion throws an exception, pcMemory will remain allocated. At the end of function, it's not known whether to delete pcMemory or not. Deleting it may cause a double deletion followed by a crash. Similarly, if it's not deleted, it may result in a memory leak. The trick is to always set the memory pointer to NULL after deletion:

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:

Code:

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{
public:
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:

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.

Callback functions have a fixed signature so you cannot alter the number or type of the arguments it takes. For example, the standard qsort() function takes a pointer to a function that has the following signature:

Code:

int (cmp*)(const void *, const void *) //user's comparison function

This signature allows you to pass exactly two arguments to your custom-made comparison function. However, suppose that the comparison function has to compare strings and you want to pass a third argument to indicate whether the comparison should be case-sensitive or not. You cannot simply add a third argument to the function call, because the compiler will complain about it (don't even think about casting the function pointer; see this tip). Instead, you can define a struct that contains two members:

Code:

struct Comparison
{
char *name;
bool caseSensitive;
};

Now instead of passing a pointer to char as the second argument, you can pass a pointer to an instance of that struct. The comparison function will unpack the struct and compare the strings accordingly: