Objects and Classes in C++: Data Field Encapsulation

Making data fields private protects data and makes the class easy to maintain.

The data fields radius in the Circle class in Listing 9.1 can be modified directly (e.g., circlel.radius = 5). This is not a good practice—for two reasons:

  • First, data may be tampered with.
  • Second, it makes the class difficult to maintain and vulnerable to bugs. Suppose you want to modify the Circle class to ensure that the radius is nonnegative after other programs have already used the class. You have to change not only the Circle class, but also the programs that use the Circle This is because the clients may have modified the radius directly (e.g., myCircle.radius = -5).

To prevent direct modifications of properties, you should declare the data field private, using the private keyword. This is known as data field encapsulation. Making the radius data field private in the Circle class, you can define the class as follows:

class Circle

{

public:

Circle();

Circle(double);

double getArea();

private:

double radius;

};

A private data field cannot be accessed by an object through a direct reference outside the class that defines the private field. But often a client needs to retrieve and/or modify a data field. To make a private data field accessible, provide a get function to return the field’s value. To enable a private data field to be updated, provide a set function to set a new value.

A get function has the following signature:

returnType getPropertyName()

If the returnType is bool, by convention the get function should be defined as follows:

bool is PropertyName()

A set function has the following signature:

void setPropertyName(dataType propertyValue)

Let us create a new circle class with a private data field radius and its associated acces­sor and mutator functions. The class diagram is shown in Figure 9.6. The new circle class is defined in Listing 9.9.

Listing 9.9 CircleWithPrivateDataFields.h

1 #ifndef CIRCLE_H
2
#define CIRCLE_H
3
4
class Circle
5 {
6   
public:
7    Circle();
8    Circle(
double);
9   
double getArea();
10   
double getRadius();
11   
void setRadius(double);
12
13   
private:
14   
double radius;
15 };
16
17
#endif

Listing 9.10 implements the class contract specified in the header file in Listing 9.9

Listing 9.10 CircleWithPrivateDataFields.cpp

1 #include “CircleWithPrivateDataFields.h”
2
3
// Construct a default circle object
4 Circle::Circle()

5 {
6     radius =
1;
7 }
8
9
// Construct a circle object
10 Circle::Circle(double newRadius)
11 {
12    radius = newRadius;
13 }
14
15
// Return the area of this circle
16 double Circle::getArea()
17 {
18   
return radius * radius * 3.14159;
19 }
20
21
// Return the radius of this circle
22 double Circle::getRadius()
23 {
24     
return radius;
25 }
26
27
// Set a new radius
28 void Circle::setRadius(double newRadius)
29 {
30    radius = (newRadius >=
0) ? newRadius : 0;
31 }

The getRadius() function (lines 22-25) returns the radius, and the setRadius (newRadius) function (line 28-31) sets a new radius into the object. If the new radius is negative, 0 is set to the radius in the object. Since these functions are the only ways to read and modify radius, you have total control over how the radius property is accessed. If you have to change the functions’ implementation, you need not change the client programs. This makes the class easy to maintain.

Listing 9.11 is a client program that uses the Circle class to create a Circle object and modifies the radius using the setRadius function.

Listing 9.11 TestCircleWithPrivateDataFields.cpp

1 #include <iostream>
2
#include “CircleWithPrivateDataFields.h”
3 using namespace std;
4
5
int main()
6 {
7    Circle circle1;
8    Circle circle2(
5.0);
9
10    cout <<
“The area of the circle of radius ”
11      << circle1.getRadius() << ” is ” << circle1.getArea() << endl;
12    cout <<
“The area of the circle of radius ”
13      << circle2.getRadius() << ” is ” << circle2.getArea() << endl;
14
15     
// Modify circle radius
16    circle2.setRadius(100);
17 cout <<
“The area of the circle of radius ”
18 << circle2.getRadius() << ” is ” << circle2.getArea() << endl;
19
20
return 0;
21 }

The data field radius is declared private. Private data can be accessed only within their defining class. You cannot use circlel.radius in the client program. A compile error would occur if you attempted to access private data from a client.

Source: Liang Y. Daniel (2013), Introduction to programming with C++, Pearson; 3rd edition.

Leave a Reply

Your email address will not be published. Required fields are marked *