当前位置: 首页 > 文档资料 > C++大学教程 >

7.5 使用 this 指针

优质
小牛编辑
124浏览
2023-12-01

每个对象都可以通过 this 指针访问自己的地址。对象的 this 指针不是对象本身的一部分,即 this 指针不在对该对象进行 sizeof 操作的结果中体现。但this指针在每次非static成员函数调用对象时(static 成员见7.7节介绍)作为第一个隐式参数传递给对象(通过编译器)。

this 指针隐式引用对象的数据成员和成员函数(当然也可以显式使用)。this 指针的类型取决于对象类型和使用 this 的成员函数是否声明为 const。在 Employee 类的非常量成虽函数中,this 指针的类型为 Employee *const(Employee 对象的常量指针)。在 Employee 类的常量成员函数中,this 指针的类型为 const Employee *const(为常量Employee 对象的常量指针)。

下面介绍一个显式使用 this 指针的简单例子,本章稍后和第8章将介绍一些使用 this 的复杂例子。每个非 static 成员函数都能访问所调用成员所在对象的 this 指针。

性能提示 7.3
为了节约存储空间,每个类的每个成员函数只有一个副本,该类的每个对象都可调用这个成员函数。另一方面每个对象又有自己的类数据成员副本。

图 7.7 演示了显式使用 this 指针,从而使 Test 类的成员函数打印 Test 对象的 private 数据 x。

1 // Fig. 7.7: fig07_07.cpp
2 // Using the this pointer to refer to object members,
3 #include <iostream.h>
4
5 class Test {
6 public:
7 Test( int = 0 }; // default constructor
8 void print() const;
9 private:
10 int x;
11 };
12
13 Test::Test( int a ) { x = a; } // constructor
14
15 void Test::print() Const // () around *this required
16 {
17 cout <<" x =" << x
18 << "\n this->x "<< this->x
19 << "\n(* this).x =" << ( *this ).x << endl;
2O }
21
22 int main()
23 {
24 Test testObject( 12 );
25
26 testObject.print();
27
28 return 0;
29 }

输出结果:

x = 12
this-> = 12
(*this).x = 12

图 7.7 使用 this 指针

作为演示,图 7.7 中的 print 成员函数首先直接打印 x。然后 print 用两个不同符号通过 this 指针访问 x,一个是 this 指针和箭头运算符(->),一个是 this 指针和圆点运算符(.)。

注意 *this 和圆点(成员选择)运算符一起使用时要用括号括起来。这个括号是必需的,因为圆点运算符的优先级高于*运算符。如果没有括号,则下列表达式:

*this.x

求值为:

*( this.x)

这是个语法错误,因为圆点运算符不能和指针一起使用。

常见编程错误 7.7
将对象指针和成员选择运算符(.)一起使用是个语法错误,因为成员选择运算符和对象或对该对象的引用一起使用。

this 指针的一个有趣用法是防止对象赋值给自己。第8章 运算符重载 中将会介绍,自我赋值可能在对象包含动态分配内存的指针时导致严重的错误。

this 指针的另一用法是允许连续使用成员函数调用。图 7.8 演示了返回 Time 对象的引用,使 Time 类的成员函数调用可以连续使用。成员函数 setTime、setHour、setMinute 和 setSecond 都可以返回 Time& 返回类型的 *this。

1 // Fig. 7.8: time6.h
2 // Cascading member function calls.
3
4 // Declaration of class Time.
5 // Member functions defined in time6.cpp
6 #ifndef TIME6_H
7 #define TIME6_H
8
9 class Time {
10 public:
11 Time( int = 0, int= 0, int = 0 ); // default constructor
12
13 // set functions
14 Time &setTime( int, int, int ); // set hour, minute, second
15 Time &setHour( int ); // set hour
16 Time &setMinute( int ); // set minute
17 Time &setSecond( int ); // set second
18
19 // get functions (normally declared const)
20 int getHour() const; // return hour
21 int getMinute() const; // return minute
22 int getseeend() const; // return second
23
24 // print functions (normally declared const}
25 void printMilitary() const; // print military time
26 void printstandard() const; // print standard time
27 private:
28 int hour; // O - 23
29 int minute; // O - 59
30 int second; // O - 58
31 };
33 #endif
34 // Fig. 7.8: time.cpp
36 #include "time6.h"
37 #include <iostream.h>
38
39 // Constructor function to initialize private data.
40 // Calls member function setTime to set variables.
41 // Default values are 0(see class definiation).
42 Time::Time( int hr, int min, int sec )
43 { setTime( hr, min, sec ); }
45 // Set the values of hour, minute, and second.
46 Time &Time::setTime{ int h, int m, int s )
47 {
48 setHour( h );
49 setMinute( m );
50 setSecond( s );
51 return *this; // enables CaScading
52 }
53
54 // Set the hour value
55 Time &Time::setHour( int h )
56 {
57 hour = ( h >= 0 && h < 24 ) ? h : 0;
59 return *this; // enables cascading
60 }
62 // Set the minute value
63 Time &Time::setMinute( int m )
64 {
68 minute = ( m >= 0 && m < 60 ) ? m : 0;
67 return *this; // enables cascading
68 }
70 // Set the second value
71 Time &Time::setSecond( int s )
72 {
73 second = ( s >= 0 && s < 60 ) ? s : 0;
74
75 return *this; // enables cascading
76 }
77
78 // Get the hour value
79 int Time::getHour() const { return hour;}
80
81 // Get the minute value
82 int Time::getMinute() const { return minute; }
83
84 // Get the second value
85 int Time::getSecond() const {eturn second;}
86
87 // Display military format time: HH:MM:
88 void Time::printMilitary() const
89 {
90 cout << (hour < 10 ? "0": "") << hour <<":"
91 << ( minute < 10 ? "0": "" ) << minute;
92 }
93
94 // Display standard format time: HH:MM:SS AM (or PM)
95 void Time::printStandard() const
96 {
97 cout << ( ( hour == 0 || hour == 12 ) ? 12 : hour % 12 )
98 << ":" << ( minute < 10 ? "0" : "" ) << minute
99 << ":" << ( second < 10 ? "0" : "" ) << second
100 << ( hour < 12 ? "AM" : "PM" );
101 }
102 // Fig. 7.8: fig07_08.cpp
103 // cascading member function calls together
104 // with the this pointer
105 #include <iostream.h>
106 #include "time6.h"
107
108 int main()
109 {
110 Time t;
111
112 t.setMour( 18 ).setMinute( 30 ).setSecond( 22 );
113 cout << "Military time: ";
114 t.printMilitaryO;
115 cout << "\nStandard time: ";
116 t.printStandard();
117
118 cout << "\n\nNew standard time: ";
119 t.setTime( 20, 20, 20 ).printStandard();
120 cout << endl;
121
122 return 0;
123 }

输出结果:

Military time: 18:30
standard time: 6:30:22 PM

New standard time: 8:20:20 PM

图 7.8 连续使用成员函数调用

为什么可以将 *this 作为引用返回呢?圆点运算符 (.) 的结合律为从左向右,因此下列表达式:

t.setHour(18).setMinute(30).setSecond(22);

首先求值t.setHour(18),然后返回对象t的引用,作为这个函数调用的值。其余表达式解释如下:

t.setMinute(30).setSecond(22);

执行setMinute(30)调用并返回t的等价值,其余表达式解释为:

t.setSecond(22);

注意:

t.setTime(20,20,20).printStandard();

调用也体现了连续使用的特性。这些调用在这个表达式中必须按这个顺序出现,因为类中定义的 printStandard 并不返回t的引用,将上述语句中的 printStandard 调用放在setTime调用之前是个语法错误。