Visibility Modes in C++ Explained

Visibility Modes in C++

In Inheritance, when classes inherit from one another, visibility modes become noticeable. In this article, we will examine the C++ visibility mode along with practice code examples about the public, private and protected members during Inheritance in C++.


C++ Visibility Modes

Visibility modes are an important aspect of the C++ programming language that affects how a programmer can use variables, classes, their executable codes, objects, and functions. Moreover, it enables developers to create complex applications. Each mode controls how much an element can be seen inside and outside its class.


C++: Visibility Mode Types

Think about inheritance, global versus local access, and public versus private access when using these modes. C++ has three main visibility modes, as given below.

  • Public: In public mode, different parts of the code can freely access any part of a class or object. Public elements can be accessed and modified from anywhere.
  • Private: Conversely, the private mode limits accessibility to only the internal parts of the class, and private elements limit access to just the class itself.
  • Protected: Protected elements restrict access to members of the same class or derived classes. Protected visibility opens accessibility to some methods beyond what is seen in private mode.
Note
By default, in C++, visibility mode is set to private.
Derived Class Derived Class Derived Class
Base Class Private Visibility Mode Protected Visibility Mode Public Visibility Mode
Private No inheritance No inheritance No inheritance
Protected Private Protected Protected
Public Private Protected Public

Why Would a C++ Programmer Need Visible Mode?

  • Visibility mode lets you choose which class members and functions can be accessed, so you can write code that fits the needs of a specific application.
  • In C++, the visibility mode helps with encapsulation.
  • It means that private or protected members of a class are hidden from outside users. It also makes it easier to conceal information so that classes or other data are not accidentally used.
  • Developers greatly benefit from visibility mode because it makes the code easier to maintain and debug over time and reduces the occurrence of errors in application development.

C++ Public Visibility Mode 

If a subclass is derived from a public base class, the public members of the base class then become public members of the derived class. The protected members also become protected constituents of the derived class.

class A {
  private: int x;
  protected: int y;
  public: int z;
};
class B: public A {
  //protected: int y; inherited from class A
  //private: int z; inherited from class A
  //visibility mode is public, so the protected members of class A become protected members of class B, whereas the public members of class A become public members of class B.
};
int main() {
  //Only the public int z can be accessed in the main function using an object of Class B;
  B obj;
  cout << obj.z;
  return 0;
}

Compilation Error1

#include <bits/stdc++.h>

using namespace std;

// Parent class
class ParentClass {

  public: int publicVar; // Public variable     
  protected: int protectedVar; // Protected variable  
  private: int privateVar; // Private variable

};

class ChildClass: public ParentClass {

};

int main() {

  ChildClass ChildClass;

  cout << ChildClass.publicVar << endl; //variable Accessible
  cout << ChildClass.protectedVar << endl; //Error: variable Inaccessible
  cout << ChildClass.privateVar << endl; //Error: variable Inaccessible
  return 0;

};

Output

main.cpp: In function ‘int main()’:
main.cpp:23:22: error: ‘int ParentClass::protectedVar’ is protected within this context
   23 |   cout << ChildClass.protectedVar << endl; //Error: variable Inaccessible
      |                      ^~~~~~~~~~~~
main.cpp:9:18: note: declared protected here
    9 |   protected: int protectedVar; // Protected variable
      |                  ^~~~~~~~~~~~
main.cpp:24:22: error: ‘int ParentClass::privateVar’ is private within this context
   24 |   cout << ChildClass.privateVar << endl; //Error: variable Inaccessible
      |                      ^~~~~~~~~~
main.cpp:10:16: note: declared private here
   10 |   private: int privateVar; // Private variable
      |                ^~~~~~~~~~

Explanation for the error above

  • publicVar is public and will continue to be public, so the compiler will display its value.
  • protectedVar is protected and will remain protected; therefore, the visibility error will persist.
  • Because privateVar is private and will remain private, it is not accessible from childClass; thus, the compiler will throw the visibility error.

C++ Protected Visibility Mode

Suppose a subclass derives from a Protected base class; the visibility mode is Protected. Then, both public and protected base class members will become protected in the derived class.

#include <iostream>

class A {
  private: int x;
  protected: int y;
  public: int z;
};
class B: protected A {
  //protected: int y,int z  inherited from class A
  //visibility mode is protected so the protected and public members of class A becomes the protected members of Class B
};
int main() {
  //As the class B members are protected, you cannot access them in the main using the Class B object.
  return 0;
}

Compilation error1

#include <bits/stdc++.h>

using namespace std;

// Parent class
class ParentClass {

  public: int publicVar; // Public variable	
  protected: int protectedVar; // Protected variable	
  private: int privateVar; // Private variable

};

class ChildClass: protected ParentClass {};

int main() {
  ChildClass ChildClass;
  cout << ChildClass.publicVar << endl; //Error: variable Inaccessible
  cout << ChildClass.protectedVar << endl; //Error: variable Inaccessible
  cout << ChildClass.privateVar << endl; //Error: variable Inaccessible
  return 0;
};

Output

main.cpp: In function ‘int main()’:
main.cpp:18:22: error: ‘int ParentClass::publicVar’ is inaccessible within this context
   18 |   cout << ChildClass.publicVar << endl; //Error: variable Inaccessible
      |                      ^~~~~~~~~
main.cpp:8:15: note: declared here
    8 |   public: int publicVar; // Public variable
      |               ^~~~~~~~~
main.cpp:19:22: error: ‘int ParentClass::protectedVar’ is protected within this context
   19 |   cout << ChildClass.protectedVar << endl; //Error: variable Inaccessible
      |                      ^~~~~~~~~~~~
main.cpp:9:18: note: declared protected here
    9 |   protected: int protectedVar; // Protected variable
      |                  ^~~~~~~~~~~~
main.cpp:20:22: error: ‘int ParentClass::privateVar’ is private within this context
   20 |   cout << ChildClass.privateVar << endl; //Error: variable Inaccessible
      |                      ^~~~~~~~~~
main.cpp:10:16: note: declared private here
   10 |   private: int privateVar; // Private variable
      |                ^~~~~~~~~~

Explanation for the error code above

  • publicVar is public and will become protected; therefore, a visibility error will occur
  • protectedVar is protected and will remain protected; therefore, the visibility error will persist
  • privateVar is not accessible from ChildClass because privateVar is private and will remain private. Therefore, compiler will throw the visibility error.

C++ Private Visibility Mode

When a subclass is derived from a Private base class, then both public and protected base class members will become private in the derived class.

class A {
  private: int x;
  protected: int y;
  public: int z;
};
class B: private A {
  //Since the visibility mode is private, none of the base class's members are inherited by the derived class.
};
int main() {
  return 0;
}

Compilation error1

#include <bits/stdc++.h>

using namespace std;

// Parent class
class ParentClass {

  public: int publicVar; // Public variable	
  protected: int protectedVar; // Protected variable	
  private: int privateVar; // Private variable

};

class ChildClass: private ParentClass {};

int main() {
  ChildClass ChildClass;
  cout << ChildClass.publicVar << endl; //Error: variable Inaccessible
  cout << ChildClass.protectedVar << endl; //Error: variable Inaccessible
  cout << ChildClass.privateVar << endl; //Error: variable Inaccessible
  return 0;
};

Output

main.cpp: In function ‘int main()’:
main.cpp:18:22: error: ‘int ParentClass::publicVar’ is inaccessible within this context
   18 |   cout << ChildClass.publicVar << endl; //Error: variable Inaccessible
      |                      ^~~~~~~~~
main.cpp:8:15: note: declared here
    8 |   public: int publicVar; // Public variable
      |               ^~~~~~~~~
main.cpp:19:22: error: ‘int ParentClass::protectedVar’ is protected within this context
   19 |   cout << ChildClass.protectedVar << endl; //Error: variable Inaccessible
      |                      ^~~~~~~~~~~~
main.cpp:9:18: note: declared protected here
    9 |   protected: int protectedVar; // Protected variable
      |                  ^~~~~~~~~~~~
main.cpp:20:22: error: ‘int ParentClass::privateVar’ is private within this context
   20 |   cout << ChildClass.privateVar << endl; //Error: variable Inaccessible
      |                      ^~~~~~~~~~
main.cpp:10:16: note: declared private here
   10 |   private: int privateVar; // Private variable
      |                ^~~~~~~~~~

Explanation for the error code above

  • publicVar is a public variable that will become private, which will result in a visibility mistake
  • protectedVar is a protected variable that will become private, generating a visibility error.
  • privateVar is not accessible from ChildClass as privateVar is private and will remain private, resulting in a visibility fault.

C++ Public protected private Visibility mode in Inheritance

Working with C++ is notoriously tricky, especially when one needs prior language experience. We sometimes run into problems that cannot be fixed, like code for creating visibility modes that give errors because it needs to use the right syntax. With any error in C++, it’s important to take a step back and ensure all line items follow the syntax guidelines.


After inheriting, how do I switch the Visibility mode?

After inheriting a base class with the aid of a specified Visibility mode, the visibility of its members will change automatically, as described above. However, we must manually alter the visibility after this Inheritance. Otherwise, it will throw compilation errors.


C++ Visibility mode Syntax

<visibility_mode>:
using base::<member>;

C++ Change the visibility of a variable “publicVar” to public

<public>:
using base::<variable>;

Consider a base class with public publicVar members, protected protectedVar members, and private privateVar members. The code below describes how to shift protectedVar from protected to public visibility.

#include <bits/stdc++.h>

using namespace std;

// Parent class
class ParentClass {

  public: int publicVar; // Public variable

  protected: int protectedVar1; // Protected variable
  int protectedVar2; // Protected variable

  private: int privateVar1; // Private variable
  int privateVar2; // Private variable

};

class ChildClass: private ParentClass { // Parent Class is Private now

  public: using ParentClass::publicVar; // As parentClass is private , so Change publicVar visibility mode
  using ParentClass::protectedVar1; //To access, change the visibility of protected variable from private to public
};

int main() {
  ChildClass ChildClass;
  cout << ChildClass.publicVar << endl; //variable Accessible
  cout << ChildClass.protectedVar1 << endl; //variable Accessible
  return 0;
};

Compilation Error1

#include <bits/stdc++.h>

using namespace std;

// Parent class
class ParentClass {

  public: int publicVar; // Public variable

  protected: int protectedVar1; // Protected variable
  int protectedVar2; // Protected variable

  private: int privateVar1; // Private variable
  int privateVar2; // Private variable

};

class ChildClass: private ParentClass { // Parent Class is Private now

  public: using ParentClass::publicVar; // As parentClass is private , so Change publicVar visibility mode
  using ParentClass::protectedVar1; //To access, change the visibility of protected variable from private to public
  using ParentClass::privateVar1; //Error: You cant change the visibility of private variable from private to public
};

int main() {
  ChildClass ChildClass;
  cout << ChildClass.publicVar << endl; //variable Accessible
  cout << ChildClass.protectedVar1 << endl; //variable Accessible
  cout << ChildClass.protectedVar2 << endl; //Error: variable Inaccessible, visibility of protected variable not changed.
  cout << ChildClass.privateVar1 << endl; //Error: variable Inaccessible
  cout << ChildClass.privateVar2 << endl; //Error: variable Inaccessible
  return 0;
};

Output

main.cpp:18:7: error: ‘int ParentClass::privateVar1’ is private within this context
   18 | class ChildClass: private ParentClass { // Parent Class is Private now
      |       ^~~~~~~~~~
main.cpp:13:16: note: declared private here
   13 |   private: int privateVar1; // Private variable
      |                ^~~~~~~~~~~
main.cpp: In function ‘int main()’:
main.cpp:29:22: error: ‘int ParentClass::protectedVar2’ is protected within this context
   29 |   cout << ChildClass.protectedVar2 << endl; //Error: variable Inaccessible, visibility of protected variable not changed.
      |                      ^~~~~~~~~~~~~
main.cpp:11:7: note: declared protected here
   11 |   int protectedVar2; // Protected variable
      |       ^~~~~~~~~~~~~
main.cpp:31:22: error: ‘int ParentClass::privateVar2’ is private within this context
   31 |   cout << ChildClass.privateVar2 << endl; //Error: variable Inaccessible
      |                      ^~~~~~~~~~~
main.cpp:14:7: note: declared private here
   14 |   int privateVar2; // Private variable
      |       ^~~~~~~~~~~

Conclusion

Any C++ programmer who wants to improve the security and organization of their code needs to know about these different visibility modes. The visibility modes tell a class that inherits from a base class whether or not you can use the base. A derived class doesn’t inherit access to private data members. But it gets a full object from its parent, including any private members declared by the parent class. After inheriting a base class with a specified visibility mode, the visibility of its members will change automatically, as explained above. However, we must manually alter the visibility after inheritance by using proper syntax.