Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>The <code>protected</code> keyword allows an inheriting class to see the <code>protected</code> members. That means instances of the inheriting class can see the protected members of themselves, as well as the protected members of other instances of that same inheriting class. It does not extend this access through pointers to the parent class type, because that access isn't safe.</p> <p>Let's make that concrete. Consider the following example:</p> <pre><code>class A { protected: int a_int; }; class B : public A { public: int good() { return a_int; // OK: Protected member of this instance } int bad( A *a_ptr ) { return a_ptr-&gt;a_int; // BAD: Can't access the protected member // through a pointer to the parent class type. } int also_good( B *b_ptr ) { return b_ptr-&gt;a_int; // OK: Pointer to the same class type as this // class is safe. } }; </code></pre> <p>The errors in your code look like the second case. So why is the second case illegal, but third case OK?</p> <p>The second case is illegal because the compiler doesn't know the actual type of object the <code>A*</code> points to. It could be <em>any</em> descendent of <code>A</code>, and may not even be convertible to <code>B*</code>. Therefore, the access extended by the <code>protected</code> clause isn't guaranteed to be safe or meaningful. For example, suppose you had</p> <pre><code>class C : public A { ... }; class D : public C { ... }; </code></pre> <p>and you passed a <code>C*</code> or a <code>D*</code> into method <code>bad()</code> above. It doesn't seem reasonable that <code>B</code> should be able to see the protected members that were exposed to <code>C</code>, since <code>C</code> and <code>B</code> aren't directly related. The same holds true for <code>D</code>.</p> <p>But, in the third case, the compiler knows for certain it has a pointer to a <code>B</code> or a class derived from <code>B</code>, so it knows that the access extended by the <code>protected</code> keyword is safe and meaningful. By that, I mean that the protected fields are managed in the way <code>B</code> expects them to be managed. In fact, without that access, you would have a hard time writing binary operators involving two instances of <code>B</code></p> <p>Make sense?</p> <p>In case you're still not convinced: Suppose I made two parallel classes, both which inherit from <code>node</code>:</p> <pre><code>// plain singly linked list class normal_sll : public node { }; // singly linked list that stores all of its elements negated class negative_sll : public node { }; </code></pre> <p>Sure, it's a contrived example, but bear with me. Because both classes derive from <code>node</code>, you could pass either class through a <code>node *</code>. So, you could pass an instance of <code>negative_sll</code> to <code>normal_sll</code> or vice versa.</p> <p>C++'s access control prevents either class from looking at the protected fields through that <code>node *</code>, though. And that's good, because <code>negative_sll</code> manages them differently than <code>normal_sll</code>.</p> <p>But, you can't pass an instance of <code>negative_sll</code> through a <code>normal_sll*</code> or vice versa. So, you know if you have a <code>normal_sll*</code> inside one of <code>normal_sll</code>'s methods, you know it's safe to access the protected members.</p> <p>Sure, it's a contrived example. I'm sure you could think of a better one. Make sense, though?</p> <p>Now you could make <code>B</code> a <code>friend</code> of <code>A</code> and override this control. But, this would let <code>B</code> see the <em>private</em> members of <code>A</code>, totally bypassing the <code>protected</code> concept. A better solution would be to rewrite your <code>SLL</code> code so that you pass <code>SLL*</code>, not <code>node*</code> to its methods.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload