我遇到了这个奇怪的代码片段,它编译得很好:
class Car
{
public:
int speed;
};
int main()
{
int Car::*pSpeed = &Car::speed;
return 0;
}
为什么c++有这个指针指向类的非静态数据成员?在实际代码中,这个奇怪的指针有什么用呢?
我遇到了这个奇怪的代码片段,它编译得很好:
class Car
{
public:
int speed;
};
int main()
{
int Car::*pSpeed = &Car::speed;
return 0;
}
为什么c++有这个指针指向类的非静态数据成员?在实际代码中,这个奇怪的指针有什么用呢?
当前回答
为了给@anon和@Oktalist的回答添加一些用例,这里有一份关于指向成员函数的指针和指向成员数据的阅读材料。
https://www.dre.vanderbilt.edu/~schmidt/PDF/C++-ptmf4.pdf
其他回答
一个指向成员的指针的真实例子可以是std::shared_ptr的更窄的混叠构造函数:
template <typename T>
template <typename U>
shared_ptr<T>::shared_ptr(const shared_ptr<U>, T U::*member);
构造函数有什么用
假设你有一个结构体foo:
struct foo {
int ival;
float fval;
};
如果你给了一个foo对象一个shared_ptr对象,你可以使用构造函数将shared_ptr对象检索到它的成员ival或fval:
auto foo_shared = std::make_shared<foo>();
auto ival_shared = std::shared_ptr<int>(foo_shared, &foo::ival);
如果想将指针foo_shared->ival传递给某个需要shared_ptr的函数,这将非常有用
https://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr
使用指向成员的指针,我们可以编写这样的泛型代码
template<typename T, typename U>
struct alpha{
T U::*p_some_member;
};
struct beta{
int foo;
};
int main()
{
beta b{};
alpha<int, beta> a{&beta::foo};
b.*(a.p_some_member) = 4;
return 0;
}
您可以使用指向(同构)成员数据的指针数组来启用双重命名成员(即x.data)和数组下标(即x[idx])接口。
#include <cassert>
#include <cstddef>
struct vector3 {
float x;
float y;
float z;
float& operator[](std::size_t idx) {
static float vector3::*component[3] = {
&vector3::x, &vector3::y, &vector3::z
};
return this->*component[idx];
}
};
int main()
{
vector3 v = { 0.0f, 1.0f, 2.0f };
assert(&v[0] == &v.x);
assert(&v[1] == &v.y);
assert(&v[2] == &v.z);
for (std::size_t i = 0; i < 3; ++i) {
v[i] += 1.0f;
}
assert(v.x == 1.0f);
assert(v.y == 2.0f);
assert(v.z == 3.0f);
return 0;
}
指向类的指针不是真正的指针;类是一个逻辑构造,在内存中没有物理存在,然而,当你构造一个指向类成员的指针时,它会给出一个指向该成员所在类的对象的偏移量;这给出了一个重要的结论:由于静态成员不与任何对象相关联,因此指向成员的指针不能指向静态成员(数据或函数) 考虑以下几点:
class x {
public:
int val;
x(int i) { val = i;}
int get_val() { return val; }
int d_val(int i) {return i+i; }
};
int main() {
int (x::* data) = &x::val; //pointer to data member
int (x::* func)(int) = &x::d_val; //pointer to function member
x ob1(1), ob2(2);
cout <<ob1.*data;
cout <<ob2.*data;
cout <<(ob1.*func)(ob1.*data);
cout <<(ob2.*func)(ob2.*data);
return 0;
}
来源:完整参考c++ - Herbert Schildt第四版
它是一个“指向成员的指针”——下面的代码说明了它的用法:
#include <iostream>
using namespace std;
class Car
{
public:
int speed;
};
int main()
{
int Car::*pSpeed = &Car::speed;
Car c1;
c1.speed = 1; // direct access
cout << "speed is " << c1.speed << endl;
c1.*pSpeed = 2; // access via pointer to member
cout << "speed is " << c1.speed << endl;
return 0;
}
至于你为什么要这样做,它给了你另一种间接的层次,可以解决一些棘手的问题。但说实话,我从未在自己的代码中使用过它们。
编辑:我想不出一个令人信服的使用指针成员数据。指向成员函数的指针可以在可插拔的体系结构中使用,但是在这么小的空间里生成一个例子再次让我感到挫败。以下是我最好的(未经测试)尝试-一个Apply函数,在应用用户选择的成员函数到对象之前,会做一些前后处理:
void Apply( SomeClass * c, void (SomeClass::*func)() ) {
// do hefty pre-call processing
(c->*func)(); // call user specified function
// do hefty post-call processing
}
c->*func周围的括号是必要的,因为->*操作符的优先级低于函数调用操作符。