成员指针运算符 .* 和 ->*

本文介绍了成员指针的概念及其使用方法,包括如何声明指向类成员变量和成员函数的指针,并展示了通过成员指针访问成员的具体操作。

有一种特殊的指针叫做成员指针,它们通常指向一个类的成员,而不是对象中成员的特定实例。

成员指针并不是真正的指针,它只是成员在对象中的偏移量,它们分别是:.* 和 ->* 。

下面例子说明了成员指针 .* 的用法:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include "stdafx.h"
#include <iostream>
using namespace std;
 
 
class myclass {
public:
    int sum;
    void myclass::sum_it(int x);
};
 
 
void myclass::sum_it(int x)
{
    int i;
    sum = 0;
    for (i = x; i; i--) sum += i;
}
 
 
int _tmain(int argc, _TCHAR* argv[])
{
    int myclass::*dp;        //指向 myclass 中整数类型成员变量的指针
    void (myclass::*fp)(int x);        //指向 myclass 中成员函数的指针
    myclass c;
 
 
    dp = &myclass::sum;        //获得成员变量的地址
    fp = &myclass::sum_it;    //获得成员函数的地址
 
 
    (c.*fp)(7);        //计算 1 到 7 相加的和
    cout << "summation of 7 is " << c.*dp;
 
 
    return 0;
}
运行输出: summation of 7 is 28


在上面程序中,创建了两个成员指针 dp 和 fp 。其中 dp 指向了成员变量 sum ,fp 指向了函数 sum_it() 。

需要注意指针的声明语法:在声明中使用了作用域解析运算符来指定指针指向的成员属于那个类。

当使用对象或对象引用来访问对象的成员时,必须使用 .* 运算符,如程序中的 c.*fp 和 c.*dp 这种用法。

如果使用指向对象的指针来访问对象的成员,那么必须使用 ->* 运算符,如下程序示例:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include "stdafx.h"
#include <iostream>
using namespace std;
 
 
class myclass {
public:
    int sum;
    void myclass::sum_it(int x);
};
 
 
void myclass::sum_it(int x)
{
    int i;
    sum = 0;
    for (i = x; i; i--) sum += i;
}
 
 
int _tmain(int argc, _TCHAR* argv[])
{
    int myclass::*dp;        //指向 myclass 中整数类型成员变量的指针
    void (myclass::*fp)(int x);        //指向 myclass 中成员函数的指针
     
    myclass *c, d;            //变量 c 显示是指向对象的指针
    c = &d;                    //将对一个对象的地址赋给 c
 
 
 
 
    dp = &myclass::sum;        //获得成员变量的地址
    fp = &myclass::sum_it;    //获得成员函数的地址
 
 
    (c->*fp)(7);        //计算 1 到 7 相加的和
    cout << "summation of 7 is " << c->*dp;
 
 
    return 0;
}
运行输出:summation of 7 is 28

上面程序中,变量 c 是指向 myclass 类型对象的指针,所以应该使用 ->* 运算符来访问 sum 和 sum_it() 。

成员指针是为了处理特殊情况而设计,在一般程序设计中通常不需要用到他们。



FROM: http://vipjy2008.blog.163.com/blog/static/372087672013933226346/

<think> 首先,用户的问题是关于C++中成员运算符.->的优先级比较。他们想知道哪个的优先级更高。 从系统级指令中,我需要: - 所有行内数学表达式用$...$格式。 - 独立公式用$$...$$格式并单独成段。 - 确保LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 在回答中引用的段落末尾自然地添加引用标识,例如[^1]。 - 回答结构清晰,帮助用户逐步解决问题。 - 保证回答真实可靠。 用户提供了几个引用: - 引用[1]:讨论了&->的优先级,说明->的优先级高于&。还提到了优先级表,其中->在优先级1中,而&在优先级2中。 - 引用[2]:C++运算符优先级列表,显示::优先级最高,然后是++、--后缀等。 - 引用[3]:解释了.->运算符的使用,但没直接比较优先级。 我需要基于这些引用我的知识来回答。我知道在C++中,成员运算符.->的优先级是相同的,因为它们都属于同一优先级级别。 回想C++运算符优先级: - 最高优先级包括::(作用域解析)、后缀++--、函数调用()、下标[]、成员访问.->。 - 在标准优先级表中,.->通常被列为同一优先级级别,优先级最高或次高。 检查引用: - 引用[1]中的优先级表显示: 1. []、()、.-> 2. -、(类型)、++、--*、&、!、~、sizeof 这表明.->都在优先级1,相同优先级。 - 引用[2]列表: 2. ++、--(后缀)、()、{}、()、[]、.-> 3. ++、--(前缀)等 所以.->都在优先级2(在引用[2]中序号为2),相同。 - 引用[3]没有直接比较优先级。 因此,.->的优先级是相同的。这意味着在表达式中,它们具有相同的结合性优先级,不会因为优先级不同而导致歧义。 在表达式中,如果有多个运算符,优先级高的先计算。但由于.->优先级相同,它们的结合性如何?通常,成员访问运算符是左结合的,即从左到右计算。 例如: - obj.member1.member2:先计算obj.member1,然后访问member2。 - ptr->member1->member2:如果ptr是指针,ptr->member1可能返回另一个指针,然后->member2。 所以,优先级相同,结合性是左结合。 回答结构: 1. **明确回答**:直接说.->的优先级相同。 2. **解释**:引用优先级表,说明它们在同一个优先级级别。 3. **结合性**:解释是左结合。 4. **示例**:给出例子说明。 5. **引用**:在引用内容后添加引用标识。 6. **相关问题**:生成相关问题。 使用中文回答。 生成相关问题: - 基于主题,如其他运算符的优先级、结合性的影响、常见错误等。 完整回答: - 开头:总结答案。 - 中间:详细解释,包括优先级表例子。 - 结尾:添加相关问题。 确保LaTeX:如果有数学表达式,但这里可能不需要,除非有方程。用户的问题是关于运算符优先级,可能不需要复杂数学。如果有变量或简单表达式,用$...$。 例如,在例子中,如果有代码,用代码块。但系统指令要求独立公式用$$...$$,但代码不是公式,所以用代码块如示例所示。 在示例中,有代码块: ```python ... ``` 所以我可以类似地使用代码块展示例子。 最终回答结构: 1. 直接回答优先级相同。 2. 解释优先级表。 3. 讨论结合性。 4. 给出例子。 5. 引用来源。 6. 相关问题。 </think> 根据您的问题,我将逐步解释C++中成员运算符`.`(点运算符`->`(箭头运算符)的优先级比较。参考提供的引用资料C++标准运算符优先级规则,以下是详细分析: ### 1. **优先级比较结论** - **`.``->`的优先级相同**。两者都属于最高优先级级别(通常列为第2级或第1级,取决于具体优先级表),在表达式中具有相同的计算顺序[^1][^2]。 - 例如: - 表达式`obj.member->sub_member`中,先计算`obj.member`,再计算`->sub_member`。 - 表达式`ptr->data.value`中,先计算`ptr->data`,再计算`.value`。 - 这是因为在C++运算符优先级表中,`.``->`被归为同一组,优先级高于其他运算符(如`&`、`*`、`+`等)[^1][^2]。 ### 2. **优先级表参考** 以下是简化的C++运算符优先级表(基于引用[1][2]),突出显示`.``->`的位置: | 优先级 | 运算符 | 名称 | 结合性 | 说明 | |---------|--------|------|---------|------| | 1 | `::` | 作用域解析 | 左到右 | 最高优先级 | | **2** | **`()`**<br>**`[]`**<br>**`.`**<br>**`->`** | 函数调用<br>数组下标<br>成员访问(对象)<br>成员访问(指针) | 左到右 | **`.``->`优先级相同,高于大多数运算符** | | 3 | `++`、`--`(前缀)<br>`!`、`~`<br>`&`、`*` | 自增/自减<br>逻辑非/按位取反<br>取地址/解引用 | 右到左 | 优先级低于成员访问 | 关键点: - **结合性为左到右**:当多个`.`或`->`连续出现时,从左向右计算[^1][^2]。 - 例如:`a.b.c` 等价于 `(a.b).c`。 - **优先级高于其他运算符**:在混合表达式中,成员运算符优先计算: - `&obj->member` 等价于 `&(obj->member)`(因为`->`优先级高于`&`)[^1]。 - `*ptr.data` 等价于 `*(ptr.data)`(因为`.`优先级高于`*`)。 ### 3. **示例说明 ```cpp #include <iostream> struct Data { int value; }; struct Object { Data data; }; int main() { Object obj; Object* ptr = &obj; obj.data.value = 42; // 正确: 先计算 obj.data,再访问 .value ptr->data.value = 42; // 正确: 先计算 ptr->data,再访问 .value // 错误示例:如果优先级不同,但实际优先级相同 // int* p = &ptr->data; // 等价于 &(ptr->data),不会歧义 std::cout << ptr->data.value << std::endl; // 输出 42 return 0; } ``` - 在`ptr->data.value`中: 1. 先计算`ptr->data`(访问指针成员)。 2. 再计算`.value`(访问嵌套成员)。 - 这验证了`.``->`优先级相同且左结合。 ### 4. **常见误区与注意事项** - **对象与指针的区别**:`.`用于对象实例(如`obj.member`),`->`用于对象指针(如`ptr->member`),但优先级规则一致[^3]。 - **错误避免**:虽然优先级相同,但错误使用类型会导致编译错误: - `Object* ptr;` - `ptr.value` // 错误:指针需用`->`,而非`.` - **结合性影响**:在链式访问中(如`a->b.c`),从左向右计算,确保逻辑清晰。 ### 引用来源 [^1]: 优先级表中,`->``.`属于同一高优先级组,高于取地址`&`解引用`*`等运算符[^1]。 [^2]: C++运算符列表确认成员访问运算符(`.``->`)优先级相同,位于第2级[^2]。 [^3]: 点运算符应用于实际对象,箭头运算符用于指针,但优先级规则无差异[^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值