注册 登录
编程论坛 C++教室

对象参数与私有变量

书呆 发布于 2010-03-29 20:49, 1250 次点击
请看:
class A
{
public:
    int f(A &a);
private:
    int x;
};
int A::f(A &a)
{
    a.x = 0;
    return 0;
}

意味着参数a的私有变量x可以被其他对象直接修改,怎么还能叫私有 ?
13 回复
#2
hahayezhe2010-03-29 21:51
有直接修改么 你不是从公有调用函数改的吗?
#3
书呆2010-03-29 23:22
呃。。。明白了
#4
debroa7232010-03-29 23:24
这只是个编程思想,如果你希望并允许调用者来修改这个私有变量,你就为他准备这个函数来修改这个变量,如果不希望,也不允许,你就不写这个函数,那么使用你的代码的人就明白你的意图了(当然这个使用者是指正常使用者)。
私有变量只是在编译期的保护,并只是为调用者传达自己的编程意图,它并不能真真做到私有,比如类A,可以不用f函数就可以达到修改私有变量x的目的:
A a;
*((int*)(&a)) = 100;
这样可以把私有变量赋值为100,这种做法需要知道类A的数据结构,并通过实例对象a的首地址和变量x在a中的偏移地址来达到修改目的的,换句话说,如果我知道你的类结构,就可以访问到类中的所有私有成员变量并达到修改的目的。有兴趣的话可以通过调试研究一下。
#5
书呆2010-03-30 12:11
回复 4楼 debroa723
我明白了,这也是OO封装的原因之一吧。。。
谢谢
#6
wei00002010-03-30 16:54
*((int*)(&a)) = 100;
请问这句是什么意思啊?
能帮忙详细解释解释吗?
#7
debroa7232010-03-30 20:01
&a:取对象a的首地址
(int*):将前面取到的地址强转成int形指针
*(int形指针)=100;//就象是对一个整形指针所指内容赋值一样。
#8
wei00002010-03-30 20:16
那再问一下,*((int*)(&a)) = 100;是怎么实现将类的私有变量赋值为100的??
还有那个私有变量x的偏移量是怎么得到啊?????
能再帮忙解答一下疑问吗?很感谢啊!!!
#9
书呆2010-03-30 22:27
由类A的结构,在对象a的存储空间中变量x偏移量为0,所以把a的地址强转为指针后,就指向a的x,从而对该指针
指向空间的赋值,就相当于对x的赋值
#10
wei00002010-03-31 11:15
那再问下,私有变量和公有变量在对象a中的偏移量都是0吗??
还有如果有两个私有变量x,y或两个公有变量m,n,他们在对象a中的偏移量也都是0吗??这样的话,像上面那样赋值,不是就不清楚到底是给哪个变量赋值了吗???
#11
书呆2010-03-31 12:39
按照声明顺序计算偏移量。
比如类中定义int x; int y; 那么x的偏移量是0,而y的偏移量就是4,
对y的赋值就应该是 *((int*)(&a) + 1) = 100;
#12
书呆2010-03-31 12:45
偏移量是由声明顺序决定的,跟访问权限无关。
#13
wei00002010-03-31 22:20
非常感谢啊
#14
debroa7232010-04-01 20:55
类的成员变量在内存分部情况,是按类设计时,代码的顺序产生的,所以第一个成员变量的地址一般都是类对象实例的首地址,而这后的成员变量地址偏移,则是根据数据实际的内存上长度来偏移。(这里之所以说一般性,是因为有虚函数的类的首地址是一个虚函数表的指针,这时要取第一个成员变量,需要偏移一个指针的内存宽度)
例:
class A
{
private:
   int  m_i;
   char m_str[10];
}
class B
{
public:
   virtual fun();
   virtual fun1();
private:
   int  m_i;
   char m_str[10];
}
    A a;
    B b;
    //给m_i赋值100
    *((int*)(&a)) = 100;
    *((int*)((char*)(&b) + sizeof(void*))) = 100;//多加一个指针的宽度
    //给m_str赋值"test"
    char* pStrA = (char*)(&a) + sizeof(int) ;
    char* pStrB = (char*)(&b) + sizeof(void*) + sizeof(int);//多加一个指针的宽度
    sprintf_s( pStrA , 10 , "test");
    sprintf_s( pStrB , 10 , "test");
以上只是实验性的,实际情况要复杂的多少,要考虑到内存对齐的原则,变量的内存宽度是受影响的,所以想要真正做到强行访问私有成员变量,需要非常了解源代码的结构。
1