发信人: ago() 
整理人: wenbobo(2002-12-06 22:08:55), 站内信件
 | 
 
 
class A {     public:         int i; };
  int A::*pi=0;
  这最后一句,的结果是给class A的定义中增加了一个属性吗? A中没有定义int *pi, 有了最后一句,A中多了一个int指针,属性?
  也不知道我问的问题写的请不清楚, 请回信. 小问题,见笑了.
  -- ※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.97.228.249] 发信人: crazyjava (骄傲的中国人), 信区: C 标  题: Re: 小问题-... 发信站: 网易虚拟社区 (Mon Jun 14 17:00:14 1999), 站内信件
  【 在 ago (ago) 的大作中提到: 】 : class A : { :     public: :         int i; :    .......
  编译能通过吗?我认为就不行。
  int A::*pi=0; 只是对pi初始化而已. 一般这样写,是由于 pi 是 static member of A, 
  for example: class A  {     public:       int i;      static int *pi; }; 
  int A::*pi=0; 
  -- 孤身走我路... 其实,路,两个人一起走比一个人要好。 email: [email protected]
  ※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 139.87.93.157] 发信人: ago (ago), 信区: C 标  题: Re: 小问题-... 发信站: 网易虚拟社区 (Mon Jun 14 17:17:29 1999), 站内信件
  程序写法没错,出自VC++6.0教材,关于"成员指针转换"部分钟的例程, 还有如下代码:
  class AClass {     public:         int I1;         Show(){cout << I1 <<"\n"} };
  int AClass::*pI1=&AClass::I1;
  void main() {     AClass aClass;     AClass *paClass=&aClass;
      int i;     aClass.*pI1=887;     aClass.Show();     i=paClass->*pI1;
      cout << i << "\n"; }
  -- ※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.97.228.249] 发信人: crazyjava (骄傲的中国人), 信区: C 标  题: Re: 小问题-... 发信站: 网易虚拟社区 (Mon Jun 14 18:51:35 1999), 站内信件
  哈哈,一时老眼昏花!看错了‘*’的位置。Sorry about that!!
  if pi is a static member, the code should be as follows: class A   {      public:        int i;       static int *pi;  };  
  int* A::pi=0;  // NOT int A::*pi = 0 !!
  现在代码是: class AClass  {      public:        int I1;        Show(){cout << I1 <<"\n"}  }; 
  int AClass::*pI1=&AClass::I1; 
  void main() {...}
  说明:pI1不是A的data member.它只是一般的指针变量, 而它的类型是"int A::*",表明指向A的data member.  eg  当pI1 = &x时,x应该是A的data member. 而int AClass::*pI1=&AClass::I1;把它分开写可能更清楚些. eg. void main()  {   ...     // declear a normal pointer "pI1"     // and it is data type is "int AClass::*"   int AClass::* pI1;       // Assign a value to pI1;   pI1 = &AClass::I1;   ...   int i;     // Error!! i is not a data member of AClass.   pI1 = &i; }
  Hope to help u. :)
  -- 孤身走我路... 其实,路,两个人一起走比一个人要好。 email: [email protected]
  ※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 139.87.93.157] 发信人: ago (ago), 信区: C 标  题: Re: 小问题-... 发信站: 网易虚拟社区 (Mon Jun 14 19:01:25 1999), 站内信件
  你回答的非常清楚了. 我明白了. 本人还算精于java,希望有机会交流心得.
  -- ※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.97.228.249] 发信人: ago (ago), 信区: C 标  题: Re: 小问题-... 发信站: 网易虚拟社区 (Mon Jun 14 19:02:17 1999), 站内信件
  忘了say thanks.
  -- ※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.97.228.249] 发信人: dunhill (天地一沙鸥), 信区: C 标  题: Re: 小问题-... 发信站: 网易虚拟社区 (Tue Jun 15 10:41:58 1999), 站内信件
  【 在 ago (ago) 的大作中提到: 】 : class A : { :     public: :         int i; : }; 
  : int A::*pi=0; 
  : 这最后一句,的结果是给class A的定义中增加了一个属性吗?  : A中没有定义int *pi,  : 有了最后一句,A中多了一个int指针,属性? 
  这个..., 我想你是知道这是指向成员变量或函数的指针,因为 你已经在看书嘛,差的只不过是理解问题。我来一步一步引导阐 述,让你xx开朗。
  先说一点基本的。假设有一个类定义如下:
  #include "iostream.h"
  class CTestA { private:     int m_iValue; public:     char *m_pszValue;     void SetValue(int i) {         m_iValue = i;     }     int GetValue() {         return m_iValue;     }     virtual void PrintValue() {         cout << m_iValue;     } }; 那么,CTestA的存储结构是怎样的呢?当你用VC编译器时(我不 知道是否所有的编译器表现都一样),  一个实例化的对象在内 存中应如下保存,假设对象名为testA:                    |------------|                    | m_pszValue |                      |------------|  偏移 8                    |  m_iValue  |                      |------------|  偏移 4                    |  __vfptr   |               testA->+------------+  偏移 0 __vfptr是指向虚函数表的指针,是实现多态性的主要机制。 由 此可见,该类的实例只占用了12个字节,而没有保存函数SetValue 和GetValue的指针。那么,当你执行     testA.SetValue(100); 时,程序如何知道testA对象的SetVaule成员函数的地址呢? 该 对象中并没有储存该函数的入口地址呀?xixi, 这个不用担心, 因为编译的时候已经直接用函数的地址,  用x86汇编代码表示, 大概如下吧:     push   100     lea    eax, &testA       push   eax     call   CTestA::SetVaule     add    esp, 8           ??对不对?? 不好,好像跑题了。知道了上面的东西,就可以更好地理解指向 类成员的指针。 在 c 中, 指针应该可以指向任何存储对象吧? 或者说,任何存储对象都可以用指针操作吧?(我不知道这样说 严不严谨,但我是这样理解的)。既然类的对象,对象的成员变 量,成员函数,虚函数等等总在内存中的某位置,所以,应该总 是可以构造一个指针指向他们。
 
  指向对象成员变量的指针 ======================
  最基本地,定义一个void*指针,如:     void *pvoid = &testA; 哈哈,这样的代码编译器竟然连警告也没有!这样,不论对象的 什么类型的成员变量, 包括private的,你都可以通过这个指针 任意访问,完全违反面向对象的数据封装性。因为void指针可以 转换为任何指针。:)
  再来,     pvoid = &testA.m_iValue;  //不能编译,不能访问私有变量     pvoid = &testA.m_pszValue;//通过编译,没有警告 可见,对象的成员变量你可以任意指定指针指向他们,只要有访 问权限。可以试验出,对静态成员变量也可以如此访问。
  结论1: 指向对象的成员变量的指针只要有访问权限即可自由使         用,其形式如前所示。
 
  指向类成员变量的指针 ====================
  类,当然不是一个对象,指向类成员变量的指针,需要指明类域, 如需安排一个指针指向CTestA::m_iValue,可以如下定义:     int CTestA::*pi = &CTestA::m_iValue; 然后,对于对象testA,testA.*pi等价于testA.m_iValue。注意 这里“.*”操作符,类似地,还有“->*”操作符, 叫做“指向 成员指针操作符”,是专门这种用处的。
  这里的pi与前面的pvoid有何不同? 前面的pvoid是专属于testA 这个对象的,而这里的pi是属于CTestA这个类的,所以引用这个 指针需加上对象标示域,如“testA”。
  pi这个指针的值,实际上等于 m_iValue 相对于类存储位置的偏 移量,本例中,应该等于4。
       指向类成员函数的指针 ====================
  指向成员函数的指针与指向成员变量的指针相当类似,不过定义 的时候要注意参数匹配。如:     void (CTestA::*pf)(int) = &CTestA::SetValue; 所以,你既可以通过     testA.SetVaule(100); 也可以通过     (testA.*pf)(100); 来做同样的事情。 值得注意的是,pf的指针所指的真的是CTestA::SetValue函数入 口地址吗?你调试的时候看看汇编码,知道并不是这样。pf指向 的是一条跳转到SetValue入口的指令。为什么要这样间接一下呢? 我怀疑是减少代码装入时的重定位初始化。  可以这样考虑,假 设程序重要调用100次SetValue,因为装入代码时, 所有的调用 都要用SetValue函数的实际地址去重定位,所以, 要花费100次 重定位,  而采用这种方法, 只需一次重定位----修改jmp指令。 而且,pe文件头的重定位表也小的多。
  写到这里,我对自己的表达能力越来越没有信心,希望你看了会 有点帮助,最好不要越看越糊涂。:))))))))))))
  -- 我是一沙鸥,天地任遨游。飞到昆仑边,飞到海尽头。 狂风我不怕,烈日我不愁。笑看黄鹂鸟,檐头意踌躇。
  ※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 210.75.46.91] 发信人: ago (ago), 信区: C 标  题: CrazyJava!!! are you here? 发信站: 网易虚拟社区 (Tue Jun 15 08:59:27 1999), 站内信件 我在看下面的话时有疑问,才引出我的问题, 我的问题的焦点在 "derived type pDAT". // Define a derived type pDAT that points to   // I1 members of objects of type AClass.  int AClass::*pDAT = &AClass::I1;  照理说,应该理解为,定义了一个派生类型 pDAT 指向AClass 的I1, 可是在使用上,pDAT完全象是一个AClass的属性. AClass a,b; a=...; b=..; ... a.*pDAT=1; b.*pDAT=2; 这样用非常好用,我想知道,pDAT是程序中的'一个'变量? 还是'每一个'AClass中多了一个属性, 或者是有其他的解释? -- ※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.97.228.249] 发信人: vcc (vcc), 信区: C 标  题: Re: CrazyJava!!! are you here? 发信站: 网易虚拟社区 (Tue Jun 15 11:24:18 1999), 站内信件 【 在 ago (ago) 的大作中提到: 】 : 我在看下面的话时有疑问,才引出我的问题, : 我的问题的焦点在 : "derived type pDAT". :  :    ....... 其实这相当于添加了类的一种类型安全的指针操作的方法。 看它的定义和使用可以明白,相当于类添加了*pMyType的方法。 1)  Operator or Construct - ::*  Syntax - type::*ptr-name  Use - Declaration of pointer to member. The type         specifies the class name, and ptr-name         specifies the name of the pointer to member.         Pointers to members can be initialized.         For example: MyType::*pMyType = &MyType::i;  2)   Operator or Construct - .*  Syntax - obj-name.*ptr-name  Use - Dereference a pointer to a member using an         object or object reference. For example:         int j = Object.*pMyType;  -- ※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.103.146.7] 发信人: dunhill (天地一沙鸥), 信区: C 标  题: Re: CrazyJava!!! are you here? 发信站: 网易虚拟社区 (Tue Jun 15 11:38:10 1999), 站内信件 【 在 ago (ago) 的大作中提到: 】 : 我在看下面的话时有疑问,才引出我的问题, : 我的问题的焦点在 : "derived type pDAT". : // Define a derived type pDAT that points to    : // I1 members of objects of type AClass.   : int AClass::*pDAT = &AClass::I1;   : 照理说,应该理解为,定义了一个派生类型 pDAT 指向AClass 的I1,  : 可是在使用上,pDAT完全象是一个AClass的属性.  : AClass a,b;  : a=...;  : b=..;  : ...  : a.*pDAT=1;  : b.*pDAT=2;  : 这样用非常好用,我想知道,pDAT是程序中的'一个'变量?  : 还是'每一个'AClass中多了一个属性,  : 或者是有其他的解释?  你们的贴子我都看了。事实是这样,就不用说了, 是不是可以 这样理解,pDat不是AClass的一个属性,而是程序的一个变量, 这个变量是个指针,这个指针至向整形,这个整形是A类的成员。 哈哈,归根结底,就是指向“类”成员的指针。如果类A有多个 整形的成员,那么,pDat可以指向任何一个,所以, 在实际上 也还是有用的,虽然很少用。 -- 我是一沙鸥,天地任遨游。飞到昆仑边,飞到海尽头。 狂风我不怕,烈日我不愁。笑看黄鹂鸟,檐头意踌躇。 ※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 210.75.46.91] 发信人: crazyjava (骄傲的中国人), 信区: C 标  题: Re: CrazyJava!!! are you here? 发信站: 网易虚拟社区 (Tue Jun 15 12:53:18 1999), 站内信件 【 在 ago (ago) 的大作中提到: 】 : 我在看下面的话时有疑问,才引出我的问题, : 我的问题的焦点在 : "derived type pDAT". :  :    ....... 在以前的贴子我也说了,在C++语言定义上, pDAT只是一般变量,而不是Aclass的data member。 为了方便理解,你自己可以这样认为。但前提是要紧记 定义,这样才不会使用错。 MSDN已经指出了使用它的原因:  "Use of pointers to class members enhances the    type safety of the C++ language."  -- 孤身走我路... 其实,路,两个人一起走比一个人要好。 email: [email protected] ※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 139.87.93.212]
 
 
  | 
 
 
 |