`
javababy1
  • 浏览: 1161818 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

C++学习笔记(四)--指针(4)

 
阅读更多

类成员指针


本文主要讨论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;

indexcursor;

indexheight, width;

};

若要声明contents成员的指针,应有如下形式:

string Screen::*ps;

若要声明cursorheightwidth成员的指针,应有如下形式:

Screen::index Screen::*pi;

从上面的使用形式可以看出,使用类成员的指针与普通指针的区别在于,需要在类成员指针前面的加上类限定符,以指明是哪个类的成员指针。同样,在初始化指针时,也只能用相应类的相应类型的成员对指针进行初始化,例如:

ps = &Screen::contents;

pi = &Screen::cursor;

上面介绍了对类数据成员的指针的使用方法,下面对函数成员的指针进行介绍。

函数成员的指针与普通函数指针相比,也多了类限定符。由于类成员函数还有可能是const,所以const也成为成员函数指针声明的一部分。也就是说,函数成员的指针必须在三个方面与它所指函数的类型相匹配:

1)函数形参的类型和数目;

2)返回类型及是否为const函数;

3)所属类的类型。

例如,要定义Screenget成员的指针,可以如下定义:

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

源文档 <http://blog.chinaunix.net/u/18517/showart_272646.html>

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics