C++ Primer学习笔记——$22 类成员指针

转载 2011年01月19日 15:16:00

题记:本系列学习笔记(C++ Primer学习笔记)主要目的是讨论一些容易被大家忽略或者容易形成错误认识的内容。只适合于有了一定的C++基础的读者(至少学完一本C++教程)。

 
作者: tyc611, 2007-04-07
   本文主要讨论C++中类成员的指针,这部分内容少有使用,也比较难于理解。
   如果文中有错误或遗漏之处,敬请指出,谢谢!
   需要使用类成员指针的情况是比较少见的,所以一般没人使用这个语言特性。下面先介绍类成员指针的使用方法,再介绍它的可能应用场合。
 
   有时,我们需要在类外的其它地方直接获得类成员,这时我们就需要使用类成员指针。类成员指针与对象的指针不同,它不仅包括类的类型,还包括成员的类型。成员指针只应用于类的非static成员,因为static类成员不是任何对象的组成部分,只需使用普通指针即可。
 
声明成员指针
 
   借用书上的一个例子,有这么一个类:
   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;
   };
  
   若要声明contents成员的指针,应有如下形式:
      string Screen::*ps;
   若要声明cursor、height或width成员的指针,应有如下形式:
      Screen::index Screen::*pi;
 
   从上面的使用形式可以看出,使用类成员的指针与普通指针的区别在于,需要在类成员指针前面的加上类限定符,以指明是哪个类的成员指针。同样,在初始化指针时,也只能用相应类的相应类型的成员对指针进行初始化,例如:
      ps = &Screen::contents;
      pi = &Screen::cursor;
 
   上面介绍了对类数据成员的指针的使用方法,下面对函数成员的指针进行介绍。
 
   函数成员的指针与普通函数指针相比,也多了类限定符。由于类成员函数还有可能是const,所以const也成为成员函数指针声明的一部分。也就是说,函数成员的指针必须在三个方面与它所指函数的类型相匹配:
   (1)函数形参的类型和数目;
   (2)返回类型及是否为const函数;
   (3)所属类的类型。
 
   例如,要定义Screen的get成员的指针,可以如下定义:
      char (Screen::*pmf)() const = &Screen::get; // not 'Screen::get'!
      char (Screen::*pmf2)(Screen::index, Screen::index) const;
      pmf2 = &Screen::get;
这里需要注意的是:(1)这里不存在函数类型到函数指针类型的自动转换(即类成员函数前面必须加上&,然后再给相应指针赋值);(2)运算符的优先级关系(注意指针外层的括号所起的作用);(3)函数到指针的自动类型匹配(注意两个重载版本的get对指针的赋值)。
 
使用类成员指针
 
   要使用类成员指针所指对象,首先应当从类对象取得成员指针,再解引用指针,所以有如下两种操作符供使用:.*和->*。这两个操作符的左操作数必须是类类型的对象或类类型的指针,右操作数是该类型的成员指针。例如:
   Screen sc;
   char c = (sc.*pmf)();  // 等价于调用sc.get();
   Screen *pS = ≻
   c = (pS->*pmf)();
 
   下面给出成员指针使用的完整例子,以方便读者更好的理解:
#include <string>

class Screen {
    friend void func();
// 声明func为类Screen的友元,否则无法使用类成员
public:
    typedef std::string::size_type index;
    char get() const {
        return 'a';
    }
    char get(index ht, index wd) const {
        return 'b';
    }
private:
    std::string contents;
    index cursor;
    index heigth, width;
};

void func()
{
    std::string Screen:: *ps = &Screen::contents;
    Screen::index Screen:: *pi = &Screen::cursor;
    char (Screen:: *pmf) () const = &Screen::get;
// not 'Screen::get'!
    char (Screen:: *pmf2) (Screen::index, Screen::index) const;
    pmf2 = &Screen::get;
    
    Screen sc;
    Screen *pS = &sc;
    Screen::index idx = sc.*pi;
    idx = pS->*pi;
    char c = (sc.*pmf)();
// 等价于调用sc.get();
    c = (pS->*pmf)();
}

int main()
{
    void (*pf)() = func// 注意普通函数的指针的初始化,与成员指针比较
    pf();
    return 0;
}
 
成员指针的应用举例
 
   当一个类有多个性质相同且类型相同的函数成员时,可以使用函数表来进行函数调用,产生用同一函数使用不同参数来达到不同操作的效果,而实际上是调用了不同的函数来实现的。下面给出这样的一个例子,方便读者有一个感性的认识:
#include <iostream>
using namespace std;

class Screen {
public:
    Screen& home() {
        cout << "Home" << endl;
        return *this;
    }
    Screen& forward() {
        cout << "Forward" << endl;
        return *this;
    }
    Screen& back() {
        cout << "Back" << endl;
        return *this;
    }
    Screen& up() {
        cout << "Up" << endl;
        return *this;
    }
    Screen& down() {
        cout << "down" << endl;
        return *this;
    }
    
// function table
    typedef Screen& (Screen:: *Action)();
    static Action Menu[];
    
// specify which direction to move
    enum Directions {HOME, FORWARD, BACK, UP, DOWN};
    Screen& move(Directions);
};

Screen::Action Screen::Menu[] = {&Screen::home, &Screen::forward, &Screen::back, &Screen::up, &Screen::down};

Screen& Screen::move(Directions dirc)
{
    (this->*Menu[dirc])();
    return *this;
}

int main()
{
    Screen sc;
    sc.move(Screen::HOME);
    sc.move(Screen::UP);
    return 0;
}
 

参考文献:
[1] C++ Primer(Edition 4)
[2] Thinking in C++(Edition 2)
[3] International Standard:ISO/IEC 14882:1998

相关文章推荐

C++Primer学习笔记103 特殊工具与技术 类成员指针

特殊工具与技术                                                                                            ...

2012/1/22 《C++ Primer Plus》第十章:对象和类 学习笔记

《C++ Primer Plus》第十章学习笔记 这一章实在重要,提出了颠覆面向过程编程的一种新的思维方法(OOP)。重点:理解抽象,封装,数据隐藏等的概念。 附上复习题第二题及答案:   Q...
  • Zyearn
  • Zyearn
  • 2012年01月22日 19:54
  • 837

C++ Primer学习笔记(7)——指针形参和引用形参的比较

前面讲到了巧用引用形参可以达到很好地目的。还有一种是指针形参,它用的比较少,专用于数组形参。问:什么时候应使用指针形参?什么时候应使用引用形参?两者的优缺点是什么?...

C++ Primer 学习笔记(三)——数组和指针

首先需明确,现代C++程序应尽量使用vector和迭代器类型,而避免使用低级的数组和指针。设计良好的程序只有在强调速度时才在类实现的内部使用数组和指针。 一、数组 1、数组的定义和初始化 (1)...

C++primer学习笔记——引用和指针

引用和指针基本

C++ Primer 学习笔记——第4章 数组和指针

C++ Primer 学习笔记—— 第4章 数组和指针 数组和Vector的区别是:数组的长度是固定的,也就是说Vector的长度是可变的.这就是为什么objC有Array和MutableArray,...
  • eminia
  • eminia
  • 2011年07月30日 01:14
  • 512

C++ Primer 学习笔记_23_函数(续2) --局部对象、内联函数、类的成员函数

函数 --局部对象内联函数类的成员函数 一局部对象二内联函数三类的成员函数 函数 --局部对象、内联函数、类的成员函数 一、局部对象     在C++语言中,每个名字都有作用域,每个...

C++ Primer 学习笔记_22_函数(续1) --return语句、递归调用、函数声明

函数 --return语句、递归调用、函数声明 三、return语句 1、没有返回值的函数     在返回值类型为void的函数中,return返回语句不是必需的,隐式的return发生在函数的...

C++primer学习笔记-----6.7函数指针

【函数指针指向的是函数而非对象。和其他指针一样,函数指针指向某种特定类型。函数的类型由它的返回类型和形参类型共同决定,与函数名无关。bool lengthCompare(const string &,...

【C++Primer学习笔记】第4章 数组和指针

1、现代C++程序中应尽量使用vector和迭代器类型,而避免使用低级的数组和指针。设计良好的程序只有在强调速度时才在类实现的内部使用数组和指针。   2、与vector类型相比,数组的显著缺陷在...
  • left_la
  • left_la
  • 2012年05月04日 16:47
  • 647
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++ Primer学习笔记——$22 类成员指针
举报原因:
原因补充:

(最多只允许输入30个字)