【C++】指向类成员变量的指针并非指针

“指向类成员变量的指针”,这个术语中包含了"类成员变量"的术语,但是严格的说,这里的成员变量只是指非静态成员变量,这个术语中还包含了"指针"这个术语,但是严格的说,它即不包含地址,行为也不象指针,说得干脆点,那就是"指向类成员变量的指针"并非指针.尽管这个术语有很大的迷惑性,但是就其含义来说,可以把一组同类型的变量抽象为一个"指向变量的指针",同样的道理,可以把一组类中同类型的类成员变量抽象为一个"指向类成员变量的指针",两者是一致的。

但是一个"指向类成员变量的指针"并不包含一个地址,简单点说,实际上它是一个成员变量在类中的偏移量.当然,严格点说,因为C++标准并为对"指向类成员变量的指针"如何实现做任何规定,说"指向类成员变量的指针"是一个整数的偏移量就不是一定正确,但是,大多数编译器确实是这样做的.下面我们看看"指向类成员变量的指针"是如何使用的?

举个例子:

// addressof example
class PTM {
public:
  int  iValue;
  int  jValue;
  static float fValue;
};

float PTM::fValue;

void PrintAll(PTM* point) {
    std::cout << "PTM Print All" << std::endl;
    std::cout << point->PTM::iValue << std::endl;
    std::cout << point->PTM::jValue << std::endl;
}

void Print(PTM* point, int PTM::* p) {
    std::cout << point->*p << std::endl;
}

int main() {
  int  PTM::*pValue = &PTM::iValue; // OK: non-static
  //float PTM::*pfValue = &PTM::fValue; // C2440 error: static
  float *spfValue   = &PTM::fValue; // OK
  std::cout << "int  PTM::*pValue = &PTM::iValue;" << std::endl;
  std::cout << "float *spfValue   = &PTM::fValue;" << std::endl << std::endl;

  std::cout << "typeid(pValue).name(): " << typeid(pValue).name() << std::endl;
  std::cout << "typeid(spfValue).name(): " << typeid(spfValue).name() << std::endl << std::endl;
    
  PTM ptm;
  ptm.iValue = 98;
  ptm.jValue = 99;
  int* iValue = &ptm.iValue;
  std::cout << "int* iValue = &ptm.iValue;" << std::endl;
  std::cout << "typeid(iValue).name(): " << typeid(iValue).name() << std::endl << std::endl;
    
  printf("address of pValue: %p\n", pValue);
  Print(&ptm, pValue);
  pValue = &PTM::jValue;
  std::cout << "pValue = &PTM::jValue;" << std::endl;
  printf("address of pValue: %p\n", pValue);
  Print(&ptm, pValue);
    
  PrintAll(&ptm);
  return 0;
}

输出结果为:

:g++ -std=c++17 -O0 main.cc -o main
main.cc:47:37: warning: format specifies type 'void *' but the argument has type 'int PTM::*' [-Wformat]
  printf("address of pValue: %p\n", pValue);
                             ~~     ^~~~~~
main.cc:51:37: warning: format specifies type 'void *' but the argument has type 'int PTM::*' [-Wformat]
  printf("address of pValue: %p\n", pValue);
                             ~~     ^~~~~~
2 warnings generated.
:./main | c++filt
int  PTM::*pValue = &PTM::iValue;
float *spfValue   = &PTM::fValue;

typeid(pValue).name(): int PTM::*
typeid(spfValue).name(): float*

int* iValue = &ptm.iValue;
typeid(iValue).name(): int*

address of pValue: 0x0
98
pValue = &PTM::jValue;
address of pValue: 0x4
99
PTM Print All
98
99
发布了423 篇原创文章 · 获赞 14 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/LU_ZHAO/article/details/105478811