6.15 微妙的陷阱:返回对 private 数据成员的引用
优质
小牛编辑
133浏览
2023-12-01
对象的引用是对象名的别名,因此可以放在赋值浯句左边,在这种情况中,引用可以成为可接收赋值的左值。要使用这种功能,就要让类的 public 成员函数返回对该类 private 数据成员的非 const 引用。
图 6.11 用简化的 Time 类演示如何返回 private 数据成员的引用。调用 badSetHour 函数返回的引用作为 private 数据成员 hour 的别名。函数调用可以按任何使用 private 数据成员的方式使用,包括作为赋值语句的左值。
编程技巧 6.8
不要让类的 public 成员函数返回对该类 private 数据成员的非 const 引用(或指针),返回这种引用会破坏类的封装。
1 // Fig. 6.11: time4.h
2 // Declaration of the Time class.
3 // Member functions defined in time4.cpp
4
5 // preprocessor directives that
6 // prevent multiple inclusions of header file
7 #ifndef TIME4_H
8 #define TIME4_H
9
10 class Time {
11 public
12 Time( int = 0, int = 0, int = 0 );
13 void setTime( int, int, int );
14 int getHour();
15 int &badSetHour( int ); // DANGEROUS reference return
16 private:
17 int hour;
18 int minute;
19 int second;
20 };
21
22 #endif
23 // Fig. 6.11: time4.cpp
24 // Member function definitions for Time class.
25 #include "time4.h"
26 #include <iostream.h>
27
28 // Constructor function to initialize private data.
29 // Calls member function setTime to set variables.
30 // Default values are 0 (see class definition).
31 Time::Time( int hr, int min, int sec )
32 { setTime( hr, min, sec ); }
33
34 // Set the values of hour, minute, and second.
35 void Time::setTime( int h, int m, int s )
36{
37 hour = ( h >= o && h < 24 ) ? h : 0;
38 minute ( m >= 0 && m < 60 ) ? m : 0;
39 second = ( s >= 0 && s < 60 ) ? s : 0;
40 }
41
42 // Get the hour value
43 int Time::getHour() { return hour; ]
44
45 // POOR PROGRAMMING PRACTICE:
46 // Returning a reference to a private data member.
47 int &Time::badSetHour( int hh )
48 {
49 hour = ( hh >= 0 && hh < 24 ) ? hh : 0;
50
51 return hour; // DANGEROUS reference return
52 }
53 // Fig. 6.11: fig06_11.cpp
54 // Demonstrating a public member function that
55 // returns a reference to a private data member.
56 // Time class has been triced for this example.
57 #include <iostream.h>
58 #include "time4.h"
59
60 int main()
61 {
62 Time t;
63 int &hourRef = t.badSetHour( 20 );
64
65 cout << "Hour before modification: "<< hourRef;
66 hourRef = 30; // modification with invalid value
67 cout << "\nHour after modification: "<< t.getHour();
68
69 // Dangerous: Function call that returns
70 // a reference can be used as an lvalue!
71 t.badSetHour(12) = 74;
72 cout << "\n\n*******************************************\n"
73 << "POOR PROGRkMMING PRACTICE!!!!!!!!\n"
74 << "badSetHour as an lvalue, Hour:"
75 << t.getHour()
76 << "\n*************************************** << endl;
77
78 return 0;
79 }
输出结果:
Hour before modification: 20
Hour after modification: 30
*********************************
POOR PROGRAMMING PRACTICE!!!!!!!!
badSetHour as an lvalue, Hour: 74
*********************************
图 6.11 返回对 private 数据成员引用
程序首先声明 Time 对象t和引用 hourRef(把调用 t.badSetHour(20)
返回的引用赋给 hourRef)。程序显示别名 hourRef 的值。然后用这个别名设置 hour 的值为 30(无效值)并再次显示该值。最后,用函数调用本身作为左值并赋值 74(另一无效值),再次显示该值。