I am trying to learn about inheritance, and how private, protected, and public variables work.
My understanding is that a class's private variables can only be read by members of that class, and that protected variables can be read by members of that class, and by derived classes.
I am implementing some code to make sure that I understand this correctly, and I seem to be able to access variables that I didn't expect to be able to.
I have a class Polygon, and a derived class Triangle. I wrote a set of read() functions in the public areas of those classes to read their variables. These functions are overloaded so that with no arguments, read() will return the variables of the calling object, or alternatively, read(&Poly) can take another polygon as an argument and return the other polygon's variables.
#include <iostream>
using namespace std;
class Polygon;
class Triangle;
class Polygon {
private:
int privatePoly = 1;
protected:
int protectedPoly = 10;
public:
int publicPoly = 100;
// Setters
void setPrivate (int x) { privatePoly = x; }
void setProtected (int x) { protectedPoly = x; }
// Read
int readPrivate (const Polygon& inPoly) { return inPoly.privatePoly; }
int readProtected (const Polygon& inPoly) { return inPoly.protectedPoly; }
int readPublic (const Polygon& inPoly) { return inPoly.publicPoly; }
};
class Triangle : public Polygon {
private:
int privateTriangle = 3;
protected:
int protectedTriangle = privateTriangle*10;
public:
int publicTriangle = privateTriangle*100;
// Read Triangle variables
int readPrivate_Tri () { return privateTriangle; }
int readProtected_Tri () { return protectedTriangle; }
int readPublic_Tri () { return publicTriangle; }
int readPrivate_Tri (const Triangle& inTri) { return inTri.privateTriangle; }
int readProtected_Tri (const Triangle& inTri) { return inTri.protectedTriangle; }
int readPublic_Tri (const Triangle& inTri) { return inTri.publicTriangle; }
};
I instantiated one object of each type, Polygon P1, and Triangle T1, and tried to read P1's private variables from the derived class T1, expecting this to fail since private variables shouldn't be readable by derived classes. It didn't.
int main(int argc, const char * argv[]) {
Polygon P1;
Triangle T1;
// To make sure T1's polygon variables are different from P1's.
T1.setPrivate(2);
T1.setProtected(20);
// T1 reading P1
cout << "T1.readPrivate(P1): " << T1.readPrivate(P1) << endl;
cout << "T1.readProtected(P1): " << T1.readProtected(P1) << endl;
cout << "T1.readPublic(P1): " << T1.readPublic(P1) << endl << endl;
return 0;
}
This produces
T1.readPrivate(P1): 1
T1.readProtected(P1): 10
T1.readPublic(P1): 100
I thought perhaps this was related to the fact that the read functions were originally declared in the parent Polygon class (and that the private/protected specifiers referred to where the functions were declared rather than who the calling object was), so I gave the Triangle class its own copy of the readPolygon(&Polygon) variables. The following was added to the definition of the Triangle class:
// Read Polygon variables with separate function unique to Triangle class
int readProtected_P_from_T (const Polygon& inPoly) { return inPoly.protectedPoly; }
int readPublic_P_from_T (const Polygon& inPoly) { return inPoly.publicPoly; }
Where the readPublic_P_from_T() function was added to check the function format.
This doesn't compile, with the error: "'protectedPoly' is a protected member of 'Polygon'"
I expected this to work because I thought a derived class could see protected variables.
And I expected the first readPrivate function to not work, when called from the derived class.
Could someone please explain how these access specifiers work?