9.9 Time Class Case Study: A Subtle Trap — Returning a Reference or a Pointer to a private Data Member
A reference to an object is an alias for the name of the object and, hence, may be used on the left side of an assignment statement. In this context, the reference makes a perfectly acceptable lvalue that can receive a value.
A member function can return a reference to a private data member of that class. If the reference return type is declared const, the reference is a nonmodifiable lvalue and cannot be used to modify the data. However, if the reference return type is not declared const, subtle errors can occur.
The program of Figs. 9.11–9.13 uses a simplified Time class (Fig. 9.11 and Fig. 9.12) to demonstrate returning a reference to a private data member with member function badSetHour (declared in Fig. 9.11 in line 13 and defined in Fig. 9.12 in lines 25–34). Such a reference return actually makes a call to member function badSetHour an alias for private data member hour! The function call can be used in any way that the private data member can be used, including as an lvalue in an assignment statement, thus enabling clients of the class to clobber the class’sprivatedata at will! A similar problem would occur if a pointer to the private data were to be returned by the function.
Figure 9.13 declares Time object t (line 9) and reference hourRef (line 12), which is initialized with the reference returned by the call t.badSetHour(20). Line 14 displays the value of the alias hourRef. This shows how hourRefbreaks the encapsulation of the class—statements in main should not have access to the private data in an object of the class. Next, line 15 uses the alias to set the value of hour to 30 (an invalid value) and line 16 displays the value returned by function getHour to show that assigning a value to hourRef actually modifies the private data in the Time object t. Finally, line 20 uses the badSetHour function call itself as an lvalue and assigns 74 (another invalid value) to the reference returned by the function. Line 25 again displays the value returned by function getHour to show that assigning a value to the result of the function call in line 20 modifies the private data in the Time object t.
Software Engineering Observation 9.7
Returning a reference or a pointer to aprivatedata member breaks the encapsulation of the class and makes the client code dependent on the representation of the class’s data. There are cases where doing this is appropriate—we’ll show an example of this when we build our customArrayclass in Section 10.10.