C++中的类成员指针
写在前面:本博客为本人原创,严禁任何形式的转载!本博客只允许放在博客园(.cnblogs.com),如果您在其他网站看到这篇博文,请通过下面这个唯一的合法链接转到原文!
本博客全网唯一合法URL:http://www.cnblogs.com/acm-icpcer/p/6729273.html
C++中的类成员指针
在上一篇文章中我提到了C++中的函数指针。那么如果想定义一个指向类数据成员或者函数成员的指针,又该怎么办呢?
本质上讲和之前我提到的写法没有什么不同,只不过是要加上域定义而已。
1.类数据成员指针
例如,对于下面的类A:
class A
{
public:
int x;
int sayhello()
{
cout<<"hello world"<<endl;
}
};
假如我想定义一个指向数据成员x的指针,则:
int A::*pointer1 = &A::x;
很明显,去掉域定义其实就是普通的指针定义:int pointer1=&x;
那么,如果用typedef来简化语法就是:
typedef int A::*int_pointer;
int_pointer pointer2 = &A::x;
两者是等价的。
调用指针时则为:
A a;
a.*pointer1 = ;
++(a.*pointer2);
cout << &a->*pointer1 << endl;
结果为7。(注意:必须声明一个A的对象才可以调用类数据成员指针)
那么这个类数据成员指针究竟是地址还是什么呢?
为了搞清楚,我们就把它打出来看看吧:
cout << pointer1 << endl << pointer2 << endl;
结果是1 1。
这是什么意思呢?实际上,类数据成员指针只是相对于对象在内存中初始地址的一个偏移量,也就是说,它是一个相对地址。
2.类函数成员指针
现在,我们讨论一下类函数成员指针的定义和使用。我们的讨论建立在以下类A和类B的基础上来讲:
class A
{
private:
int y;
public:
double w;
int x;
int sayhello()
{
cout<<"hello world"<<endl;
}
}; class B:public A
{ };
类成员函数指针定义:
int (A::*classAfunctionpointer1)();
classAfunctionpointer1 = &A::sayhello;
可以看到,这其实也是在普通的全局函数指针前面加上了一个域定义而已(普通全局函数指针:int (*classAfunctionpointer1)();)。
那么,如果用typedef来简化语法就是:
typedef int (A::*FP)();
FP classAfunctionpointer2 = &A::sayhello;
调用时都是一样的:
(a.*classAfunctionpointer1)();
(a.*classAfunctionpointer2)();
或者
(&a->*classAfunctionpointer1)();
(&a->*classAfunctionpointer2)();
结果都是打印出hello world。(注意:类成员函数指针在使用前必须先声明一个对象)
那么,类B继承了类A,理论上讲B也可以使用A的指针:
B b;
(b.*classAfunctionpointer1)();
确实可以,结果也是打印出hello world。
那么这又是为什么呢?
实际上,类成员函数的地址是绝对的,因为类成员函数是定义在一个固定的代码区中。当年使用不同的对象去调用同一个类成员函数的时候,本质上,编译器会把该对象的this指针默认加在该成员函数的形参列表中,以便让函数明白是谁在调用它。所以不同的对象去调用同一个类成员函数的时候,编译器才能理解并作出反应。
3.示例代码
好了,根据上面讲到的所有基础知识,我给出如下程序:
#include<iostream>
using namespace std; class A
{
private:
int y;
public:
double w;
int x;
int sayhello()
{
cout<<"hello world"<<endl;
}
}; class B:public A
{ }; typedef int A::*int_pointer;
typedef int (A::*FP)(); int main()
{
int A::*pointer1 = &A::x;
int_pointer pointer2 = &A::x;
A a;
a.*pointer1 = ;
++(a.*pointer2);
cout << &a->*pointer1 << endl << pointer1 << endl << pointer2 << endl; double A::*pointer3 = &A::w;
cout<<pointer3<<endl; B b;
a.sayhello();
int (A::*classAfunctionpointer1)();
classAfunctionpointer1 = &A::sayhello;
FP classAfunctionpointer2 = &A::sayhello;
(a.*classAfunctionpointer1)();
(a.*classAfunctionpointer2)();
(&a->*classAfunctionpointer1)();
(b.*classAfunctionpointer1)(); return ;
}
TZ
2017/4/18于华中农业大学
C++中的类成员指针的更多相关文章
- C/C++基础----特殊工具和技术 (重载new和delete,RTT,限定作用域的枚举类型,类成员指针,嵌套类,局部类,volatile,链接指示 extern “C”)
重载new和delete 1调用operator new( 或new[])标准库函数分配足够大的.原始的.未命名的内存空间以便存储特定类型的对象 2编译器运行相应地构造函数以构造这些对象,并为其传入初 ...
- C++ 类成员指针
C++的类成员指针是一种奇葩的指针. 假设现在我们要表示一个三维的点,现在有两种定义方式: struct point1{ int x, y, z; }; struct point2{ int c[3] ...
- C++中static类成员
static局部变量 static局部变量确保不迟于在程序执行流程第一次经过该对象的定义语句时进行初始化 这种对象一旦被创建,在程序结束前不会被撤销.在该函数被多次调用的过程中,静态局部对象会持续存在 ...
- C++ Primer 笔记——类成员指针
1.当我们初始化一个成员指针或为成员指针赋值时,该指针并没有指向任何数据.成员指针指定了成员而非成员所属的对象,只有当解引用成员指针时,我们才提供对象信息. 2.和普通的函数指针类似,如果成员存在重载 ...
- C++类成员指针(指向类成员的指针)
1.指向类的数据成员的指针: 声明格式如下: <类型说明符> <类名>::* <指针变量名>; 2.指向类的成员函数的指针: 声明格式如下: <类型说明符 ...
- [转载] C++ 类中的类成员变量怎么调用带参数的构造函数来初始化?
#include "stdafx.h" class A { public: A(){ax = ;}; A(int a){ax = a;}; int ax; }; class B { ...
- 详解C++中基类与派生类的转换以及虚基类
很详细!转载链接 C++基类与派生类的转换在公用继承.私有继承和保护继承中,只有公用继承能较好地保留基类的特征,它保留了除构造函数和析构函数以外的基类所有成员,基类的公用或保护成员的访问权限在派生类中 ...
- 成员指针与mem_fn
本文是<functional>系列的第4篇. 成员指针是一个非常具有C++特色的功能.更低级的语言(如C)没有类,也就没有成员的概念:更高级的语言(如Java)没有指针,即使有也不会有成员 ...
- C#中增量类功能的方式之 继承与扩展
之前一次公司培训的时候,将它记录下来,https://www.cnblogs.com/AlvinLee/p/10180536.html这个博客上面比较全面. 1.扩展方法 扩展方法是一种特殊的静态方法 ...
随机推荐
- FFmpeg X264的preset和tune
鉴于x264的参数众多,各种参数的配合复杂,为了使用者方便,x264建议如无特别需要可使用preset和tune设置.这套开发者推荐的参数较为合理,可在此基础上在调整一些具体参数以符合自己需要,手动设 ...
- codeforces水题100道 第一题 Codeforces Beta Round #1 A. Theatre Square (math)
题目链接:http://www.codeforces.com/problemset/problem/1/A题意:至少用多少块边长为a的方块铺满NxM的矩形区域.C++代码: #include < ...
- Form表单验证神器: BootstrapValidator
前言:做Web开发的我们,表单验证是再常见不过的需求了.友好的错误提示能增加用户体验.博主搜索bootstrap表单验证,搜到的结果大部分都是文中的主题:bootstrapvalidator.今天就来 ...
- Objective-c官方文档 怎么使用对象
版权声明:原创作品,谢绝转载!否则将追究法律责任. 对象发送和接受消息 尽管有不同的方法来发送消息在对象之间,到目前位置是想中括号那样[obj doSomeThing]:左边是接受消息的接收器,右 ...
- WP8.1学习系列(第十七章)——交互UX之输入和反馈模式
如果你将 Windows 应用商店应用设计为触摸交互,则可免费获取对触摸板.鼠标.笔和键盘交互的支持.你的用户可以从一种输入法切换到另一种,而不会丧失应用体验的感觉.将键盘插入平板电脑?没问题.你的应 ...
- Qt编写数据库通用翻页demo(开源)
在Qt与数据库结合编程的过程中,记录一多,基本上都需要用到翻页查看记录,翻页有个好处就是可以减轻显示数据的表格的压力,不需要一次性将数据库表的记录全部显示,也基本上没有谁在一页上需要一次性显示所有记录 ...
- 【大数据系列】hadoop脚本分析
一.start-all.sh hadoop安装目录/home/hadoop/hadoop-2.8.0/ libexec/hadoop-config.sh ---设置变量 sbin/start- ...
- C#串口介绍以及简单串口通信程序设计实现
C#串口介绍以及简单串口通信程序设计实现 周末,没事干,写个简单的串口通信工具,也算是本周末曾来过,废话不多,直接到主题 串口介绍 串行接口简称串口,也称串行通信接口或串行通讯接口(通常指COM接口) ...
- Android NDK学习(4)使用cygwin生成.so库文件
转:http://www.cnblogs.com/fww330666557/archive/2012/12/14/2817389.html 简单的示例: makefile文件: LOCAL_PATH: ...
- SSL是什么?如何使用?
SSL(Secure Sockets Layer 安全套接层),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议.TLS与 ...