Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Understanding Encapsulation in C++ through Access Control and Member Functions

Tech Aug 1 2

Encapsulation combines data and the methods that operate on that data into a single unit, representing real-world entities. It also enforces controlled access to these internal components.

In C++, this unit is called a class. For example, we can design a Circle class to calculate its circumference.

#include <iostream>
const double PI_VALUE = 3.14159;

class CircularShape {
public: // Public access specifier
    int shape_radius; // Attribute (data member)

    double computePerimeter() { // Behavior (member function)
        return 2 * PI_VALUE * shape_radius;
    }
};

int main() {
    CircularShape my_circle; // Instantiation of an object
    std::cout << "Enter the circle's radius: ";
    std::cin >> my_circle.shape_radius;
    std::cout << "The circumference is: " << my_circle.computePerimeter() << std::endl;
    return 0;
}

In this example, class defines a new type. The class body includes access specifiers, attributes (data members), and behaviors (member functions). The process of creating an object from a class is instantiation. An object's members are accessed using the dot (.) operator.

Access Control Levels

A class designer can place members under different access specifiers to enforce encapsulation. The three levels are:

  1. public: Members are accessible from any where (both inside and outside the class).
  2. protected: Members are accessible within the class and by derived classes (subclasses), but not from outside the class hierarchy.
  3. private: Members are accessible only within the class itself.

The distinction between protected and private becomes significant with inheritance; a subclass can access protected members of its parent but not private ones.

#include <iostream>
#include <string>

class Human {
public:
    std::string person_name;

protected:
    std::string vehicle;

private:
    std::string secret_code;

public:
    void initializeData() {
        person_name = "Alex";
        vehicle = "Tractor";
        secret_code = "654321";
    }

    void displayName() {
        std::cout << person_name << std::endl;
    }

private:
    void displayVehicle() {
        std::cout << vehicle << std::endl;
    }

    void displaySecret() {
        std::cout << secret_code << std::endl;
    }
};

int main() {
    Human person_obj;
    person_obj.initializeData();

    person_obj.displayName(); // Allowed: public member
    // person_obj.displayVehicle(); // Error: protected member not accessible
    // person_obj.displaySecret();  // Error: private member not accessible

    person_obj.person_name = "Jamie"; // Allowed: public attribute
    person_obj.displayName();
    return 0;
}

Difference Between struct and class

In C++, struct and class are fundamentally the same except for they default access specifier.

  • Members of a struct default to public access.
  • Members of a class default to private access.
#include <iostream>

class ExampleClass { // Members are private by default
    int internal_data;
};

struct ExampleStruct { // Members are public by default
    int public_data;
};

int main() {
    ExampleClass obj_c;
    ExampleStruct obj_s;

    // obj_c.internal_data = 10; // Error: private member
    obj_s.public_data = 10;      // Allowed: public member
    return 0;
}

Benefits of Making Member Attributes Private

Declaring all data members as private offers key advantages:

  1. Fine-grained access control: You can precisely define read and write permissions through public member functions.
  2. Data validation: In the setter functions, you can implement logic to ensure the data being assigned is valid.
#include <iostream>
#include <string>

class Employee {
private: // All data is private
    std::string emp_name;  // Read-Write
    int emp_age = 30;      // Read-Only (no public setter)
    std::string emp_motto; // Write-Only (no public getter)

public: // Public interface to manage private data
    // Setter for name (Write permission with validation)
    void setName(const std::string& new_name) {
        if (!new_name.empty()) {
            emp_name = new_name;
        }
    }
    // Getter for name (Read permission)
    std::string getName() const {
        return emp_name;
    }

    // Getter for age (Read permission only)
    int getAge() const {
        return emp_age;
    }

    // Setter for motto (Write permission only)
    void setMotto(const std::string& motto) {
        emp_motto = motto;
    }
};

int main() {
    Employee worker;
    worker.setName("Casey");
    // worker.emp_age = 25; // Direct access is forbidden

    std::cout << "Name: " << worker.getName() << std::endl;
    std::cout << "Age: " << worker.getAge() << std::endl;

    worker.setMotto("Keep coding!");
    // std::cout << worker.emp_motto; // Cannot read write-only member
    return 0;
}

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.