Note that there are some explanatory texts on larger screens.

plurals
  1. POWhy does this derived class need to be declared as a friend?
    primarykey
    data
    text
    <p>I'm learning C++ on my own, and I thought a good way to get my hands dirty would be to convert some Java projects into C++, see where I fall down. So I'm working on a polymorphic list implementation. It works fine, except for one strange thing.</p> <p>The way I print a list is to have the <code>EmptyList</code> class return "null" (a string, not a pointer), and <code>NonEmptyList</code> returns a string that's their data concatenated with the result of calling <code>tostring()</code> on everything else in the list.</p> <p>I put <code>tostring()</code> in a <code>protected</code> section (it seemed appropriate), and the compiler complains about this line (<code>s</code> is a <code>stringstream</code> I'm using to accumulate the string):</p> <pre><code>s &lt;&lt; tail-&gt;tostring(); </code></pre> <p>Here's the error from the compiler:</p> <pre> ../list.h: In member function 'std::string NonEmptyList::tostring() [with T = int]': ../list.h:95: instantiated from here ../list.h:41: error: 'std::string List::tostring() [with T = int]' is protected ../list.h:62: error: within this context </pre> <p>Here's most of <code>list.h</code>:</p> <pre><code>template &lt;class T&gt; class List; template &lt;class T&gt; class EmptyList; template &lt;class T&gt; class NonEmptyList; template &lt;typename T&gt; class List { public: friend std::ostream&amp; operator&lt;&lt; (std::ostream&amp; o, List&lt;T&gt;* l){ o &lt;&lt; l-&gt;tostring(); return o; } /* If I don't declare NonEmptyList&lt;T&gt; as a friend, the compiler complains * that "tostring" is protected when NonEmptyClass tries to call it * recursively. */ //friend class NonEmptyList&lt;T&gt;; virtual NonEmptyList&lt;T&gt;* insert(T) =0; virtual List&lt;T&gt;* remove(T) =0; virtual int size() = 0; virtual bool contains(T) = 0; virtual T max() = 0; virtual ~List&lt;T&gt;() {} protected: virtual std::string tostring() =0; }; template &lt;typename T&gt; class NonEmptyList: public List&lt;T&gt;{ friend class EmptyString; T data; List&lt;T&gt;* tail; public: NonEmptyList&lt;T&gt;(T elem); NonEmptyList&lt;T&gt;* insert(T elem); List&lt;T&gt;* remove(T elem); int size() { return 1 + tail-&gt;size(); } bool contains(T); T max(); protected: std::string tostring(){ std::stringstream s; s &lt;&lt; data &lt;&lt; ","; /* This fails if List doesn't declare NonEmptyLst a friend */ s &lt;&lt; tail-&gt;tostring(); return s.str(); } }; </code></pre> <p>So declaring <code>NonEmptyList</code> a friend of <code>List</code> makes the problem go away, but it seems really strange to have to declare a derived class as a friend of a base class.</p>
    singulars
    1. This table or related slice is empty.
    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.
 

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