1. Pointer to Class Member
A pointer to member embodies the type of the class as well as the type of the member. Pointers to member apply only to non static members of a class. static class members are not part of any object, so no special syntax is needed to point to a static member. Pointers to static members are ordinary pointers.class Screen {
public:
typedef std::string::size_type index;
char get() const;
char get(index ht, index wd) const;
private:
std::string contents;
index cursor;
index height, width;
};
## 2. Defining a Pointer to Data Member
string Screen::*ps_Screen = &Screen::contents;
普通指针使用*来标示,而指向类的成员函数的指针使用ClassName::*标示。需要注意的是,指向类的数据成员的指针并非指针,因为它既不包含地址,行为也不像指针。与常规指针不同,一个指向成员的指针并不指向一个具体的内存位置,它指向的是一个类的特定成员,而不是指向一个特定对象里的特定成员。通常最清晰的做法是将指向数据成员的指针看作 为一个偏移量 。 C++标准并没有说该如何实现指向成员的指针,大多数编译器都将指向数据成员的指针实现为一个整数,其中包含被指向成员的偏移量。另外加上1(加1是为了让0值可以表示一个空的数据成员指针)。 这个偏移量告诉你,一个特定成员的位置距离对象的起点有多少个字节。一个类成员的偏移量在任何对象中都是相同的。 为啥偏移量会加1呢?这主要用来区分“没有指向任何数据成员的指针”和“指向第一个数据成员的指针”这两种情况。考虑下面这样的例子:float Point3d::*p1 =0;
float Point3d::*p2 = &Point3d::x;
if( p1 == p2 ){
cout <<” p1 & p2 contain the same value.”;
cout <<”they must address the same member!”<<endl;
}
3. Defining a Pointer to Member Function
A pointer to a member function must match the type of the function to which it points, in three ways:
- The type and number of the function parameters, including whether the member is const.
- The return type.
- The class type of which it is a member
char (Screen::*pmf)() const = &Screen::get;
char (Screen::*pmf2)(Screen::index, Screen::index) const;
pmf2 = &Screen::get;
typedef char (Screen::*Action)(Screen::index, Screen::index) const;
Action get = &Screen::get;
4. Using a Pointer to Member Function
char (Screen::*pmf)() const = &Screen::get; |
5. Using a Pointer to Data Member
Screen::index Screen::*pindex = &Screen::width; |
6. Pointer-to-Member Function Tables
One common use for function pointers and for pointers to member functions is to store them in a function table. A function table is a collection of function pointers from which a given call is selected at run time.class Screen {
public:
// other interface and implementation members as before
Screen& home(); // cursor movement functions
Screen& forward();
Screen& back();
Screen& up();
Screen& down();
};
class Screen {
public:
// other interface and implementation members as before
// Action is pointer that can be assigned any of the cursor movement members
typedef Screen& (Screen::*Action)();
static Action Menu[]; // function table
public:
// specify which direction to move
enum Directions { HOME, FORWARD, BACK, UP, DOWN };
Screen& move(Directions);
};
Screen& Screen::move(Directions cm)
{
// fetch the element in Menu indexed by cm
// run that member on behalf of this object
(this->*Menu[cm])();
return *this;
}
// What's left is to define and initialize the table itself:
Screen::Action Screen::Menu[] = { &Screen::home,
&Screen::forward,
&Screen::back,
&Screen::up,
&Screen::down,
};
Screen myScreen;
myScreen.move(Screen::HOME); // invokes myScreen.home
myScreen.move(Screen::DOWN); // invokes myScreen.down