C++成员解除引用运算符的示例详解

下面看下成员解除引用运算符,C++允许定义指向类成员的指针,对这种指针进行声明或解除引用时,需要使用一种特殊的表示法。
例:

class Example
{
private:
    int feet;
    int inches;
public:
    Example();
    Example(int ft);
    ~Example();
    void show_in()const;
    void show_ft()const;
    void use_ptr()const;
};

如果没有具体的对象,则inches成员只是一个标签。也就是说,这个类将inches定义为一个成员标识符,但要为它分配内存。必须声明这个类的一个对象:

Example ob;//现在ob.inches存在

因此,可以结合使用标识符inches和特定的对象,来引用实际的内存单元(对于成员函数,可以省略对象名,但对象被认为是指针执行对象)。
C++允许这样定义一个指向标识符inches的成员指针:

int Example::*pt = &Example::inchers;

这种指针与常规指针有所区别。常规指针指向特定的单元格,而pt指针并不是指向特定的内存单元,因为声明中没有指出具体的对象。指针pt指的是inches成员在任意Example对象中的位置。和标识符inches一样,pt被设计与对象标识符要求使用。实际上。表达式*pt对标识符inches的角色做了假设,因此,可以使用对象标识符来指定访问的对象,使用pt指针来指定该对象的inches成员。例如:类方法可以使用下面得的代码:

int Example::*pt = &Example::inches;
Example ob1;
Example ob2;
Example *pq = new Example;
cout<<ob1.*pt<<endl;//ob1对象的inches成员
cout<<ob2.*pt<<endl;//ob2对象的inches成员
cout<<po->*pt<<endl;//*po对象的inches成员

其中,*和->*都是成员解除运算符,声明对象后,ob1.*pi指的将是ob1对象的inches成员,同样,pq->*pt指的是pq指向的对象的inxhes成员。
改变上述示例中使用的对象,将改变使用的inches成员。不过也可以修改pt指针本身。由于feet的类型与inches相同,因此可以将pt重新设置为指向feet成员(而不指向inches成员),这样ob1.*pt将是ob1的feet成员:

pt = &Example::feet;
cout<<ob1.*pt<<endl;//*pt相当于成员名,可用标识(相同类型)其他成员

可以使用成员指针标识成员函数,其语法稍微复杂的。对于不带任何参数、返回值为void的函数,声明一个指向函数的指针:

void (*pf)();//pf 指向函数

声明指向成员函数指针时,必须指出该函数所属的类。例:

void (Example::*pf)()const;//pf指向类成员函数

表明pf可用于使用Example方法地方。且Example::*pf必须放在括号中,可以将特定成员函数的地址赋给指针:

pf = &Example::show_inches;

注意,与普通函数指针的赋值情况不同,这里必须使用地址运算符,完成赋值操作后,便可以使用一个对象来调用该成员函数:

Example ob3(20);
(ob3.*pf)();//使用ob3对象调用show_feet()

必须将ob3*p放在括号中,以明确地指出,该表达式表示的是一个函数名。
由于show_feet()原型与show_inches()相同,因此也可以使用pf来访问show_feet()方法:

pf = &Example::show_feet;
(ob3*pf)();//将show_feet()应用于ob3对象

例:
下面程序use_ptr()方法,使用成员指针来访问Example类的数据成员和函数成员。

#include <iostream>
using namespace std;
class Example
{
private:
    int feet;
    int inches;
public:
    Example();
    Example(int ft);
    ~Example();
    void show_in()const;
    void show_ft()const;
    void use_ptr()const;
};
Example::Example()
{
    feet=0;
    inches=0;
}
Example::Example(int ft)
{
    feet=ft;
    inches=12*feet;
}
Example::~Example()
{
}
void Example::show_in()const
{
    cout<<inches<<"inches\n";
}
void Example::show_ft()const
{
    cout<<feet<<"feet\n";
}
void Example::use_ptr()const
{
    Example yard(3);
    int Example::*pt;
    pt=&Example::inches;
    cout<<"Set pt to &Example::inches:\n";
    cout<<"this->pt:"<<this->*pt<<endl;
    cout<<"yard.*pt:"<<yard.*pt<<endl;
    pt=&Example::feet;
    cout<<"Set pt to &Example::inches:\n";
    cout<<"this->pt:"<<this->*pt<<endl;
    cout<<"yard.*pt:"<<yard.*pt<<endl;
    void (Example::*pf)()const;
    pf=&Example::show_in;
    cout<<"Set pf to &Example::show_in:\n";
    cout<<"Using (this->*pf)():";
    (this->*pf)();
    cout<<"Using (yard.*pf)():";
    (yard.*pf);
}
int main()
{
    Example car(15);
    Example van(20);
    Example garage;
    cout<<"car.usr_ptr() output:\n";
    car.use_ptr();
    cout<<"\nvan.use_ptr()outptr:\n";
    van.use_ptr();
    return 0;
}

本例子在编译期间给指针赋值,在更为复杂的类中,可以使用指向数据成员和方法的成员指针。以便在运行阶段确定与指针关联的成员。

到此这篇关于C++成员解除引用运算符的示例详解的文章就介绍到这了,更多相关C++解除引用运算符内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C++运算符重载详情介绍

    文章转自公众号:Coder梁(ID:Coder_LT) C++当中除了函数可以重载之外,其实运算符也是可以重载的.我们之前已经接触过一些,可能大家没有意识到. 举个例子,乘号*,运用在指针上,就是取值的意思,而运用在算数当中,则是乘法的意思.同样一个符号,用在不同的地方,起到了不同的效果.这其实就是一种重载,C++根据操作数的数目和类型来决定要使用哪一种操作. 另外C++允许将运算符重载扩展到用户自定义的类型,也就是结构体和类当中.比如,我们可以将重载加号,对两个对象相加. 其实这种用法也出现过

  • C++运算符重载限制介绍

    目录 一.重载限制 1.必须至少有一个操作数是用户定义的类型 2.不能违反运算符原来的规则 3.不能创建新运算符 4.禁止名单 5.部分运算符只能通过成员函数重载  文章转自公众号:Coder梁(ID:Coder_LT) 一.重载限制 上一篇我们讲了在类和结构体当中重载运算符,关于运算符的重载并不是随心所欲的.C++给出了一些限制,从而保证了规范,以及程序运行的准确性. 下面我们就来一一来看下: 1.必须至少有一个操作数是用户定义的类型 这句话看不明白没有关系,我们只需要记住它的目的就好了.它的

  • C++基础入门之运算符

    目录 1. 算术运算符 2. 赋值运算符 3. 比较运算符 4. 逻辑运算符 总结 1. 算术运算符 2. 赋值运算符 3. 比较运算符 4. 逻辑运算符 总结 本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我们的更多内容!

  • C++赋值运算符

    C++当中允许类对象赋值,这是通过默认的重载赋值运算符实现的,它的原型如下: Class_name & Class_name::operator=(const Class_name &); 它接受并返回一个指向类对象的引用. 将已有的对象赋给另一个对象时,将会使用重载的赋值运算符: StringBad headline1("Celery"); StringBad knot; knot = headline1; // 调用赋值运算符 如果是对象初始化的过程,则不一定会使用

  • C++成员解除引用运算符的示例详解

    下面看下成员解除引用运算符,C++允许定义指向类成员的指针,对这种指针进行声明或解除引用时,需要使用一种特殊的表示法.例: class Example { private: int feet; int inches; public: Example(); Example(int ft); ~Example(); void show_in()const; void show_ft()const; void use_ptr()const; }; 如果没有具体的对象,则inches成员只是一个标签.也

  • C++之值传递&指针传递&引用传递的示例详解

    目录 1.函数基础 2.值传递 3.指针传递 4.引用传递 1.函数基础 一个函数由以下四部分组成: 返回类型 函数名 参数(0个或多个) 函数体 其中,函数的参数叫做形参,函数执行的操作的语句块叫做函数体 2.值传递 像一个这样swap函数,调用的时候,会用实参初始化swap函数对应的形参 void Swap(int a, int b) { int tmp = a; a = b; b = tmp; } 在内存中会拷贝一份实参的值,但是修改形参的值并不影响实参的值 测试用例 #include <

  • JS中原始值和引用值的储存方式示例详解

    在ECMAscript中,变量可以存放两种类型的值,即原始值和引用值 原始值指的是代表原始数据类型的值,也叫基本数据类型,包括:Number.Stirng.Boolean.Null.Underfined 引用值指的是复合数据类型的值,包括:Object.Function.Array.Date.RegExp 根据数据类型不同,有的变量储存在栈中,有的储存在堆中.具体区别如下: 原始变量及他们的值储存在栈中,当把一个原始变量传递给另一个原始变量时,是把一个栈房间的东西复制到另一个栈房间,且这两个原始

  • python中前缀运算符 *和 **的用法示例详解

    这篇主要探讨 ** 和 * 前缀运算符,**在变量之前使用的*and **运算符. 一个星(*):表示接收的参数作为元组来处理 两个星(**):表示接收的参数作为字典来处理 简单示例: >>> numbers = [2, 1, 3, 4, 7] >>> more_numbers = [*numbers, 11, 18] >>> print(*more_numbers, sep=', ') 2, 1, 3, 4, 7, 11, 18 用途: 使用 * 和

  • vue实例成员 插值表达式 过滤器基础教程示例详解

    目录 一. 什么是Vue 二.为什么学Vue 三.如何使用Vue 下载安装? 插值表达式 四.vue特点 1.虚拟DOM 2.数据的双向绑定 3.单页面应用 4.数据驱动 五.Vue实例 六.实例成员 - 挂载点 | el - 自定义插值表达式括号| delimiters - 数据 | data - 过滤器 | filters - 方法 | methods - js对象(即字典)补充 - 插值表达式转义 | delimters - 计算属性 | computed - 监听属性 | watch 一

  • go语言结构体指针操作示例详解

    目录 指针 go指针操作 不能操作不合法指向 new函数 指针做函数的参数 数组指针 结构体指针变量 结构体成员普通变量 结构体成员指针变量 结构体比较和赋值 结构体作为函数参数 指针 指针是代表某个内存地址的值.内存地址储存另一个变量的值. 指针(地址),一旦定义了不可改变,指针指向的值可以改变 go指针操作 1.默认值nil,没有NULL常量 2.操作符“&”取变量地址,“*“通过指针(地址)访问目标对象(指向值) 3.不支持指针运算,不支持“->”(箭头)运算符,直接用“.”访问目标成

  • Go语言基础结构体用法及示例详解

    目录 概述 语法 结构体定义的三种形式 第一种[基本的实例化] 第二种[指针类型的结构体] 第三种[取结构体的地址实例化,通过&的操作] 初始化结构体 键值对初始化结构体 值列表填充结构体 匿名结构体 访问结构体成员 结构体作为函数参数 结构体指针 添加结构体方法 总结 示例 概述 结构体是由一系列具有相同类型或不同类型的数据构成的数据集合 语法 定义结构体[标识自定义结构体的名称,在同一个包内不能重复] type 结构名 struct { 字段1: 字段1的值, 字段2: 字段2的值, ...

  • C语言函数基础教程分类自定义参数及调用示例详解

    目录 1.  函数是什么? 2.  C语言中函数的分类 2.1 库函数 2.1.1 为什么要有库函数 2.1.2 什么是库函数 2.1.3 主函数只能是main()吗 2.1.4常见的库函数 2.2 自定义函数 2.2.1自定义函数是什么 2.2.2为什么要有自定义函数 2.2.3函数的组成 2.2.4 举例展示 3. 函数的参数 3.1 实际参数(实参) 3.2  形式参数(形参) 4. 函数的调用 4.1 传值调用 4.2  传址调用 4.3 练习 4.3.1. 写一个函数判断一年是不是闰年

  • javascrip高级前端开发常用的几个API示例详解

    目录 MutationObserver API 特点 IntersectionObserver API 举个例子 图片懒加载 无限滚动 getComputedStyle() API 与style的异同 getBoundingClientRect API 应用场景 1.获取 dom 元素相对于网页左上角定位的距离 2.判断元素是否在可视区域内 MutationObserver MutationObserver 是一个可以监听 DOM 结构变化的接口. 当 DOM 对象树发生任何变动时,Mutati

  • JavaScript展开运算符和剩余运算符的区别详解

    目录 什么是剩余运算符? 剩余运算符在JavaScript函数中是如何工作的? 注意!不能在包含剩余参数的函数体中使用"use strict" 剩余运算符在参数解构中是如何工作的? JavaScript arguments和剩余参数之间有哪些区别? 什么是展开运算符以及它在JavaScript中是如何工作的? 有关展开运算符我们需要知道的 1. 展开运算符不能展开对象字面量的值 2. 展开运算符不克隆相同的属性 3. 注意展开运算符在包含非原语的对象中是何如工作的 如果myName数组

随机推荐