简体   繁体   中英

Don't understand private/protected variables. My implementation didn't do what I expected

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?

Any function within a class can access its private variables. It can access protected and public variables from iherited classes as well.

If the function itself is public, anyone can call it.

Usually private variables are used for internal needs of the class by its member functions and are not intended for the public. However, public member functions can use them for doing a particular action.

In your case all member functions are public. Therefore, you can call them to access any internal data inside the class.

If you want to fail, try to access the member data directly without the function. For example

class A {
   int a = 0;
public:
   int b = 1;
   int getA() {
       return a;
   }
};


 A c1;
 cout << c1.a << c1.b;

the compiler will fail on the member access, because a is private.

On the other hand, if you use the getA() function, it will work, because the function itself can access private members:

cout << c1.getA() << c1.b;

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.

That understanding is correct.

I instantiate 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.

readPrivate() is a member of Polygon , so it has no problem reading Polygon 's internals.

(Public) Inheritance allows Triangle to have these functions too, but since they are actually at the Polygon level, it doesn't have a problem.

This doesn't compile, with the error: "'protectedPoly' is a protected member of 'Polygon'"

You are running into this situation . That link explains that problem and its answer far better than I could, so I'll leave it right there.

Could someone please explain how these access specifiers work?

You seem to have a pretty good grasp on the subject already, except with a few minor discrepancies. However, if you wish to read up more on inheritance, here is a useful resource on it .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM