再上一篇:9.3 对象
上一篇:9.4 成员函数的重载
主页
下一篇:第十章 构造函数和析构函数
再下一篇:10.2 析构函数
文章列表

9.5 this指针

《VC++程序设计基础》,讲述C++语言的语法和标准库,以及Visual C++ 函数库和MFC类库的使用,并附相关代码示例。

用对象的成员函数来访问该对象的成员时,在成员函数的实现中,只要给出成员的名就可实现对该对象成员的访问;但在成员函数之外要访问某对象中的某一个成员时,就需要指明访问哪一个对象的成员。实际上,当调用一个成员函数时,系统自动地向它传递一个隐含的参数,该参数是一个指向接受该函数调用的对象的指针,在成员函数的函数体中可直接使用关键字this来访问该指针。在成员函数的实现中,当访问该对象的某一个成员时,系统自动地使用了这个隐含的this指针,在定义成员函数的函数体时,均省略了this指针。如例9.8中的成员函数int GetElem(int i),当使用this指针时,完整的程序段为:

int GetElem(int i)

{

if((i>=0 )&& (i<=this->nElem)) return this->List[i];

else return 0;

}

this指针具有如下形式的缺省说明:

ListClass *const this;

即把这个指针说明为const型指针,只允许在成员函数体内使用该指针,但不允许改变这个指针的值。若允许用户修改这个指针的值,就可能出现系统无法预测的错误。

从前面的例子可以看出,程序设计者通常不必关心这个指针,这指针是由系统自动维护的。但在特殊的应用场合,程序设计者可能要用到这个指针的值。例如,在处理线性表的类中,增加一个拷贝线性表的成员函数CopyList();它的原型为:

void CopyList( ListClass );

这函数的定义为:

void ListClass::CopyList(ListClass L)

{

nMax=L.Max();

nElem=L.Elem();

if ( List ) delete [ ] List;

List = new int[nMax]; //E

for(int i=0;i

List[i]=L.GetElem(i);

}

当程序中出现:

ListClass m1;

m1.CopyList (list);

实现了将对象list中的线性表拷贝到对象m1中。但出现如下拷贝时:

list..CopyList (list);

即出现同一对象中的线性表自己拷贝到自己的情况,执行E行时,因List指向当前的线性表,用new运算符为线性表动态分配存储空间,并将所分配存储空间的指针值赋给List时,线性表中的数据全部丢失。当然,F行也不能正确实现数据的拷贝。为了防止这种情况的发生,该成员函数必须改写为:

void ListClass::CopyList(ListClass L)

{

if( &L != this ){ //G

nMax=L.Max();

nElem=L.Elem();

if ( List ) delete [ ] List;

List = new int[nMax];

for(int i=0;i

List[i]=L.GetElem(i);

}

}

当出现一个线性表自己拷贝到自己时,G行的条件不成立,则该函数不再做任何事情直接返回。否则,完成线性表的拷贝工作。在类似于这种情况的应用中,必须使用指针“this”。

习题与思考9

1.定义一个描述复数的类,数据成员有:实部和虚部;成员函数有:输出复数,置实部,置虚部。

2.定义一个描述学生基本情况的类,数据成员包括:姓名,学号,数学、英语、物理和C++成绩;成员函数有:输出数据,置姓名和学号,置四门课的成绩,求出总成绩和平均成绩。

3.写出下面程序的运行结果:

#include

class P{

char c1,c2;

public:

void Set(char c)

{c1=1+(c2=c);}

unsigned WhereIs(void )

{ return (unsigned ) this; }

void Print(void )

{ cout<

};

void main(void )

{

P a, b;

a.Set('A'); b.Set('B');

a.Print(); b.Print();

cout<<"a is at "<

cout<<"b is at "<

}

4.三维坐标中的一条直线可通过该直线的二端点的坐标(x1,y1,z1)和(x2,y2,z2)来描述。定义一个类,实现坐标数据的设置,输出端点的坐标和直线的长度。构成一个完整的程序,完成测试工作。

5.下面是一个类的测试程序,给出类的定义,构成一个完整的程序。执行程序时的输出为:

输出结果:200-60=140

主函数为:

void main(void)

{

Test c;

c.Init(200,60);

c.Print();

}

6.把例9.8处理一个线性表中的整数改为字符。完成该例中类同的要求,动态产生线性表,并输出线性表中的数据。

7.设一个类的定义如下:

class T{

char *p1, *p2;

public:

void Init(char *s1, char *s2);

void Print( )

{ cout<<"p1="<

void CopyT(T &t );

void FreeT( void) ;

};

成员函数Init(char *s1, char *s2)将s1和s2所指向的字符串分别送到p1和p2所指向的

动态申请的内存空间中,函数CopyT(T &t )将对象t中的二个字符串拷贝到当前的对

象中,FreeT( void)释放p1和p2所指向的动态分配的内存空间。设计一个完整的程序,

包括完成这三个函数的定义和测试程序。