类的成员变量偏移指针和成员函数指针

本文详细介绍了C++中类成员变量偏移指针的概念及其使用方法,并通过实例展示了如何操作这些指针。此外,还讲解了类成员函数指针的声明和使用技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 1、类的成员变量的偏移指针

这是个特殊的指针

class A
{
public:
	int x;
	int y;
};


&A::x和&A::y就表示类A的数据成员偏移指针。

 int _tmain(int argc, _TCHAR* argv[])
{
printf("%p\n", &A::x);
printf("%p\n", &A::y);
}

输出:0和4

 

int A::*是一个类型,表示类A中的成员变量偏移指针,这个指针值类型为int型。

int A::* p;
p=&A::x;

语法为:<mem_type> <class_type>::* 

表示为:某类的某个成员类型的偏移指针

 &<class_type>::<mem_name> 为类成员的偏移指针值。

<对象>.*<偏移指针值>和 <对象指针>->*<偏移指针值>:表示为偏移指针应用到对象上后的数据成员的值。

例如:
int A::* p1=&A::x; 
A a a.*p1=3; 
A* pA; pA->*p1=4;

int memadd(const A& ca, int A::* a, int A::* b)  
{  
    return ca.*a + ca.*b;  
}  
A a;
int n = memadd(a, &A::x, &A::y);

成员变量偏移指针是一种特殊的指针,你无法给它赋予自定义数值。如果给它赋值为NULL,会自动设置为0xFFFFFFFF,如果设置为某个数值,编译无法通过。只能赋值为&A::x这样的编译期常量。

int A::* p;
p = NULL;
p = &A::x;
p = 0x4; //编译出错

2、类的成员函数指针

假设有类:

class A
{
public:
	int x;

	int foo(int n)
	{
		return n;
	}
};


那么该类的成员函数foo的指针声明如下:

int (A::*)(int)

typedef int(A::* FuncType)(int);

使用方式如下:

	A a, *pA=&a;
	FuncType f = &A::foo;
	(a.*f)(3);
	(pA->*f)(3);

注意:(a.*f)和(pa->*f)别忘记两边的双括号,否则编译不通过。


 

<think>我们首先需要明确几个关键概念: 1. 在C++中,成员变量指针(pointer to member)普通指针是不同的型。 2. 成员函数指针(pointer to member function)普通函数指针也是不同的型。 问题:成员变量指针是否可以用来调用非静态成员函数? 注意:这里要区分“成员变量指针成员函数指针”。它们是两个不同的概念。 根据引用[1]引用[2]: - 静态成员函数相当于普通函数,其指针型也是普通函数指针型。 - 非静态成员函数必须通过对象(或对象指针)来调用,并且其指针型是“成员函数指针型(带有作用域)。 但是,用户的问题中提到了“成员变量指针”,即指向成员的指针,它指向的是成员变量(数据成员),而不是成员函数。 因此,我们需要澄清: 1. 成员变量指针(pointer to data member)用于访问特定对象的成员变量。 2. 成员函数指针(pointer to member function)用于调用特定对象的成员函数。 所以,问题中的“成员变量指针”不能用来调用非静态成员函数,因为: - 成员变量指针存储的是成员变量布局中的偏移量,它用于访问数据成员,而不是调用函数。 - 调用非静态成员函数需要使用成员函数指针,并且必须绑定到一个对象上。 举例说明: 假设有一个A: ```cpp class A { public: int data; void func() { std::cout << "Hello"; } }; ``` 1. 成员变量指针: ```cpp int A::* pData = &A::data; // 成员变量指针 A a; a.*pData = 10; // 通过成员变量指针访问a的data成员 ``` 2. 成员函数指针: ```cpp void (A::* pFunc)() = &A::func; // 成员函数指针 (a.*pFunc)(); // 通过成员函数指针调用a的func成员函数 ``` 结论:成员变量指针(指向数据成员的指针)不能用来调用成员函数(无论是静态还是非静态)。调用成员函数必须使用成员函数指针。 但是,如果用户误将“成员变量指针”理解为“指向对象的指针(即对象指针)”,则对象指针可以用来调用非静态成员函数。例如: ```cpp A* pObj = new A(); pObj->func(); // 通过对象指针调用非静态成员函数 ``` 所以,我们需要根据用户的问题字面意思来回答:成员变量指针不能调用非静态成员函数。 同时,引用[3]中提到,静态成员函数可以通过对象指针来调用非静态成员函数(间接调用),但这与成员变量指针无关。 因此,回答如下: 在C++中,成员变量指针(即指向数据成员的指针)不能用来调用非静态成员函数成员变量指针仅用于访问的数据成员,而调用非静态成员函数需要以下两种方式之一: 1. 使用对象(或对象引用)结合点运算符(`.`)来调用。 2. 使用对象指针(指向对象的指针)结合箭头运算符(`->`)来调用。 3. 使用成员函数指针(指向成员函数指针)结合对象(或对象指针)来调用。 示例: ```cpp class MyClass { public: int data; void nonStaticFunc() { /* ... */ } }; // 成员变量指针 int MyClass::* pData = &MyClass::data; // 成员函数指针 void (MyClass::* pFunc)() = &MyClass::nonStaticFunc; MyClass obj; MyClass* pObj = &obj; // 使用成员变量指针访问数据 obj.*pData = 10; pObj->*pData = 20; // 使用成员函数指针调用函数 (obj.*pFunc)(); (pObj->*pFunc)(); ``` 注意:成员变量指针成员函数指针都是与关联的,而不是与具体的对象关联。在使用时,需要绑定到一个具体的对象(或对象的指针)上。 因此,直接使用成员变量指针来调用非静态成员函数在语法上是不允许的,也是没有意义的。 如果用户实际想表达的是“通过指向对象的指针(即对象指针)来调用非静态成员函数”,那么答案是肯定的。但根据问题中的术语“成员变量指针”,答案是否定的。 为了明确,我们总结如下: | 指针型 | 用途 | 能否调用非静态成员函数 | |--------------------|------------------------------|----------------------| | 成员变量指针 | 访问的数据成员 | 否 | | 成员函数指针 | 调用成员函数 | 是(需绑定对象) | | 对象指针(普通) | 指向对象的指针,可访问成员 | 是(通过`->`运算符) | 所以,用户的问题“C++ 成员变量指针是否可以用来调用非静态成员函数”的答案是:**不可以**。 最后,生成相关问题: 1. 如何正确使用C++中的成员函数指针? 2. 静态成员函数指针非静态成员函数指针有什么区别? 3. 在C++中,如何通过对象指针调用非静态成员函数? 4. 成员变量指针成员函数指针在内存表示上有何不同?</think>### 成员变量指针能否调用非静态成员函数? **不可以直接调用**。成员变量指针(如 `int ClassName::*`)与成员函数指针(如 `void (ClassName::*)()`)是两种完全不同的型,在C++中有本质区别: #### 1. **成员变量指针的本质** 成员变量指针存储的是**成员在内的偏移量**,而非实际内存地址: ```cpp class MyClass { public: int data; // 成员变量 void func() {} // 成员函数 }; int main() { int MyClass::* pData = &MyClass::data; // ✅ 成员变量指针 // void (MyClass::* pFunc)() = &MyClass::data; // ❌ 编译错误:型不匹配 } ``` 成员变量指针: - 仅用于访问**数据成员**(如 `obj.*pData`) - 无法存储函数地址 - 不能通过它调用函数[^2] #### 2. **调用非静态成员函数的正确方式** 必须通过**成员函数指针**绑定到具体对象: ```cpp void (MyClass::* pFunc)() = &MyClass::func; // ✅ 成员函数指针 MyClass obj; (obj.*pFunc)(); // 通过对象调用 MyClass* pObj = new MyClass(); (pObj->*pFunc)(); // 通过对象指针调用 ``` 关键点: - 成员函数指针型必须包含名:`void (ClassName::*)()` - 调用时必须绑定对象(`obj.*` 或 `ptr->*`)[^2] #### 3. **静态 vs 非静态成员函数** | **特性** | **静态成员函数** | **非静态成员函数** | |------------------------|-----------------------------------|-----------------------------------| | **指针型** | 普通函数指针 `void (*)()` | 作用域指针 `void (ClassName::*)()` | | **调用方式** | `ClassName::Func()` 或 `(*pFunc)()` | `obj.Func()` 或 `(obj.*pFunc)()` | | **访问非静态成员** | ❌ 禁止访问 | ✅ 可直接访问 | | **`this`指针** | 不存在 | 隐含 `this` 指针 | 静态成员函数指针可像普通函数指针使用,但**不能访问非静态成员**: ```cpp static void StaticFunc(); void (*pStatic)() = &MyClass::StaticFunc; // ✅ 等同于普通函数指针 pStatic(); // 直接调用 ``` #### 4. 为什么需要区分? - **内存模型差异**:成员函数需通过隐式 `this` 指针访问对象数据 - **安全性**:防止未绑定对象时访问无效内存 - **标准规定**:C++型系统严格区分数据指针函数指针 > 当需要将成员函数作为回调时(如线程函数),可通过静态函数+对象指针间接调用非静态成员[^3]: > ```cpp > static void ThreadWrapper(void* obj) { > static_cast<MyClass*>(obj)->nonStaticFunc(); > } > pthread_create(..., ThreadWrapper, this); > ``` ### 总结 | **操作** | **是否可行** | **原因** | |------------------------|--------------|------------------------------| | 成员变量指针调用函数 | ❌ | 型不匹配,存储的是偏移量 | | 成员函数指针调用函数 | ✅ | 需绑定具体对象 | | 静态函数指针调用函数 | ✅ | 等同于普通函数指针 | | 通过对象调用非静态函数 | ✅ | 标准用法(`obj.func()`) | **结论**:成员变量指针**不能**用来调用非静态成员函数,必须使用正确型的成员函数指针并绑定到对象。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值