C++的类成员指针的语法
来源:互联网 发布:centos 7iso镜像安装 编辑:程序博客网 时间:2024/06/01 10:08
近日项目中使用了C++的类成员指针的语法,所以写了本博客分享一下。
有两点要特别指出的是:
(1)在不知道这个语法之前,我们通过指针访问类的成员变量或成员函数,一般都是将其定义为static,这样再在外部访问。一个寻常的例子是线程回调函数。
(2)这种语法,无论是类成员变量指针,还是类成员函数指针,其指针必须是与类对象伴生的。如果没有类对象,那么类成员指针其实是没有意义的!这一点请读者搞明白!
一、指向成员变量的指针并非指针
C++中指向成员变量的指针其实是一个相对于类对象的偏移量。《C++必知必会》的条款15讲述了这一说法:“与常规指针不同,一个指向成员变量的指针并不指向一个内存位置。它指向的是一个类的特定成员,而不是指向一个特定对象里的特定成员。通常最清晰的做法是将指向数据成员的指针看作为一个偏移量。......。这个偏移量告诉你,一个特定成员的位置距离对象的起点有多少个字节。”
示例代码如下:
/*一、指向成员变量的指针并非指针class member variables*/class DemoClass{public: DemoClass() : m_a(100),m_b(3) { } // .... public: int m_0; int m_a; int m_b;};int DemoClass::*pClassMemberVariable = NULL; // ipm是一个指针,指向类DemoClass的一个int成员,该处初始化为0 void testMemberVariablePointer(){ DemoClass aC; cout << &(aC.m_a) << endl; // 0x22fecc cout << &(aC.m_b) << endl; //ipm = &(aC.m_a); // 编译错误: cannot convert 'int*' to 'int DemoClass::*' in assignment pClassMemberVariable = &DemoClass::m_a; // ok cout << pClassMemberVariable << endl; //注意!!!有偏移量了! cout << aC.*pClassMemberVariable << endl; //cout << *pClassMemberVariable << endl; //编译错误:error C2171: “*”:“int DemoClass::* ”类型的操作数非法 //cout << aC.pClassMemberVariable << endl;//编译错误:error C2039: “pClassMemberVariable”: 不是“DemoClass”的成员 cout << aC.m_a << endl; // 100 aC.*pClassMemberVariable = 99; //语法解释:pClassMemberVariable相当于一个类属指针,通过偏移量的方式指向m_a的地址。 //所以,pClassMemberVariable其实并不是一个真实的指针,你不能通过使用*pClassMemberVariable //的方式来访问它。 cout << aC.m_a << endl; // 99 pClassMemberVariable = &DemoClass::m_b; //更改pClassMemberVariable的偏移量 cout << pClassMemberVariable << endl; //注意!!!偏移量改变了! DemoClass *pC = &aC; cout << pC->m_a << endl; // 99 pC->*pClassMemberVariable = 1001; // 这个用法等价于 aC.*pClassMemberVariable = 99; cout << aC.m_a << " | " << pC->m_a << " | " << pC->*pClassMemberVariable << endl; // 1001 | 1001 | 1001 cout << aC.m_b << " | " << pC->m_b << " | " << pC->*pClassMemberVariable << endl; // 1001 | 1001 | 1001 }
由此可见,给定一个成员变量在类中的偏移量,为了访问位于那个偏移量的数据成员,我们还需要该类的一个对象的地址。这时候就需要用到 .* 和 ->* 两个操作符了。其实这两个操作符也没啥新奇的。. 和 ->分别为对象和对象指针的成员访问操作符, 而 * 则为解引用操作符。当写下 aC.*pClassMemberVariable 时,其实就是请求将 aC的地址加上pClassMemberVariable所表示的偏移量,然后访问该 aC 所表示的对象中的特定数据成员。当写下 pC->*pClassMemberVariable 时,其实就是pC所指向的地址加上pClassMemberVariable所表示的偏移量,然后访问pC所指向的对象中的特定数据成员。
贴两个pClassMemberVariable 改变的运行截图:
二、指向成员函数的指针并非指针
获取非静态成员函数的地址时,得到的不是一个地址,而是一个指向成员函数的指针。为了对一个指向成员函数的指针进行解引用,需要一个对象或一个指向对象的指针。因为通过指向成员函数的指针调用该函数时,需要将对象的地址用作this指针的值,以便进行函数调用(当然,也有其它的用途)。
下面是一段“指向成员函数指针”使用的示例代码:
/*二、指向成员函数的指针并非指针class member function*/struct Point{ int x; int y;};class Shape{public: // .... /*virtual*/ void moveTo(Point newLocation) { cout << "Shape::(" << newLocation.x << ", " << newLocation.y << ")" << endl; } bool validate() const { cout << "Shape::validate()" << endl; return true; } virtual bool draw() const = 0; // .... };class Circle : public Shape{ // .... //virtual void moveTo(Point newLocation) //{ // cout << "Circle::(" << newLocation.x << ", " << newLocation.y << ")" << endl; //} virtual bool draw() const { return true; } // .... };void (Shape::*pClassMemberFunction)(Point) = NULL;void testMemberFunctionPointer(){ pClassMemberFunction = &Shape::moveTo; Circle circle; //pClassMemberFunction = &circle.moveTo; // 编译错误:ISO C++ forbids taking the address of a bound member function to form a pointer to member function. Say '&Circle::moveTo' Point pt; pt.x = 9999; pt.y = 9999; (circle.*pClassMemberFunction)(pt); // 通过对象直接调用 .* pt.x = 888; (&circle->*pClassMemberFunction)(pt); Shape *ps = &circle; (ps->*pClassMemberFunction)(pt); // 通过指针调用 ->* void (Circle::*pClassMemberFunction2)(Point) = &Shape::moveTo; (circle.*pClassMemberFunction2)(pt); void (Shape::*pClassMemberFunction3)(Point) = &Circle::moveTo; (circle.*pClassMemberFunction3)(pt); bool (Shape::*pmV)() const = 0; pmV = &Shape::validate; (circle.*pmV)();}
主函数如下:
int main(int argc, char**argv){ testMemberVariablePointer(); testMemberFunctionPointer(); return 0;}
以上代码中vs2017中编译运行通过。其他编译器,请读者自行尝试。
- C++的类成员指针的语法
- C++_Primer_chapter18 3.类成员的指针
- 含有指针成员的类的拷贝[C/C++/C#]
- 类成员的指针
- 类的成员指针
- C/C++学习笔记:指向类成员变量的指针
- 成员函数的指针(C++)
- C++:指向对象成员函数的指针
- 【boolan c++】 带有指针成员的class
- C语言的指针的基本语法
- 静态类成员的指针
- 类成员函数的指针
- 类的成员函数指针
- 指向类成员的指针
- C++类的成员指针
- 类的成员函数指针
- 指向类成员的指针
- 指向类成员的指针
- 控件
- 【贪心】Allowance POJ 3040
- 嵌入式学习8(scanf函数的注意事项)
- HDU 1024 Max Sum Plus Plus (dp)
- python 字符串转为日期
- C++的类成员指针的语法
- 软文
- SAPUI5教程——更改ODataModel默认的请求方式
- leetcode之Find Minimum in Rotated Sorted Array 问题
- 配置tomcat运行网站
- POJ 1611 The Suspects(并查集)
- Unity中贴图融合之弹痕融合
- 八、rabbitMQ RPC
- Arrays-----118. Pascal's Triangle