代码改变世界

c++指针比较的含义

2011-12-16 21:07  javaspring  阅读(287)  评论(0编辑  收藏  举报

  在c++中,一个对象可以有多个有效地地址,因此,指针比较并不是关于地址问题,而是关于类的判别 (object identity)。

   class Shape {.......};

   class Subject {.........};

   class ObservedBlob :public shape , public Subject {.........};

   在这个类的继承层次结构中,ObservedBlob 只是由shape和Subject派生而来,并且都是公有继承,因此存在从派生类对象到任何基类的预定义转换。


    ObservedBlob *obj=new ObservedBlob; 

    Shape * s=obj;              //发生预定义转换

    Subject * subj=obj;       //发生预定义转换

  

   The availability of these conversions means that a pointer to anObservedBlob may be compared to a pointer to either of its base classes.

    if( ob == s ) ...
    if( subj == ob ) ...

    In this case, both of these conditions will be true even if the addresses contained inob,s, andsubj differ. Consider two possible memory layouts for theObservedBlob object to which these pointers refer, as shown inFigure 7.

 

    多重继承情形下两种可能的内存排列。不管是哪一种排列,对象都具有多个地址。

    第一种排列中,s和subj都指向对象ob内的Shape和Subject子对象,他们指向的地址与对象ob所在的地址不同。


    在第二种排列中,s和对象ob恰好具有相同的地址。

#include <iostream>
using std::cout;
using std::endl;
class Shape
{
public:  
	Shape(){cout<<"Base class-Shape is Constructed"<<endl;}  
	virtual ~Shape(){cout<<"Base class-Shape is deconstructed"<<endl;}  
	virtual void Clue(){cout<<"this is a member function in Shape"<<endl;}  
};


class Subject 
{
public:  
	Subject (){cout<<"Base class-Subject is Constructed"<<endl;}  
	virtual ~Subject (){cout<<"Base class-Subject is deconstructed"<<endl;}  
	virtual void Play(){cout<<"this is a member function in Subject"<<endl;}  
};

class ObservedBlob :public Shape , public Subject
{
public:
	ObservedBlob(){cout<<"Derived class is Constructed"<<endl;}  
	~ObservedBlob(){cout<<"Derived class is deconstructed"<<endl;}  
	void Clue(){cout<<"this is a member function in ShapeDerived"<<endl;}  
	void Play(){cout<<"this is a member function in SubjectDerived"<<endl;}  
};

void main()  
{  
	ObservedBlob *ob=new ObservedBlob;
	cout<<endl<<"ob的内存地址:   "<<ob<<endl;
	Shape* s=ob;
	Subject* subj=ob;
	s->Clue();
	cout<<endl<<"s的内存地址:    "<<s<<endl;
	subj->Play();
    cout<<endl<<"subj的内存地址: "<<subj<<endl;
	ob->Clue();  
	ob->Play();
	delete ob; 
	getchar();
}  


执行结果:



   不管是那种排列,ob 、s、subj都指向同一个ObservedBlob对象,编译器为了确保

    if( ob == s ) ...
    if( subj == ob ) ...

表达式的正确性,编译器将通过指针的偏移量的运算来完成指针的比较,例如下面的表达式:

   ob == subj

may be (loosely) translated as

  ob ? (ob+delta == subj) : (subj == 0)
delta是Subject子对象在ObservedBlob对象中的偏移量。 换句话说的话,就是假如ob是空指针,subj也就是空指针(因为    Subject * subj=obj;);否则ob将通过与偏移量delta相加,实现变为一个指向ob对象内Subject基类子对象的指针的转换,再与subj相比较。

 

  其实,不能看出,一般而言,我们在处理一个对象指针或者引用时,要注意避免类型信息的丢失。

 当用对象的指针赋值给void指针时,会导致对象类型信息丢失。