指向班级私人数据成员

时间:2016-03-13 23:50:59

标签: c++ class templates pointers pointer-to-member

考虑一个类card,它有两个公共成员int suitint value,以及一个模板函数,用于通过指针传递给成员的卡片排序。会员,像这样:

//class card with public members
class card{
 public:
    int suit;
    int value;
};   

//sorting algorithm
template<typename m_pointer, typename iterator, typename Functype>
void sort_array(m_pointer member, iterator begin, iterator end, Functype pred){
   iterator iter1=begin;
   while(iter1!=end && ++iter1!=end){
    iterator iter2=iter1;
    while(iter2!=begin){
        iterator iter3=iter2;
        --iter3;
        //here i use the pointer-to-member to sort the cards
        if(pred((*iter3).*member, (*iter2).*member)){
            std::swap(*iter3, *iter2);
        }
        else break;
        --iter2;
    }
  }
}

int main(){
  card array[3]={{3,1},{2,3},{4,5}};
  //let's sort the cards by the suit value in a decreasing order
  sort(&card::suit, array, array+3, [](int a, int b){return a<b;});
}

如果卡会员suit是公开的,那么显然没有问题,但实际上我没想到的是,即使我宣布相同的代码也不会给您带来任何麻烦<{1}}或suit为私人会员。

value

据我所知,我不能从类外部访问私有成员,并且将指向成员的指针传递给私有成员的唯一方法是通过成员函数返回成员地址,例如:

class card{
   int suit;
   int value;
  public://adding this for clarity, read forward
   int* pointer_to_suit();    
};

那么,为什么上面的代码(带模板的代码)可能有效?

修改 好的,上面的代码不能自己编译,但由于某种原因,下面的代码编译得很好。我发布了整个代码,因为我不知道工作的诀窍可能在哪里,抱歉这个烂摊子:

//function member of the class card
int* card::pointer_to_suit(){
   return &suit;
}

编辑2:是的,它运行http://coliru.stacked-crooked.com/a/d1795f0845770fcb。请注意,此处的代码未翻译,并且为了简洁,我还没有添加一些代码。

编辑3:正如Barry回答https://stackoverflow.com/a/35978073/5922196中提到的,这是一个template<typename m_pointer, typename iterator, typename Functype> void sort_array(m_pointer member, iterator begin, iterator end, Functype pred){ iterator iter1=begin; while(iter1!=end && ++iter1!=end){ iterator iter2=iter1; while(iter2!=begin){ iterator iter3=iter2; --iter3; if(pred((*iter3).*puntatore, (*iter2).*puntatore)){ std::swap(*iter3, *iter2); } else break; --iter2; } } } class card{ int suit; int value; public: card(): suit(0), value(0) {} card(int a, int b): suit(a), value(b){} bool operator==(card a){return (suit==a.get_s() && value==a.get_v());} bool operator!= (card a){return !(*this==a);} void set_values(int a, int b){suit=a; value=b;} int get_v(){return value;} void set_v(int v){value=v;} int get_s(){return suit;} void set_s(int s){suit=s;} double points_card(); }; template<typename iterator> void ordina(iterator begin, iterator end, short (&suit)[4]){ for(int i=0; i<4; i++) suit[i]=0; iterator it1=begin; while(it1!=end){ if((*it1).get_s()==1) suit[0]+=1; else if((*it1).get_s()==2) suit[1]+=1; else if((*it1).get_s()==3) suit[2]+=1; else if((*it1).get_s()==4) suit[3]+=1; ++it1; } sort_array(&carte::suit, begin, end, [](char a, char b){ if(b==0) return false; else if(a==0) return true; return (a>b); }); sort_array(&carte::value, begin, begin+suit[0], [](int a, int b){return (a<b);}); sort_array(&carte::value, begin+suit[0], begin+suit[0]+suit[1], [](int a, int b){return (a<b);}); sort_array(&carte::value, begin+suit[0]+suit[1], begin+suit[0]+suit[1]+suit[2], [](int a, int b){return (a<b);}); sort_array(&carte::value, begin+suit[0]+suit[1]+suit[2], begin+suit[0]+suit[1]+suit[2]+suit[3],[](int a, int b){return (a<b);}); } int main(){ card array[5]={{2,3},{1,2},{3,4},{4,5},{3,2}}; short suits[4]={1,1,2,1}; ordina(array, array+5, suits); return 0; } 编译错误。我使用了gcc,这个错误仍未解决

1 个答案:

答案 0 :(得分:3)

恭喜,您在gcc中发现了一个错误!这是一个最低重现的例子。请注意,当我们说最小时,我们的确意味着最小。我发现这只是反复删除你的大部分代码行。此外,始终包含您使用的编译器。会有所帮助吗?

gcc汇编了这个:

class X {
    int mem;
};

template <class T>
auto foo(T) {
    return &X::mem;
}

int main() {
    auto p = foo(0);
}

clang没有。铿锵是对的。这是gcc bug 41437