我遇到了这个奇怪的代码片段,它编译得很好:

class Car
{
    public:
    int speed;
};

int main()
{
    int Car::*pSpeed = &Car::speed;
    return 0;
}

为什么c++有这个指针指向类的非静态数据成员?在实际代码中,这个奇怪的指针有什么用呢?


当前回答

我喜欢*和&运算符:

struct X 
{ 
    int a {0}; 
    int *ptr {NULL};

    int &fa() { return a; }
    int *&fptr() { return ptr; }
};

int main(void) 
{
    X x;
    int X::*p1 = &X::a;     // pointer-to-member 'int X::a'. Type of p1 = 'int X::*'
    x.*p1 = 10;

    int *X::*p2 = &X::ptr;  // pointer-to-member-pointer 'int *X::ptr'. Type of p2 = 'int *X::*' 
    x.*p2 = nullptr;
    X *xx;
    xx->*p2 = nullptr;

    int& (X::*p3)() = X::fa; // pointer-to-member-function 'X::fa'. Type of p3 = 'int &(X::*)()'
    (x.*p3)() = 20; 
    (xx->*p3)() = 30;

    int *&(X::*p4)() = X::fptr;  // pointer-to-member-function 'X::fptr'. Type of p4 = 'int *&(X::*)()'
    (x.*p4)() = nullptr; 
    (xx->*p4)() = nullptr;
}

事实上,只要成员是公共的或静态的,所有都是真的

其他回答

它是一个“指向成员的指针”——下面的代码说明了它的用法:

#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周围的括号是必要的,因为->*操作符的优先级低于函数调用操作符。

我认为,只有当成员数据相当大(例如,另一个相当庞大的类的对象),并且您有一些外部例程,只对该类的对象引用起作用时,才会想要这样做。你不想复制成员对象,所以这让你可以传递它。

使用指向成员的指针,我们可以编写这样的泛型代码

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;
}

一个指向成员的指针的真实例子可以是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

IBM有更多关于如何使用它的文档。简单地说,您使用指针作为类的偏移量。你不能在它们所指向的类之外使用这些指针,所以:

  int Car::*pSpeed = &Car::speed;
  Car mycar;
  mycar.*pSpeed = 65;

It seems a little obscure, but one possible application is if you're trying to write code for deserializing generic data into many different object types, and your code needs to handle object types that it knows absolutely nothing about (for example, your code is in a library, and the objects into which you deserialize were created by a user of your library). The member pointers give you a generic, semi-legible way of referring to the individual data member offsets, without having to resort to typeless void * tricks the way you might for C structs.