You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

312 lines
21 KiB
HTML

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Chapter 15: Friends # In all examples discussed up to now, we&rsquo;ve seen that private members are only accessible by the members of their class. This is good, as it enforces encapsulation and data hiding. By encapsulating functionality within a class we prevent that a class exposes multiple responsibilities; by hiding data we promote a class&rsquo;s data integrity and we prevent that other parts of the software become implementation dependent on the data that belong to a class.">
<meta name="theme-color" media="(prefers-color-scheme: light)" content="#ffffff">
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="#343a40">
<meta name="color-scheme" content="light dark"><meta property="og:url" content="https://doc.cyub.vip/cpp/docs/Friends/">
<meta property="og:site_name" content="C&#43;&#43; Annotations Version 12.4.0">
<meta property="og:title" content="C&#43;&#43; Annotations Version 12.4.0">
<meta property="og:description" content="Chapter 15: Friends # In all examples discussed up to now, weve seen that private members are only accessible by the members of their class. This is good, as it enforces encapsulation and data hiding. By encapsulating functionality within a class we prevent that a class exposes multiple responsibilities; by hiding data we promote a classs data integrity and we prevent that other parts of the software become implementation dependent on the data that belong to a class.">
<meta property="og:locale" content="en">
<meta property="og:type" content="article">
<meta property="article:section" content="docs">
<title>Friends | C&#43;&#43; Annotations Version 12.4.0</title>
<link rel="manifest" href="/cpp/manifest.json">
<link rel="icon" href="/cpp/favicon.png" >
<link rel="canonical" href="https://doc.cyub.vip/cpp/docs/Friends/">
<link rel="stylesheet" href="/cpp/book.min.309b7ed028807cdb68d8d61e26d609f48369c098dbf5e4d8c0dcf4cdf49feafc.css" integrity="sha256-MJt&#43;0CiAfNto2NYeJtYJ9INpwJjb9eTYwNz0zfSf6vw=" crossorigin="anonymous">
<script defer src="/cpp/fuse.min.js"></script>
<script defer src="/cpp/en.search.min.96d87afe14f4404fb82eb23166af34b971841affca153da6e6aee977701013ac.js" integrity="sha256-lth6/hT0QE&#43;4LrIxZq80uXGEGv/KFT2m5q7pd3AQE6w=" crossorigin="anonymous"></script>
<script defer src="/cpp/sw.min.5d1fdbd1fdf1d81d76c1e5a2529d146b38922120c27ebed041d7584fa87ce6df.js" integrity="sha256-XR/b0f3x2B12weWiUp0UaziSISDCfr7QQddYT6h85t8=" crossorigin="anonymous"></script>
<!--
Made with Book Theme
https://github.com/alex-shpak/hugo-book
-->
</head>
<body dir="ltr">
<input type="checkbox" class="hidden toggle" id="menu-control" />
<input type="checkbox" class="hidden toggle" id="toc-control" />
<main class="container flex">
<aside class="book-menu">
<div class="book-menu-content">
<nav>
<h2 class="book-brand">
<a class="flex align-center" href="/cpp/"><span>C&#43;&#43; Annotations Version 12.4.0</span>
</a>
</h2>
<div class="book-search hidden">
<input type="text" id="book-search-input" placeholder="Search" aria-label="Search" maxlength="64" data-hotkeys="s/" />
<div class="book-search-spinner hidden"></div>
<ul id="book-search-results"></ul>
</div>
<script>document.querySelector(".book-search").classList.remove("hidden")</script>
<ul class="book-languages">
<li>
<input type="checkbox" id="languages" class="toggle" />
<label for="languages" class="flex justify-between">
<a role="button" class="flex align-center">
<img src="/cpp/svg/translate.svg" class="book-icon" alt="Languages" />
English
</a>
</label>
<ul>
<li>
<a href="https://doc.cyub.vip/cpp/zh/">
Chinese
</a>
</li>
</ul>
</li>
</ul>
<ul>
<li>
<a href="/cpp/docs/Overview/">1. Overview</a></li>
<li><strong>2. C++ Intro</strong></li>
<li>
<a href="/cpp/docs/A-First-Impression/">3. A First Impression</a></li>
<li>
<a href="/cpp/docs/Name-Spaces/">4. Name Spaces</a></li>
<li><strong>5. Strings</strong></li>
<li>
<a href="/cpp/docs/IOStreams/">6. IOStreams</a></li>
<li><strong>7. Classes</strong></li>
<li>
<a href="/cpp/docs/Static-Data-And-Functions/">8. Static Data And Functions</a></li>
<li><strong>9. Memory Management</strong></li>
<li><strong>10. Exceptions</strong></li>
<li><strong>11. Operator Overloading</strong></li>
<li><strong>12. Abstract Containers</strong></li>
<li><strong>13. Inheritance</strong></li>
<li><strong>14. Polymorphism</strong></li>
<li>
<a href="/cpp/docs/Friends/"class=active>15. Friends</a></li>
<li><strong>16. Pointers to Members</strong></li>
<li><strong>17. Nested Classes</strong></li>
<li><strong>18. Standard Template Library</strong></li>
<li><strong>19. Generic Algorithms</strong></li>
<li><strong>20. Multi Threading</strong></li>
<li><strong>21. Function Templates</strong></li>
<li><strong>22. Class Templates</strong></li>
<li><strong>23. Advanced Template Use</strong></li>
<li><strong>24. Coroutines</strong></li>
<li><strong>25. Examples</strong></li>
</ul>
</nav>
<script>(function(){var e=document.querySelector("aside .book-menu-content");addEventListener("beforeunload",function(){localStorage.setItem("menu.scrollTop",e.scrollTop)}),e.scrollTop=localStorage.getItem("menu.scrollTop")})()</script>
</div>
</aside>
<div class="book-page">
<header class="book-header">
<div class="flex align-center justify-between">
<label for="menu-control">
<img src="/cpp/svg/menu.svg" class="book-icon" alt="Menu" />
</label>
<strong>Friends</strong>
<label for="toc-control">
</label>
</div>
</header>
<article class="markdown book-article"><h1 id="chapter-15-friends">
Chapter 15: Friends
<a class="anchor" href="#chapter-15-friends">#</a>
</h1>
<p>In all examples discussed up to now, we&rsquo;ve seen that private members are only accessible by the members of their class. This is good, as it enforces encapsulation and data hiding. By encapsulating functionality within a class we prevent that a class exposes multiple responsibilities; by hiding data we promote a class&rsquo;s data integrity and we prevent that other parts of the software become implementation dependent on the data that belong to a class.</p>
<p>In this (very) short chapter we introduce the <code>friend</code> keyword and the principles that underly its use. The bottom line being that by using the <code>friend</code> keyword functions are granted access to a class&rsquo;s <code>private</code> members. Even so, this does not imply that the principle of data hiding is abandoned when the <code>friend</code> keyword is used.</p>
<p>In this chapter the topic of friendship among classes is not discussed. Situations in which it is natural to use friendship among classes are discussed in chapters
<a href="/cpp/">17</a> and
<a href="/cpp/">21</a> and such situations are natural extensions of the way friendship is handled for functions.</p>
<p>There should be a well-defined conceptual reason for declaring friendship (i.e., using the <code>friend</code> keyword). The traditionally offered definition of the class concept usually looks something like this:</p>
<blockquote>
<p>A class is a set of data together with the functions that operate on that data.</p>
</blockquote>
<p>As we&rsquo;ve seen in chapter
<a href="/cpp/">11</a> some functions have to be defined outside of a class interface. They are defined outside of the class interface to allow promotions for their operands or to extend the facilities of existing classes not directly under our control. According to the above traditional definition of the class concept those functions that cannot be defined in the class interface itself should nevertheless be considered functions belonging to the class. Stated otherwise: if permitted by the language&rsquo;s syntax they would certainly have been defined inside the class interface. There are two ways to implement such functions. One way consists of implementing those functions using available public member functions. This approach was used, e.g., in section
<a href="/cpp/">11.2</a>. Another approach applies the definition of the class concept to those functions. By stating that those functions in fact belong to the class they should be given direct access to the data members of objects. This is accomplished by the <code>friend</code> keyword.</p>
<p>As a general principle we state that all functions operating on the data of objects of a class that are declared in the same file as the class interface itself belong to that class and may be granted direct access to the class&rsquo;s data members.</p>
<h2 id="151-friend-functions">
15.1: Friend functions
<a class="anchor" href="#151-friend-functions">#</a>
</h2>
<p>In section 11.2 the insertion operator of the class <code>Person</code> (cf. section
<a href="/cpp/">9.3</a>) was implemented like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>ostream <span style="color:#f92672">&amp;</span><span style="color:#66d9ef">operator</span><span style="color:#f92672">&lt;&lt;</span>(ostream <span style="color:#f92672">&amp;</span>out, Person <span style="color:#66d9ef">const</span> <span style="color:#f92672">&amp;</span>person)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">return</span>
</span></span><span style="display:flex;"><span> out <span style="color:#f92672">&lt;&lt;</span>
</span></span><span style="display:flex;"><span> <span style="color:#e6db74">&#34;Name: &#34;</span> <span style="color:#f92672">&lt;&lt;</span> person.name() <span style="color:#f92672">&lt;&lt;</span> <span style="color:#e6db74">&#34;, &#34;</span>
</span></span><span style="display:flex;"><span> <span style="color:#e6db74">&#34;Address: &#34;</span> <span style="color:#f92672">&lt;&lt;</span> person.address() <span style="color:#f92672">&lt;&lt;</span> <span style="color:#e6db74">&#34;, &#34;</span>
</span></span><span style="display:flex;"><span> <span style="color:#e6db74">&#34;Phone: &#34;</span> <span style="color:#f92672">&lt;&lt;</span> person.phone();
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p><code>Person</code> objects can now be inserted into streams.</p>
<p>However, this implementation required three member functions to be called, which may be considered a source of inefficiency. An improvement would be reached by defining a member <code>Person::insertInto</code> and let <code>operator&lt;&lt;</code> call that function. These two functions could be defined as follows:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>std<span style="color:#f92672">::</span>ostream <span style="color:#f92672">&amp;</span><span style="color:#66d9ef">operator</span><span style="color:#f92672">&lt;&lt;</span>(std<span style="color:#f92672">::</span>ostream <span style="color:#f92672">&amp;</span>out, Person <span style="color:#66d9ef">const</span> <span style="color:#f92672">&amp;</span>person)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">return</span> person.insertInto(out);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>std<span style="color:#f92672">::</span>ostream <span style="color:#f92672">&amp;</span>Person<span style="color:#f92672">::</span>insertInto(std<span style="color:#f92672">::</span>ostream <span style="color:#f92672">&amp;</span>out)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">return</span>
</span></span><span style="display:flex;"><span> out <span style="color:#f92672">&lt;&lt;</span> <span style="color:#e6db74">&#34;Name: &#34;</span> <span style="color:#f92672">&lt;&lt;</span> d_name <span style="color:#f92672">&lt;&lt;</span> <span style="color:#e6db74">&#34;, &#34;</span>
</span></span><span style="display:flex;"><span> <span style="color:#e6db74">&#34;Address: &#34;</span> <span style="color:#f92672">&lt;&lt;</span> d_address <span style="color:#f92672">&lt;&lt;</span> <span style="color:#e6db74">&#34;, &#34;</span>
</span></span><span style="display:flex;"><span> <span style="color:#e6db74">&#34;Phone: &#34;</span> <span style="color:#f92672">&lt;&lt;</span> d_phone;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>As <code>insertInto</code> is a member function it has direct access to the object&rsquo;s data members so no additional member functions must be called when inserting <code>person</code> into <code>out</code>.</p>
<p>The next step consists of realizing that <code>insertInto</code> is only defined for the benefit of <code>operator&lt;&lt;</code>, and that <code>operator&lt;&lt;</code>, as it is declared in the header file containing <code>Person</code>&rsquo;s class interface should be considered a function belonging to the class <code>Person</code>. The member insertInto can therefore be omitted when <code>operator&lt;&lt;</code> is declared as a friend.</p>
<p><strong>Friend functions</strong> must be declared as friends in the class interface. These friend declarations are not member functions, and so they are independent of the class&rsquo;s <code>private</code>, <code>protected</code> and <code>public</code> sections. Friend declaration may be placed anywhere in the class interface. Convention dictates that friend declarations are listed directly at the top of the class interface. The class <code>Person</code>, using friend declaration for its extraction and insertion operators starts like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Person</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">friend</span> std<span style="color:#f92672">::</span>ostream <span style="color:#f92672">&amp;</span><span style="color:#66d9ef">operator</span><span style="color:#f92672">&lt;&lt;</span>(std<span style="color:#f92672">::</span>ostream <span style="color:#f92672">&amp;</span>out, Person <span style="color:#f92672">&amp;</span>pd);
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">friend</span> std<span style="color:#f92672">::</span>istream <span style="color:#f92672">&amp;</span><span style="color:#66d9ef">operator</span><span style="color:#f92672">&gt;&gt;</span>(std<span style="color:#f92672">::</span>istream <span style="color:#f92672">&amp;</span>in, Person <span style="color:#f92672">&amp;</span>pd);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#75715e">// previously shown interface (data and functions)
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>};
</span></span></code></pre></div><p>The insertion operator may now directly access a <code>Person</code> object&rsquo;s data members:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>std<span style="color:#f92672">::</span>ostream <span style="color:#f92672">&amp;</span><span style="color:#66d9ef">operator</span><span style="color:#f92672">&lt;&lt;</span>(std<span style="color:#f92672">::</span>ostream <span style="color:#f92672">&amp;</span>out, Person <span style="color:#66d9ef">const</span> <span style="color:#f92672">&amp;</span>person)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">return</span>
</span></span><span style="display:flex;"><span> cout <span style="color:#f92672">&lt;&lt;</span> <span style="color:#e6db74">&#34;Name: &#34;</span> <span style="color:#f92672">&lt;&lt;</span> person.d_name <span style="color:#f92672">&lt;&lt;</span> <span style="color:#e6db74">&#34;, &#34;</span>
</span></span><span style="display:flex;"><span> <span style="color:#e6db74">&#34;Address: &#34;</span> <span style="color:#f92672">&lt;&lt;</span> person.d_address <span style="color:#f92672">&lt;&lt;</span> <span style="color:#e6db74">&#34;, &#34;</span>
</span></span><span style="display:flex;"><span> <span style="color:#e6db74">&#34;Phone: &#34;</span> <span style="color:#f92672">&lt;&lt;</span> person.d_phone;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Friend declarations are true declarations. Once a class contains friend declarations these friend functions do not have to be declared again below the class&rsquo;s interface. This also clearly indicates the class designer&rsquo;s intent: the friend functions are declared by the class, and can thus be considered functions belonging to the class.</p>
<h2 id="152-extended-friend-declarations">
15.2: Extended friend declarations
<a class="anchor" href="#152-extended-friend-declarations">#</a>
</h2>
<p>C++ has added extended friend declarations to the language. When a class is declared as a friend, then the class keyword no longer has to be provided. E.g.,</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Friend</span>; <span style="color:#75715e">// declare a class
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">using</span> FriendClass <span style="color:#f92672">=</span> Friend; <span style="color:#75715e">// and maybe a using declaration
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Class1</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">friend</span> FriendClass; <span style="color:#75715e">// Friend: also OK
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>};
</span></span></code></pre></div><p>In the pre-C++11 standards the friend declaration required an explicit <code>class</code>; e.g., <code>friend class Friend</code>.</p>
<p>The explicit use of <code>class</code> remains required if the compiler hasn&rsquo;t seen the friend&rsquo;s name yet. E.g.,</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Class1</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span> <span style="color:#75715e">// friend Unseen; // fails to compile: Unseen unknown.
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> <span style="color:#66d9ef">friend</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Unseen</span>; <span style="color:#75715e">// OK
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>};
</span></span></code></pre></div><p>Section
<a href="/cpp/">22.10</a> covers the use of extended friend declarations in class templates.</p>
</article>
<footer class="book-footer">
<div class="flex flex-wrap justify-between">
</div>
<script>(function(){function e(e){const t=window.getSelection(),n=document.createRange();n.selectNodeContents(e),t.removeAllRanges(),t.addRange(n)}document.querySelectorAll("pre code").forEach(t=>{t.addEventListener("click",function(){if(window.getSelection().toString())return;e(t.parentElement),navigator.clipboard&&navigator.clipboard.writeText(t.parentElement.textContent)})})})()</script>
</footer>
<div class="book-comments">
</div>
<label for="menu-control" class="hidden book-menu-overlay"></label>
</div>
</main>
</body>
</html>