Member Access Control in Inheritance

Member Access Control in Inheritance

Understanding Member Access Control

In C++, member access control determines which members of a class can be accessed from other classes or objects. When inheritance is involved, this control extends to derived classes, allowing for controlled visibility of base class members. The access specifiers (public, protected, private) dictate the level of access, and their application in inheritance scenarios is critical for maintaining encapsulation and flexibility.

Access Specifiers in C++

C++ provides three access specifiers:

  • public: Members are accessible from anywhere.
  • protected: Members are accessible within the class and derived classes.
  • private: Members are only accessible within the defining class.

When inheritance is involved, these specifiers determine how members are visible in the derived class.


Inheritance and Access Specifiers

Public Inheritance

In a public inheritance, all members of the base class are visible in the derived class. The access specifiers of the base class members are preserved, and the derived class can access them directly.

class Base {
public:
    int publicMember;
protected:
    int protectedMember;
private:
    int privateMember;
};

class Derived : public Base {
public:
    void accessMembers() {
        publicMember = 42;  // Valid
        protectedMember = 21;  // Valid
        privateMember = 10;  // Invalid
    }
};

In this example, the Derived class can access all members of Base due to public inheritance. However, the privateMember is inaccessible because it is private in the base class.


Protected Inheritance

In a protected inheritance, the base class members are accessible within the derived class but not outside. This ensures that derived classes can access members but not their implementations.

class Base {
public:
    int publicMember;
protected:
    int protectedMember;
private:
    int privateMember;
};

class Derived : protected Base {
public:
    void accessMembers() {
        protectedMember = 21;  // Valid
        // publicMember = 42;  // Invalid
    }
};

Here, Derived can access protectedMember but not publicMember. The privateMember is not accessible at all.


Private Inheritance

In a private inheritance, the base class is hidden from the derived class, and the derived class cannot access the base class's members directly. This is often used to encapsulate implementation details.

class Base {
public:
    int publicMember;
protected:
    int protectedMember;
private:
    int privateMember;
};

class Derived : private Base {
public:
    void accessMembers() {
        // Base::publicMember = 42;  // Invalid
        // Base::protectedMember = 21;  // Invalid
        // Base::privateMember = 10;  // Invalid
    }
};

The Derived class cannot access any members of Base directly. This ensures that the base class's implementation is encapsulated.


Rules When Inheriting from Multiple Classes

When a class inherits from multiple bases, the access specifiers of the base class members are resolved based on their visibility in the inheritance hierarchy. The rules are as follows:

  1. Public inheritance allows all members to be accessed.
  2. Protected inheritance restricts access to members within the derived class.
  3. Private inheritance hides all members from the derived class.

The visibility of members depends on the access specifiers of the base class and the inheritance type. For example, if a base class has a protected member and the derived class inherits publicly, the member is accessible within the derived class but not outside.


Practical Examples

  1. Public Inheritance:
    A derived class can access all base class members directly.

    class Base { public: int x; };
    class Derived : public Base { public: int y; };
    
  2. Protected Inheritance:
    The derived class can access members but not their implementations.

    class Base { protected: int x; };
    class Derived : protected Base { public: int y; };
    
  3. Private Inheritance:
    The derived class cannot access any members of the base class.

    class Base { private: int x; };
    class Derived : private Base { };
    

Conclusion

Member access control in inheritance is a fundamental aspect of C++ design, enabling controlled visibility of base class members in derived classes. The use of access specifiers (public, protected, private) determines how members are accessible, and inheritance types (public, protected, private) dictate the rules for visibility. Understanding these concepts is essential for writing encapsulated and flexible C++ code.