C++ 指向数组元素的成员指针

C++ 指向数组元素的成员指针,c++,class,pointers,C++,Class,Pointers,可以定义指向成员的指针,并在以后使用: structfoo { INTA; int b[2]; }; int main() { 富吧; intfoo::*aptr=&foo::a; bar.a=1; 标准::cout 但是,编译器只是抱怨“非静态数据成员'foo::b'的使用无效” 这是因为foo::a和foo::b有不同的类型。更具体地说,foo::b是大小为2的ints数组。指针声明必须兼容,即: int (foo::*aptr)[2]=&foo::b; 有没有可能做到这一点(或者

可以定义指向成员的指针,并在以后使用:

structfoo
{
INTA;
int b[2];
};

int main() {
富吧; intfoo::*aptr=&foo::a; bar.a=1; 标准::cout 但是,编译器只是抱怨“非静态数据成员'foo::b'的使用无效”

这是因为
foo::a
foo::b
有不同的类型。更具体地说,
foo::b
是大小为2的
int
s数组。指针声明必须兼容,即:

int (foo::*aptr)[2]=&foo::b;
有没有可能做到这一点(或者至少没有工会)

是的,见下文:

struct foo
{
  int a;
  int b[2];
};

int main()
{

  foo bar;

  int (foo::*aptr)[2]=&foo::b;
  /* this is a plain int pointer */
  int *bptr=&((bar.*aptr)[1]);

  bar.a=1; 
  bar.b[0] = 2;
  bar.b[1] = 11;

  std::cout << (bar.*aptr)[1] << std::endl;
  std::cout << *bptr << std::endl;
}
structfoo
{
INTA;
int b[2];
};
int main()
{
富吧;
int(foo::*aptr)[2]=&foo::b;
/*这是一个普通的int指针*/
int*bptr=&((bar.*aptr)[1]);
bar.a=1;
bar.b[0]=2;
bar.b[1]=11;
标准::cout
一切顺利

使用成员和函数指针的小技巧。
试着写

char c = &foo::b; // or any other function or member pointer
在Compiler error中,您将看到您的案例的预期类型
int(foo::*)[2]

编辑

我不确定没有此指针您想要的东西是否合法。如果要向指针添加1个偏移量,您应该从成员数组上的指针获取数组上的指针。但是您可以在没有此指针的情况下取消对成员指针的引用。

问题是,访问数组中的项是访问纯整数的另一个间接层次。如果该数组相反,作为指针,您不会期望能够通过成员指针访问int

struct foo
{
  int a;
  int *b;
};

int main()
{

  foo bar;
  int foo::* aptr=&(*foo::b); // You can't do this either!
  bar.a=1;
  std::cout << bar.*aptr << std::endl;
}
structfoo
{
INTA;
int*b;
};
int main()
{
富吧;
int foo::*aptr=&(*foo::b);//您也不能这样做!
bar.a=1;

std::cout您不能在语言本身之外执行此操作。但您可以使用boost。将函子绑定到该数组的某个元素,并将其分配给
boost::function

#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/function.hpp>
#include <iostream>

struct test {
    int array[3];
};

int main() {
    namespace lmb = boost::lambda;

    // create functor that returns test::array[1]
    boost::function<int&(test&)> f;
    f = lmb::bind(&test::array, lmb::_1)[1];

    test t = {{ 11, 22, 33 }};
    std::cout << f(t) << std::endl; // 22

    f(t) = 44;
    std::cout << t.array[1] << std::endl; // 44
}
#包括
#包括
#包括
#包括
结构测试{
int数组[3];
};
int main(){
名称空间lmb=boost::lambda;
//创建返回test::array[1]的函子
boost::函数f;
f=lmb::bind(&test::array,lmb::_1)[1];
测试t={11,22,33};

std::cout我不确定这是否适用于您,但我想做一件类似的事情,并通过从另一个方向处理问题来解决它。在我的类中,我有几个对象,我希望可以通过命名标识符访问这些对象或在循环中迭代。而不是创建指向对象中某个位置的成员指针数组中,我只是单独声明了所有对象,并创建了指向这些对象的成员指针的静态数组

像这样:

struct obj
{
    int somestuff;
    double someotherstuff;
};

class foo
{
  public:
    obj apples;
    obj bananas;
    obj oranges;

    static obj foo::* fruit[3];

    void bar();
};

obj foo::* foo::fruit[3] = { &foo::apples, &foo::bananas, &foo::oranges };


void foo::bar()
{
    apples.somestuff = 0;
    (this->*(fruit[0])).somestuff = 5;
    if( apples.somestuff != 5 )
    {
        // fail!
    }
    else
    {
        // success!
    }
}



int main()
{
    foo blee;
    blee.bar();
    return 0;
}

这似乎对我有用。我希望这能有所帮助。

2020更新,实际解决方案:

  • 该标准目前没有指定任何实际使用成员指针的方法,以允许算术或任何方法获取指向“内部”数组元素的指针
  • OTOH,标准库现在已经具备了自己修补适当的成员指针类的所有必要条件,即使使用数组元素访问也是如此
首先,成员指针通常被实现为“仅偏移量”,尽管这相当可怕

结构{inta;浮点b[10];}; 浮点数(S::*mptr)[10]=&S::b; *重新解释\u cast(&mptr)//这是4 int S::*iptr=&S::a; *重新解释\u cast(&iptr)//这是0 iptr=nullptr; *重新解释演员表(&iptr)//这似乎是我盒子上的18446744073709551615
相反,您可以制作一个小包装器(它很长,但我不想删除便利操作符):

#包括
模板
班级成员
{
尺寸\u t关闭\u;
公众:
成员_ptr():off_(0){}
成员ptr(大小偏移量):off(偏移量){
/*成员访问*/
friend const T&operator->*(const M*a、const member_ptr&p)
{return(*a)->*p;}
friend T&operator->*(M*a,施工员\U ptr&p)
{return(*a)->*p;}
/*运算符。*不能重载,因此只需再次使用箭头即可*/
friend const T&operator->*(const M&a、const member_ptr&p)
{return*reinterpret_cast(reinterpret_cast(&a)+p.off_u)}
friend T&operator->*(并购、施工成员\u ptr&p)
{return*reinterpret_cast(reinterpret_cast(&a)+p.off_u)}
/*将数组访问转换为数组元素访问*/
成员_ptr运算符*()常量
{返回成员(关闭)}
/*立即使用偏移量也一样*/
成员ptr运算符[](大小偏移)常量
{返回成员\u ptr(off)+offset;}
/*一些操作员*/
成员(ptr&operator++)()
{off_+=sizeof(T);返回*this;};
成员兼操作员——()
{off_u-=sizeof(T);返回*this;};
成员_ptr运算符++(int)
{member_ptr copy;off_+=sizeof(T);return copy;};
成员ptr运算符--(int)
{member_ptr copy;off_-=sizeof(T);return copy;};
成员ptr和操作员+=(大小偏移)
{off_+=offset*sizeof(T);返回*this;}
成员ptr和操作员-=(大小偏移)
{off_u-=offset*sizeof(T);返回*this;}
成员ptr运算符+(大小偏移)常量
{自动复制=*此;复制+=偏移量;返回复制;}
成员ptr运算符-(大小偏移)常量
{auto copy=*this;copy-=偏移量;return copy;}
size_t offset()常量{return off_;}
};
模板
会员制会员制(TM:*a)
{return member_ptr(reinterpret_cast(&((M*)nullptr)->*a));}
现在我们可以使指针直接指向数组元素:

auto-mp=make_-member_-ptr(&S::b)[2];
S S;
s->*mp=123.4;
//s.b[2]现在预计为123.4
最后,如果您真的非常喜欢物化引用,您可能会得到一点haskell lensish,并让它们组合:

//在类成员\u ptr中,注意类型M->T->TT的传递性:
模板
成员ptr操作员+(常量成员ptr&t)
{return member_ptr(off_u+t.offset());}
//测试:
结构A{int A;};
结构B{A arr[10];};
bx;
自动p=生成成员
struct foo
{
  int a;
  int *b;
  int c[2];

  int &GetA() { return a; } // changed to return references so you can modify the values
  int &Getb() { return *b; }
  template <int index>
  int &GetC() { return c[index]; }
};
typedef long &(Test::*IntAccessor)();

void SetValue(foo &f, IntAccessor ptr, int newValue)
{  
    cout << "Value before: " << f.*ptr();
    f.*ptr() = newValue;
    cout << "Value after: " << f.*ptr();
}

int main()
{
  IntAccessor aptr=&foo::GetA;
  IntAccessor bptr=&foo::GetB;
  IntAccessor cptr=&foo::GetC<1>;

  int local;
  foo bar;
  bar.a=1;
  bar.b = &local;
  bar.c[1] = 2;

  SetValue(bar, aptr, 2);
  SetValue(bar, bptr, 3);
  SetValue(bar, cptr, 4);
  SetValue(bar, &foo::GetC<0>, 5);
}
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/function.hpp>
#include <iostream>

struct test {
    int array[3];
};

int main() {
    namespace lmb = boost::lambda;

    // create functor that returns test::array[1]
    boost::function<int&(test&)> f;
    f = lmb::bind(&test::array, lmb::_1)[1];

    test t = {{ 11, 22, 33 }};
    std::cout << f(t) << std::endl; // 22

    f(t) = 44;
    std::cout << t.array[1] << std::endl; // 44
}
struct obj
{
    int somestuff;
    double someotherstuff;
};

class foo
{
  public:
    obj apples;
    obj bananas;
    obj oranges;

    static obj foo::* fruit[3];

    void bar();
};

obj foo::* foo::fruit[3] = { &foo::apples, &foo::bananas, &foo::oranges };


void foo::bar()
{
    apples.somestuff = 0;
    (this->*(fruit[0])).somestuff = 5;
    if( apples.somestuff != 5 )
    {
        // fail!
    }
    else
    {
        // success!
    }
}



int main()
{
    foo blee;
    blee.bar();
    return 0;
}