如何通过其偏移访问私有数据私有成员?

时间:2011-09-03 03:51:59

标签: c++ visual-studio

我正在尝试通过偏移来访问和修改类的私有数据成员 AFAIK,首先是计算偏移量,然后通过偏移量访问成员 这是我的代码。

class Test {  
public:
    int a;  
    int b;
private:  
    int c;
};  
Test test;
cout << *(&test + &Test::b + 1);  // access c

我收到错误:“+”运算符无效,右操作数包含“int Test::*”类型。

There是一个类似的帖子,printf ab的偏移量为1,4,但尝试这样时:

cout << &Test::a << '\t' << &Test::b;  

我得到1 1

我的问题:
1.为什么cout得到错误的结果?
2. Test::*p指向什么?
3.如何访问和修改Test :: *指针?(或者当不知道偏移时如何访问私有成员?)

4 个答案:

答案 0 :(得分:3)

Test::p是成员指针。成员指针与常规指针不同。你不能只对它们做指针算术。它们不是对内存中某个位置的引用;它们是一种特殊的物体。

如果你想要一个指向对象的常规指针(即:现有类的成员),你必须得到指向那段特定内存的指针。

&test.b

BTW,无论您尝试访问的私人数据是出于某种原因而私有 。因此,除非你有一个非常非常的理由基本上打破内存保护(以及可移植性,因为这是完全未定义的行为),你不应该这样做。

答案 1 :(得分:3)

这有效:

#include <iostream>
using namespace std;
class test {
  public:
      int a;
      int b;
      test () : c(100) {}
      void show () {cout << "c = " << c << endl;}
  private:
      int c;
};


int main (void)
{
  test x;
  test *ptr;
  ptr = &x;
  ptr++;
  ptr = (test *) ((int *)ptr - 1);
  cout << "c = " << *((int *)ptr) << endl;
  *((int *)ptr) = 200;
  x.show ();
  return 0;
}

但应该知道偏移量。在上面的ptr类型为test,因此ptr++会将指针值增加到sizeof (test)。因为私有成员c的位置在末尾并且是一个整数类型,所以通过先将ptr强制转换为int *然后递减1来减少一个整数步骤,现在指向到c的地址。它首先打印,然后通过首先将c投射到ptr然后分配值然后打印来修改int *的值。

当您知道c的位置时,无法保证始终获得c的值,因为填充在其他情况下可能会有所不同。此外,没有必要访问私有数据成员,因为在对象设计方法时,它被成员函数访问,并且是通过提供抽象来组织的工具。当在其他语言(如没有面向对象的功能)的其他语言中实现这样的概念时,您可以通过亲自遵循约定来实现这样的私有 - 公共环境,但是如果您访问了“私有”,编译器将不执行任何操作。实际上不应该。但是在C ++中,编译器提供了限制并阻止您转移和破坏您所创建的面向对象的设计。在运行时所有内存中,您可以访问它们,而不受您的代码的任何限制,无论是私人还是公共。如果您知道如何解释可执行文件中的字节,您可以更改任何您喜欢的内容,甚至是代码本身。我不认为这是一个好主意,因为它会使代码变得不可预测和不可移植,并且肯定违反了OOD方法。

答案 2 :(得分:2)

如果必须,#define private public技巧应该这样做。

答案 3 :(得分:1)

你真的无法测试对象的内存布局。编译器可以随意使用它。

当成员被不同的访问说明符分隔时,该语言没有说明他们的顺序。在您的情况下,a必须后跟b,但理论上c可以放在编译器认为合适的任何位置。

在一个更大的例子中,如

class Test {  
public:
    int a;  
    int b;
private:  
    int c;
protected:
    double d;
};

例如,如果可以改善对齐,则允许编译器在d之前放置c