发信人: 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]
|
|