c++ - 指向类的私有(private)数据成员的指针

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

考虑一个类 card,它有两个公共(public)成员:intsuitint 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;});
}

如果卡成员(member)suit是公开的,显然没有问题,但实际上我没想到的是,即使我声明suit<,相同的代码也不会带来任何麻烦value 作为私有(private)成员。

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

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

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

那么,为什么上面的代码(带有模板的代码)可以工作呢?

编辑: 好的,上面的代码本身不能编译,但由于某种原因,下面的代码对我来说编译得很好。我将发布整个代码,因为我不知道它的工作技巧可能在哪里,对于困惑表示抱歉:

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

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

编辑3:如巴里回答https://stackoverflow.com/a/35978073/5922196中所述,这是一个 gcc 编译器错误。我使用了g++ 4.9.2,这个错误仍然没有解决

最佳答案

恭喜,您发现了 gcc 中的错误!这是一个最小化复制的示例。请注意,当我们说最小时,我们真正的意思是最小。我通过重复删除大部分代码行发现了这一点。另外,始终包含您使用的编译器的内容。会有帮助的。

gcc 编译此:

class X {
    int mem;
};

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

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

clang 没有。叮当是对的。这是 gcc 错误 41437 .

关于c++ - 指向类的私有(private)数据成员的指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35977414/

相关文章:

c++ - 为什么我不能使用函数按值对 map 进行排序?

c++ - 使用带有 CMake 和 Conan 的外部库的 undefined reference

C++ 错误 : 'unordered_map' does not name a type

php - ZF2模块加载性能

c++ - 新构造的对象作为默认模板函数参数

成员运算符的 C++ enable_if(或解决方法)

c++ - 类成员函数的返回值类型

Java将变量传递给类返回不同的变量

c++ - 有没有更好的方法来初始化引用成员以引用同一个类中的另一个成员

java - 在java中从vmware中的模板克隆vm时更改磁盘大小