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++.
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.
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.
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 |
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; }
#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.privateVar
is private and will remain private, it is not accessible from childClass; thus, the compiler will throw the visibility error.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; }
#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 occurprotectedVar
is protected and will remain protected; therefore, the visibility error will persistprivateVar
is not accessible from ChildClass because privateVar
is private and will remain private. Therefore, compiler will throw the visibility error.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; }
#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 mistakeprotectedVar
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.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 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.
<visibility_mode>: using base::<member>;
<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; };
#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 | ^~~~~~~~~~~
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.