成员指针
成员函数指针并非常规的指针
- 成员指针分为成员函数指针 和数据成员指针 。数据成员指针 /虚函数成员指针并没有真的指向一个内存 ,仅仅是表示在当前类,那个字段的位置 。如:
&X::value
表示的只是这个数据成员value
在类X
中的位置。- 数据成员指针 /虚函数成员指针是一种类似于偏移量 的东西,而成员函数指针真正的存储了一个地址。
- 成员指针无法脱离类的实例对象单独使用 ,无论是非静态数据成员指针还是非静态成员函数指针。
- 静态数据成员和静态成员函数不与类关联,不参与这个成员指针的讨论。
代码存储位置:shanchuann /Modern_CPP
成员函数指针
1 |
|
使用更为直观的传参的方式
1 | struct X |
注:当你的左操作数为引用或普通实例时,访问成员指针时使用
.*
运算符,而为指针时采用->*
运算符。
1 | struct X |
成员函数重载
问:如何确定绑定的是哪个成员函数呢?
答:使用static_cast
指定类型的成员函数为成员函数指针进行类型转换来消除歧义。
1 | struct Test_bind |
输出:
1 | t(int n) |
同样的,其他普通函数的重载也可以通过此方式解决。
注:
operator.*
不可以重载,但operator->*
可以
1
2
3
4
5
6
7
8
9
10
11
12 struct X {
void f() { cout << "1" << endl; }
template<typename Ty>
auto operator->*(Ty p) {
return (this->*p)();
}
};
int main() {
X x;
x->*& X::f; // 通过重载的`operator->*`调用成员函数 //1
}
数据成员指针
1 | struct X |
与绑定成员函数指针类似,我们直接得到了x对象的数据成员x的引用 /
传参写法
1 | struct X |
这些一般由我们间接使用,如C++17中的invoke
1 | class Test { |
成员访问运算符
运算符名 | 语法 | 可重载 | 原型实例(对于class T )类定义内 |
原型实例(对于class T )类定义外 |
---|---|---|---|---|
下标 | a[b] |
是 | R &T::operator[](S b);``R &T::operator[](S1 s1, ...); |
N /A |
间接寻址 | *a |
是 | R &T::operator*(); |
R &operator*(T a); |
取地址 | &a |
是 | R* T::operator &(); |
R* operator &(T a); |
对象的成员 | a.b |
否 | N /A | N /A |
指针的成员 | a->b |
是 | R* T::operator->() |
N /A |
指向对象的成员的指针 | a.*b |
否 | N /A | N /A |
指向指针的成员的指针 | a->*b |
是 | R &T::operator->*(S b); |
R &T::operator->*(T a,S b); |
- 下标运算符 :C++23起支持多参数下标操作
- 成员运算符(. 和 .*) :不可重载,这是C++的语法限制
- 类定义外重载 :只有部分运算符支持在类外重载为全局函数
- 返回类型 R :表示运算符的返回类型,具体取决于实现
内建的下标(subscript)运算符内提供对指针或数组操作数所指对象的访问。对于数组arr
和索引i
,arr[i]
等价于*(arr + i)
内建的 间接寻址(indirection)运算符 提供对它的指针操作数所指向的对象或函数的访问。
内建的 取地址 (address of)运算符 创建指向它的对象或函数操作数的指针。
对象的成员 和 指向对象的成员的指针 运算符提供对它的对象操作数的教据成员或成员函数的访问。
内建的 指针的成员 和 指向指针的成员的指针运算符 提供对它的指针操作数所指向的类的数据成员或成员函数的访问。
成员指针都存什么
普通成员函数指针
普通的成员函数指针存储明确的地址
1 | struct X { |
由于MSVC管制较严,所以采用G++进行编译
数据成员指针
存储的为偏移量而非明确地址
1 | struct X { |
虚成员函数指针
同样的,虚函数成员存储的也为偏移量
1 | struct X { |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 山川不念旧!
评论