使用公共成员变量的地址来访问私有成员

时间:2016-06-23 03:02:03

标签: c++ pointers memory-management

我创建了以下简单的测试程序,以表明我可以使用公共整数的地址来访问私有整数的值:

#include <iostream>
using namespace std;
class CarType{
  public:
    int year;
    CarType(int price, int year){this -> year = year; this -> price = price;};
  private: 
    int price;
};

int main(){
  //Create new CarType object
  CarType a = CarType(15000, 1999);
  //Increment the memory address of public member variable, year by 1 and save the result
  int* pricePointer = &a.year+1;
  //De-reference the memory address and output it
  cout << "PRICE: "<< *pricePointer << endl;
  return 0;
}

输出显示我只需知道年份的地址即可访问价格变量。有没有办法防止这种情况发生?这只是一个边缘情况还是适用于所有类型的对象?

1 个答案:

答案 0 :(得分:3)

这可能是可能未定义(但肯定是不明智的)行为,你可以像防止人们写入随机地址一样阻止它,或者防止没有经验的人用链锯切断四肢。换句话说,根本不是。

Caveat Coder。

我在上一段中说可能的原因是它并不完全清楚。在语言 - 律师术语中,请参阅C++14 5.7 Additive operators /4

  

出于这些运算符的目的,指向非阵列对象的指针与指向长度为1的数组的第一个元素的指针的行为相同,其中对象的类型为其元素类型。

在讨论向指针添加整数值时

/5

  

如果指针操作数和结果都指向同一个数组对象的元素,或者指向数组对象的最后一个元素,则评估不应产生溢出;否则,行为未定义。

在你的情况下,你的指针实际指向&#34;一个指过最后一个元素&#34;因此,添加本身不会产生未定义的行为。

您可能认为取消引用该对象是未定义的,但根据3.9.2 Compound types /3中的注释,它似乎有效:

  

例如,超过数组末尾的地址(5.7)将被视为指向可能位于该地址的数组元素类型的无关对象。

但是,未定义或未定义,取消引用仍然不明智,因为您实际上知道那里存在正确类型的变量。实现可以根据需要自由填充结构,因此无法保证price*(year + 1)相同。