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