1

I know the definition of private and protected, and what their differences are. However, when I go ahead and play around with them to test every different scenario, I am not getting consistent/expected behavior. This is the paragraph that confuses me (from Teach Yourself C++ in 21 days :) )

In total, three access specifiers exist: public, protected, and private. If a function has an object of your class, it can access all the public member data and functions. The member functions, in turn, can access all private data members and functions of their own class and all protected data members and functions of any class from which they derive.

To be more specific, I wrote a code to see (the code is below the question statement): 1- If Frisky and Boots, two instances of the Cat class, can see each other's private data. By "see"ing, I mean to have member functions that takes the other cat as its argument and be able to set/get its private data. The claim was they should be, and I can confirm it.

2- With the same meaning for "see"ing, can a member function in the cat "Frisky" take as an argument an instance of Mammal, say "Human", and set/get its protected data? I understand from above claim that yes it should, but the code won't compile. It complains that it is protected.

If I am understanding this wrong, what is actually meant by the above paragraph? Any help is appreciated, thanks!

using namespace std;

class Mammal
{
public:
    int myNumFeet;
    void setMyNumVertebras(int);
protected:
    int myNumVertebras;
};


class Cat : public Mammal
{
public:
    void tellHisAge(Cat);
    void tellHisNumVertebras(Mammal);
    void setMyAge(int);

private:
    int myAge;
    int myWeight;
};

int main()
{
    Cat Frisky;
    Frisky.setMyAge(3);
    Frisky.setMyNumVertebras(23);

    Cat Boots;
    Boots.setMyAge(4);
    Boots.setMyNumVertebras(23);

    Mammal Human;
    Human.setMyNumVertebras(33);

    Frisky.tellHisAge(Boots);

    Frisky.tellHisNumVertebras(Human);
    return 0;
}

void Cat::tellHisAge(Cat Boots)
{
    cout << Boots.myAge <<endl;
}
void Cat::setMyAge(int age)
{
    myAge = age;
}

void Mammal::setMyNumVertebras(int num)
{
    myNumVertebras = num;
}

void Cat::tellHisNumVertebras(Mammal Human)
{
    cout<< myNumVertebras <<endl;
}

1 Answers1

1

What you are seeing is the correct behavior for inheritance. Peers can see each others' private and protected members, but they cannot see the private and protected members of a parent class.

I offer you two references:

It's OK for instances of Cat to see the private and protected members of Cat, because presumably the logic in Cat fully understands the constraints of the class at that level, and will maintain all of the class invariants.

Cat, despite being a Mammal, is not privy to the implementation of Mammal, and so cannot see its private members. The idea is that Mammal has sealed off its implementation, including to classes that inherit from it.

Cat can also see the protected members it inherited from Mammal in another instance of Cat (or something that inherits from Cat). That is, if you pass a Cat (or something derived from Cat) to one of Cat's member functions, it can see the protected members it inherited from Mammal, as well as the private members of Cat.

It cannot, however, see the protected members of a random Mammal. If you just pass a Mammal& or Mammal* to a method in Cat, all that Cat knows is that they have a common ancestor, Mammal. If another class inherits from Mammal, it might use the protected members of Mammal in a way that Cat doesn't expect. Therefore, you cannot access the protected members of a Mammal object from within Cat.

Protected members are some of the most annoying members to reason about, because they represent a very limited interface between a base class and a derived class that has no abstraction. They are inherently fragile. See my first link above for a more general explanation.

Community
  • 1
  • 1
Joe Z
  • 17,413
  • 3
  • 28
  • 39
  • Thanks a lot for comprehensive reply. Your explanation makes total sense and I think my confusion is this sentence that I quoted from the book: "The member functions, in turn, can access all private data members and functions of their own class and all protected data members and functions of any class from which they derive." The second claim is wrong based on your explanation and my understanding, do you agree? Or am I still not getting the point of the second part of this quoted sentence? You seem to claim "...and all protected data members and functions of any class that DERIVES FROM THEM." – user3133942 Dec 25 '13 at 15:23
  • @user3133942 : I think the statement becomes correct as long as you apply it only to instances of that same class. (Instances of `Cat` in this example.) – Joe Z Dec 25 '13 at 15:45