C++成员解除引用运算符详解:数据与函数指针的正确用法

蓝鲸
蓝鲸
发布时间:2026-10-16 | 3人浏览过
原创

在 C++ 中,成员解除引用运算符提供了一种灵活的操作类内部结构的方式。它允许程序在运行时动态选择要访问的成员变量或调用的成员函数,而非在编译期硬编码。掌握这一特性对于编写通用的容器管理或策略模式代码至关重要。

结果与目标

使用 C++ 的成员指针,可以在不改变类定义的情况下,让同一套逻辑操作不同的数据成员(如 feet 与 inches)或执行不同的行为(如 show_in() 与 show_ft())。这将提升代码的复用性与可配置性。

准备条件

  1. 理解对象内存模型:类的成员变量是特定对象的一部分,但“指向成员的指针”并不直接指向具体的内存地址,而是指向该类结构中该成员的偏移量位置。
  2. 基础语法知识:熟悉 &(取地址)、.(成员访问)、->(指针解引用)以及 *(解引用运算符)。
  3. 开发环境:支持 C++98 及以上标准的编译器(如 GCC, Clang, MSVC)。

真实操作顺序

第1步:定义包含多个同类型成员的结构体

为了演示成员指针的灵活性,首先定义一个包含两个整型成员变量的类。这里以测量单位为例,定义英尺 (feet) 和英寸 (inches)。

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 仅是一个符号标识符。只有创建了对象(如 Example ob;),该成员才拥有实际的内存空间。

第2步:声明并初始化指向数据成员的指针

声明指向成员的指针需使用 类名::成员名 格式,并赋值时加上取地址符 &。注意,此处的 Example::* 表示这是一个属于 Example 类的成员指针。

// pt 是指向 Example 类中 int 类型成员的指针
int Example::*pt = &Example::inches;

此时 pt 本身不包含任何对象的值,它仅仅记录了 “inches 在这个类里的位置”。

第3步:使用成员解除引用运算符访问数据

要实际获取数据,必须将成员指针与具体的对象实例结合。核心规则如下:

  • obj.*ptr:当对象是实体时使用点号(.)。
  • ptr_obj->*ptr:当对象是通过指针访问时使用箭头(->)。
Example ob1;
Example ob2;
Example *pq = new Example;

// 访问 ob1 对象中由 pt 指向的成员(当前为 inches)
cout << ob1.*pt << endl;

// 访问 pq 所指向对象中由 pt 指向的成员
cout << pq->*pt << endl;

如果希望操作同一个对象的其他成员,只需重新赋值 pt:

pt = &Example::feet; // 现在 pt 指向 feet 成员
// ob1.*pt 将返回 feet 的值,而非 inches

第4步:声明指向成员函数的指针

指向成员函数的指针比普通函数指针复杂,必须包含返回值类型、参数列表以及所属类。由于普通函数指针不需要指定所属类(通常默认为全局),成员函数指针必须在括号内标明类域。

// 声明指向 返回void、无参、const 修饰的成员函数的指针
void (Example::*pf)()const;

第5步:调用成员函数

赋值后,可以通过对象调用该函数。关键点在于:调用表达式必须被括号包围,否则编译器可能会错误解析优先级。

// 关联具体的方法
pf = &Example::show_in;

Example ob3(20);

// 正确写法:先进行成员解引用得到函数名,再进行调用
(ob3.*pf)();

由于 show_in() 和 show_ft() 签名完全一致,我们可以随时切换 pf 的行为:

pf = &Example::show_feet;
(ob3.*pf)(); // 现在输出的是 feet 的内容

完成判断

当程序运行 car.use_ptr() 或 van.use_ptr() 时,观察控制台输出的变化。如果在 use_ptr 内部动态更改了 pt 或 pf 的值,且 cout 输出的数值确实对应了修改后的字段或执行了预期的打印函数,即说明成员解除引用机制工作正常。完整的逻辑验证可以参考下方的综合示例。

综合示例代码

以下代码展示了如何在类内部方法中使用成员指针操作自身 this 以及其他外部对象 yard。

#include <iostream>
using namespace std;

class Example {
private:
    int feet;
    int inches;
public:
    Example() : feet(0), inches(0) {}
    Example(int ft) : feet(ft), inches(12*ft) {}
    ~Example() {}

    void show_in() const { cout << inches << " inches\n"; }
    void show_ft() const { cout << feet << " feet\n"; }

    void use_ptr() const {
        Example yard(3); // 局部对象

        // --- 测试数据成员指针 ---
        int Example::*pt;
        pt = &Example::inches;
        cout << "Set pt to &Example::inches:\n";
        // 使用 this 指针访问调用者的成员
        cout << "this->*pt: " << this->*pt << endl; 
        // 使用局部对象访问其成员
        cout << "yard.*pt: " << yard.*pt << endl;

        pt = &Example::feet;
        cout << "Set pt to &Example::feet:\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);
    cout << "car.use_ptr() output:\n";
    car.use_ptr();
    cout << "\nvan.use_ptr() output:\n";
    van.use_ptr();
    return 0;
}

排错提示

  1. 优先级混淆:最常见的错误是忘记给函数调用加括号,写成 *ob3.pf 而不是 (ob3.*pf)()。前者会先解引用指针再访问成员,导致语义错误。
  2. 类型不匹配:指向成员变量的指针必须确保源和目标类型一致(如 int 对 int),指向函数的指针必须确保参数列表、返回值及 const 属性完全一致。
  3. 丢失 & 符号:给成员指针赋值时,必须使用 &ClassName::MemberName,直接写 ClassName::MemberName 会报错。

简要总结

C++ 的成员解除引用运算符(.* 和 ->*)是实现细粒度控制的核心工具。通过分离“位置的定位”(成员指针声明)与“目标的访问”(对象实例操作),程序员可以构建出高度抽象的数据处理逻辑。无论是遍历不同属性的数组,还是在运行时决定算法执行路径,这都是一项不可或缺的技术。以上就是C++成员解除引用运算符的详细内容,更多关于C++高级指针技巧的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表