<?xml version="1.0"?>
<rss version="2.0"><channel><title>&#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;: &#x644;&#x63A;&#x629; C++</title><link>https://academy.hsoub.com/programming/cpp/page/3/?d=2</link><description>&#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;: &#x644;&#x63A;&#x629; C++</description><language>ar</language><item><title>&#x627;&#x644;&#x646;&#x648;&#x639; std::string: &#x627;&#x644;&#x633;&#x644;&#x627;&#x633;&#x644; &#x627;&#x644;&#x646;&#x635;&#x64A;&#x629; &#x641;&#x64A; Cpp</title><link>https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D9%86%D9%88%D8%B9-stdstring-%D8%A7%D9%84%D8%B3%D9%84%D8%A7%D8%B3%D9%84-%D8%A7%D9%84%D9%86%D8%B5%D9%8A%D8%A9-%D9%81%D9%8A-cpp-r940/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_06/28.jpg.af938e164c12f4cefdf9eabbc5af994f.jpg" /></p>
<p>
	النوع <code>std::string</code> والذي يدعى السلسلة النصية في العربية هو كائن يمثّل سلاسل من المحارف، ويوفر صنف <code>string</code> القياسي خيارًا بسيطًا وآمنًا ومتعدّد الاستخدامات لتخزين سلاسل المحارف ومعالجتها، وذلك موازنة <a data-ss1617022524="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-7-%D8%A7%D9%84%D9%85%D8%B5%D9%81%D9%88%D9%81%D8%A7%D8%AA-%D9%81%D9%8A-cpp-r891/" rel="">بمصفوفات</a> المحارف، و<code>‎string‎</code> هو جزء من فضاء الاسم <code>‎std‎</code>، وقد صار معياريًا في عام 1998.
</p>

<h2>
	تقطيع السلاسل النصية
</h2>

<p>
	يمكن تقطيع سلسلة نصيَّة إلى سلاسل نصيَّة أصغر تدعى الوحدات أو القطع (tokens)، تُسمّى هذه العمليَّة بالترميز المُقطَّع للسلاسل النصيَّة أو تقطيع السلاسل النصية (String Tokenization).
</p>

<p>
	ولدينا عدّة طرق لتقطيع سلسلة نصّية، وسنُدرجها من الأقل إلى الأكثر تكلفة في وقت التشغيل:
</p>

<ul>
	<li>
		<strong>الطريقة الأولى: <code>‎std::strtok‎</code> </strong>
	</li>
</ul>

<p>
	هي أقل طرق تقطيع السلاسل النصّية تكلفة، كما تسمح بتعديل الفاصل (delimiter) بين القطع (tokens)، غير أن هذه الطريقة تعتريها ثلاثة إشكاليات في C++‎:
</p>

<ul>
	<li>
		لا يمكن استخدام <code>‎std::strtok‎</code> على عدّة سلاسل نصّية في نفس الوقت (باستثناء بعض التطبيقات implementations التي تمكّن من ذلك، مثل: <code>‎strtok_s‎</code>)
	</li>
	<li>
		لا يمكن استخدام <code>‎std::strtok‎</code> على عدّة خيوط أو عمليات (threads) في وقت واحد (لكن قد يتغيّر ذلك بحسب التطبيق كما هو الحال في <a data-ss1617022524="1" href="https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/strtok-strtok-l-wcstok-wcstok-l-mbstok-mbstok-l?redirectedfrom=MSDN&amp;view=vs-2019#Anchor_3" rel="external nofollow">Visual Studio</a>)
	</li>
	<li>
		استدعاء <code>‎std::strtok‎</code> يُعدّل السلسلة النصية التي يعمل عليها، لذلك لا يمكن استخدامه على السلاسل النصّية من النوع <code>const strings</code> أو <code>‎‎const char*‎</code> أو السلاسل النصية المجردة، ويجب نسخ السلاسل النصّية المُدخلة لتقطيع أيٍّ من هذه السلاسل باستخدام <code>‎std::strtok‎</code> أو للعمل على السلاسل النصّية التي ينبغي حفظ محتوياتها، ثم يمكن العمل على النسخة بعد ذلك .
	</li>
</ul>

<div class="banner-container ipsBox ipsPadding">
	<div class="inner-banner-container">
		<p class="banner-heading">
			دورة تطوير التطبيقات باستخدام لغة Python
		</p>

		<p class="banner-subtitle">
			احترف تطوير التطبيقات مع أكاديمية حسوب والتحق بسوق العمل فور انتهائك من الدورة
		</p>

		<div>
			<a class="ipsButton ipsButton_large ipsButton_primary ipsButton_important" href="https://academy.hsoub.com/learn/python-application-development" rel="">اشترك الآن</a>
		</div>
	</div>

	<div class="banner-img">
		<img alt="دورة تطوير التطبيقات باستخدام لغة Python" src="https://academy.hsoub.com/learn/assets/images/courses/python-application-development.png">
	</div>
</div>

<p>
	ستكون تكلفة هذه الخيارات جزءًا من تكلفة حجز القطع، لكن إذا كنت تريد استخدام خوارزميات سريعة ولم تتمكن من تجاوز إشكاليات <code>‎std::strtok‎</code>، فربما عليك النظر في خيار <a data-ss1617022524="1" href="https://stackoverflow.com/questions/53849/how-do-i-tokenize-a-string-in-c/38595708#38595708" rel="external nofollow">hand-spun solution</a>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_8" style=""><span class="com">// السلسلة النصية المراد تقطيعها</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">string str </span><span class="pun">{</span><span class="pln">
    </span><span class="str">"The quick brown fox"</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="com">// المتجه الذي سنخزن فيه القطع.</span><span class="pln">
</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&gt;</span><span class="pln"> tokens</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> strtok</span><span class="pun">(</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> str</span><span class="pun">[</span><span class="lit">0</span><span class="pun">],</span><span class="pln"> </span><span class="str">" "</span><span class="pun">);</span><span class="pln"> i </span><span class="pun">!=</span><span class="pln"> NULL</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> strtok</span><span class="pun">(</span><span class="pln">NULL</span><span class="pun">,</span><span class="pln"> </span><span class="str">" "</span><span class="pun">))</span><span class="pln">
    tokens</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="pln">i</span><span class="pun">);</span></pre>

<p>
	<a data-ss1617022524="1" href="ideone.com/8kAGoa" rel="">انظر هذا المثال الحي</a>.
</p>

<ul>
	<li>
		<strong>الطريقة الثانية: <code>‎std::istream_iterator‎</code> </strong>
	</li>
</ul>

<p>
	يستخدم <code>std::istream_iterator‎</code> هنا عامل الاستخراج من <a data-ss1617022524="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-10-%D9%85%D8%AC%D8%A7%D8%B1%D9%8A-%D8%A7%D9%84%D8%AA%D8%AF%D9%81%D9%82-streams-%D9%88%D9%85%D8%B9%D8%A7%D9%84%D9%90%D8%AC%D8%A7%D8%AA%D9%87%D8%A7-%D9%81%D9%8A-cpp-r894/" rel="">المجرى</a> بشكل تكراري، وإذا كانت السلسلة النصّية المعطاة مفصولة بمسافات فارغة فسنستطيع التوسعة على المعامِل <code>‎std::strtok‎</code> بالتخلص من صعوباته، مما يسمح بالترميز المقطَّع المُضمَّن (inline)، ومن ثم دعم إنشاء متجهات السلاسل النصّية الثابتة (<code>‎const vector&lt;string&gt;‎</code>) ودعم محرف مسافات فاصلة متعددة، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_10" style=""><span class="com">// السلسلة النصية المراد تقطيعها</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string str</span><span class="pun">(</span><span class="str">"The  quick \tbrown \nfox"</span><span class="pun">);</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">istringstream is</span><span class="pun">(</span><span class="pln">str</span><span class="pun">);</span><span class="pln">
</span><span class="com">// المتجه الذي سنخزن فيه القطع.</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">vector</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">&gt;</span><span class="pln"> tokens </span><span class="pun">=</span><span class="pln">    std</span><span class="pun">::</span><span class="typ">vector</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">&gt;(</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">istream_iterator</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">&gt;(</span><span class="pln">is</span><span class="pun">),</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">istream_iterator</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">&gt;());</span></pre>

<p>
	<a data-ss1617022524="1" href="http://ideone.com/gWmfV9" rel="external nofollow">انظر هذا المثال الحي</a>.
</p>

<ul>
	<li>
		<strong>الطريقة الثالثة: <code>std::regex_token_iterator‎</code></strong>
	</li>
</ul>

<p>
	تَستخدم <code>‎std::regex_token_iterator‎</code> تعبيرًا نمطيًّا أو <code>‎std::regex‎</code> للقيام بعملية التقطيع بشكل تكراري، وهذا يسمح بتعريف الفاصل بشكل أكثر مرونة، مثل الفاصلات <code>,</code> والمسافات الفارغة، انظر:
</p>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_12" style=""><span class="com">// السلسلة النصية المُراد تقطيعها</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string str </span><span class="pun">{</span><span class="pln">
    </span><span class="str">"The ,qu\\,ick ,\tbrown, fox"</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">regex re </span><span class="pun">{</span><span class="pln">
    </span><span class="str">"\\s*((?:[^\\\\,]|\\\\.)*?)\\s*(?:,|$)"</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="com">// المتجه الذي سنخزن فيه القطع.</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&gt;</span><span class="pln"> tokens </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">sregex_token_iterator</span><span class="pun">(</span><span class="pln">str</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> str</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> re</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">),</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">sregex_token_iterator</span><span class="pun">()</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	<a data-ss1617022524="1" href="http://ideone.com/q58zoX" rel="external nofollow">انظر هذا المثال الحي</a>، وهذا مثال آخر في درس التعابير النمطية للمزيد من التفاصيل.
</p>

<h2>
	التحويل إلى مؤشر ‎ (const)‎ char*‎
</h2>

<p>
	استخدم الدالة التابعة <code>‎c_str()‎</code> لتمكين مؤشّر <code>‎const char*‎</code> من الوصول إلى بيانات سلسلة نصّية، واعلم أنّ المؤشّر يبقى صالحًا ما دامت السلسلة النصّية ضمن النطاق (scope) ولم يمسّها تغيير، هذا يعني أنه لا يمكن استدعاء توابع غير ثابتة على الكائن.
</p>

<p>
	<strong>الإصدار ≥ C++‎ 17</strong>
</p>

<p>
	استخدم الدالة التابعة <code>‎data()‎</code> للحصول على مؤشّر قابل للتغيير <code>‎char*‎</code>، والذي يمكن استخدامه لمعالجة السلسلة النصّية.
</p>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	ويمكن الحصول على مؤشّر <code>‎char*‎</code> قابل للتعديل عن طريق أخذ عنوان الحرف الأول: <code>‎&amp;s[0‎]‎</code>، سيُعيد ذلك في C++‎ 11 سلسلةً نصّية مُنسّقة جيدًا ومنتهية بالمحرف الفارغ (null-terminated). لاحظ أنّ <code>‎&amp;s[0‎]‎</code> ستكون مُنسّقة حتى لو كانت <code>s</code> فارغة، بينما تكون <code>‎&amp;s.front()‎</code> غير مُحدّدة إن كانت <code>‎s‎</code> فارغة.
</p>

<p>
	<strong>الإصدار ≥ C++‎ 17</strong> في المثال التالي، تشير كل من <code>cstr</code> و <code>data</code> إلى <code>"This is a string.\0"</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_14" style=""><span class="pln">std</span><span class="pun">::</span><span class="pln">string str</span><span class="pun">(</span><span class="str">"This is a string."</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">*</span><span class="pln"> cstr </span><span class="pun">=</span><span class="pln"> str</span><span class="pun">.</span><span class="pln">c_str</span><span class="pun">();</span><span class="pln"> 
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">*</span><span class="pln"> data </span><span class="pun">=</span><span class="pln"> str</span><span class="pun">.</span><span class="pln">data</span><span class="pun">();</span><span class="pln"> 
std</span><span class="pun">::</span><span class="pln">string str</span><span class="pun">(</span><span class="str">"This is a string."</span><span class="pun">);</span></pre>

<p>
	انسخ محتويات <code>str</code> لفك <code>lifetime</code> من كائن <code>std::string</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_16" style=""><span class="pln">std</span><span class="pun">::</span><span class="pln">unique_ptr</span><span class="pun">&lt;</span><span class="kwd">char</span><span class="pln"> </span><span class="pun">[]&gt;</span><span class="pln"> cstr </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">make_unique</span><span class="pun">&lt;</span><span class="kwd">char</span><span class="pun">[]&gt;(</span><span class="pln">str</span><span class="pun">.</span><span class="pln">size</span><span class="pun">()</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span></pre>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_18" style=""><span class="com">// حل بديل للسطر أعلاه، غير محصن من الاعتراضات.</span><span class="pln">
</span><span class="com">// char* cstr_unsafe = new char[str.size() + 1];</span><span class="pln">

std</span><span class="pun">::</span><span class="pln">copy</span><span class="pun">(</span><span class="pln">str</span><span class="pun">.</span><span class="pln">data</span><span class="pun">(),</span><span class="pln"> str</span><span class="pun">.</span><span class="pln">data</span><span class="pun">()</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">.</span><span class="pln">size</span><span class="pun">(),</span><span class="pln"> cstr</span><span class="pun">);</span><span class="pln">
cstr</span><span class="pun">[</span><span class="pln">str</span><span class="pun">.</span><span class="pln">size</span><span class="pun">()]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">'\0'</span><span class="pun">;</span><span class="pln">        </span><span class="com">//  ينبغي إضافة سلسلة نصّية منتهية بحرف فارغ</span><span class="pln">

</span><span class="com">// delete[] cstr_unsafe;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> cstr</span><span class="pun">.</span><span class="pln">get</span><span class="pun">();</span></pre>

<h2>
	استخدام الصنف <code>std::string_view</code>
</h2>

<p>
	<strong>الإصدار ≥ C++‎ 17</strong>
</p>

<p>
	قدّمت C++‎ 17 الصنف <code>‎std::string_view‎</code>، وهو ببساطة مدىً غير مالك (non-owning range) من المحارف الثابتة (<code>‎const char‎</code>)، والقابلة للتنفيذ إمّا على هيئة زوج من المؤشّرات، أو مؤشّر وطول (length)، وهو نوع معاملات أفضل للدوالّ التي تتطلب سلاسل نصّية غير قابلة للتعديل.
</p>

<p>
	وكان قبل الإصدار C++‎ 17 ثلاثة خيارات لفعل هذا: الأول: وسيط واحد، قد يقوم بالتخصيص إن لم تكن بيانات المستدعي في سلسلة نصية مثل سلسلة نصية مجردة أو <code>&lt;vector&lt;char</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_20" style=""><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string </span><span class="kwd">const</span><span class="pun">&amp;</span><span class="pln"> s</span><span class="pun">);</span></pre>

<p>
	الثاني: وسيطان، يجب أن يمررهما في كل مكان.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_22" style=""><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">*</span><span class="pln"> s</span><span class="pun">,</span><span class="pln"> </span><span class="typ">size_t</span><span class="pln"> len</span><span class="pun">);</span></pre>

<p>
	والثالث: وسيط واحد، لكن يجب أن يستدعي <code>()strlen</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_24" style=""><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">*</span><span class="pln"> s</span><span class="pun">);</span></pre>

<p>
	يستطيع المستدعي تمرير مزود بيانات محرفية لكن سيكون على <code>()foo</code> أن يتواجد في ترويسة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_26" style=""><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">StringT</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">(</span><span class="typ">StringT</span><span class="pln"> </span><span class="kwd">const</span><span class="pun">&amp;</span><span class="pln"> s</span><span class="pun">);</span></pre>

<p>
	يمكن استبدال كلّ ما في المثال السابق بالشيفرة التالية، ومزاياها أنها بوسيط واحد، مع ربط أقوى، وبدون نُسخ بغض النظر عن كيفية تخزين المستدعي للبيانات.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_28" style=""><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string_view s</span><span class="pun">);</span></pre>

<p>
	لاحظ أنّ <code>std::string_view</code> <strong>لا يمكنها</strong> تعديل البيانات الأساسية (underlying data) الخاصّة بها.
</p>

<p>
	<code>‎string_view‎</code> مفيدة في حال أردت تجنّب عمليات النسخ غير الضرورية، كما تقدم مجموعة من وظائف السلاسل النصّية، رغم أنّ سلوك بعض الدوالّ قد يختلف، انظر المثال التالي لسلسلة نصية طويلة بدون داعي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_30" style=""><span class="pln">std</span><span class="pun">::</span><span class="pln">string str </span><span class="pun">=</span><span class="pln"> </span><span class="str">"lllloooonnnngggg sssstttrrriiinnnggg"</span><span class="pun">;</span><span class="pln"> </span><span class="com">// سلسلة نصّية طويلة</span></pre>

<p>
	استخدام <code>string::subsr</code> سيعيد سلسلة نصية جديدة، وهذا مكلف إن كانت السلسلة طويلة، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_32" style=""><span class="pln">std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> str</span><span class="pun">.</span><span class="pln">substr</span><span class="pun">(</span><span class="lit">15</span><span class="pun">,</span><span class="pln"> </span><span class="lit">10</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span></pre>

<p>
	وعليه فلا نحبذ هذا الأسلوب، ومن ناحية أخرى فلن تنشئ الطريقة الصحيحة هنا أي نسخ إضافية، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_34" style=""><span class="pln">std</span><span class="pun">::</span><span class="pln">string_view view </span><span class="pun">=</span><span class="pln"> str</span><span class="pun">;</span></pre>

<p>
	وستعيد <code>string_view::substr</code> سلسلة <code>string_view</code> جديدة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_36" style=""><span class="pln">std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> view</span><span class="pun">.</span><span class="pln">substr</span><span class="pun">(</span><span class="lit">15</span><span class="pun">,</span><span class="pln"> </span><span class="lit">10</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span></pre>

<h2>
	التحويل إلى <code>std::wstring</code>
</h2>

<p>
	تُمثَّل تسلسلات المحارف في C++‎ عبر تخصيص الصنف <code>‎std::basic_string‎</code> بنوع محرفي أصلي (native)، والمجموعتان الرئيسيتان المُعرّفتان في المكتبة القياسية هما <code>‎std::string‎</code> و <code>‎std::wstring‎</code>:
</p>

<ul>
	<li>
		<code>‎std::string‎</code> هي سلسلة مبنية بعناصر من نوع <code>char</code>
	</li>
	<li>
		<code>‎std::wstring‎</code> مبنية بعناصر من نوع <code>wchar_t</code>
	</li>
</ul>

<p>
	استخدم لأجل التحويل بين النوعين، <code>‎wstring_convert‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_38" style=""><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;string&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;codecvt&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;locale&gt;</span><span class="pln">

std</span><span class="pun">::</span><span class="pln">string input_str </span><span class="pun">=</span><span class="pln"> </span><span class="str">"this is a -string-, which is a sequence based on the -char- type."</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">wstring input_wstr </span><span class="pun">=</span><span class="pln"> L</span><span class="str">"this is a -wide- string, which is based on the -wchar_t- type."</span><span class="pun">;</span><span class="pln">
</span><span class="com">// التحويل</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">wstring str_turned_to_wstr </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">wstring_convert</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">codecvt_utf8</span><span class="str">&lt;wchar_t&gt;</span><span class="pun">&gt;().</span><span class="pln">from_bytes</span><span class="pun">(</span><span class="pln">input_str</span><span class="pun">);</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">string wstr_turned_to_str </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">wstring_convert</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">codecvt_utf8</span><span class="str">&lt;wchar_t&gt;</span><span class="pun">&gt;().</span><span class="pln">to_bytes</span><span class="pun">(</span><span class="pln">input_wstr</span><span class="pun">);</span></pre>

<p>
	لتحسين قابلية الاستخدام وسهولة القراءة، عرِّف دوالًا لتنفيذ عملية التحويل:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_40" style=""><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;string&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;codecvt&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;locale&gt;</span><span class="pln">

</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">convert_t</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">codecvt_utf8 </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">wchar_t</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">wstring_convert </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">convert_t</span><span class="pun">,</span><span class="pln"> </span><span class="typ">wchar_t</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> strconverter</span><span class="pun">;</span><span class="pln">

std</span><span class="pun">::</span><span class="pln">string to_string</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">wstring wstr</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> strconverter</span><span class="pun">.</span><span class="pln">to_bytes</span><span class="pun">(</span><span class="pln">wstr</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

std</span><span class="pun">::</span><span class="pln">wstring to_wstring</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string str</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> strconverter</span><span class="pun">.</span><span class="pln">from_bytes</span><span class="pun">(</span><span class="pln">str</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	مثال تطبيقي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_42" style=""><span class="pln">std</span><span class="pun">::</span><span class="pln">wstring a_wide_string </span><span class="pun">=</span><span class="pln"> to_wstring</span><span class="pun">(</span><span class="str">"Hello World!"</span><span class="pun">);</span></pre>

<p>
	هذا أفضل وأوضح بكثير من السطر التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_44" style=""><span class="pln">td</span><span class="pun">::</span><span class="pln">wstring_convert</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">codecvt_utf8</span><span class="str">&lt;wchar_t&gt;</span><span class="pun">&gt;().</span><span class="pln">from_bytes</span><span class="pun">(</span><span class="str">"HelloWorld!"</span><span class="pun">)‎‎‎</span></pre>

<p>
	لاحظ أنّ <code>‎char‎</code> و <code>‎wchar_t‎</code> لا تقتضيان الترميز (encoding) ولا تُعطيان أيّ إشارة عن الحجم بالبايتات، على سبيل المثال، تُستخدم <code>‎wchar_t‎</code> عادة كنوع بيانات ثنائي البايت، وعادة ما تحتوي على بيانات مُرمّزة بترميز UTF-16 في ويندوز (أو UCS-2 في الإصدارات السابقة لنظام ويندوز 2000) أو كنوع بيانات رباعي البايت مُرمّز باستخدام الترميز UTF-32 في لينكس.
</p>

<p>
	هذا على النقيض من الأنواع الحديثة <code>‎char16_t‎</code> و <code>‎char32_t‎</code>، والتي جاءت في الإصدار C++‎ 11، إذ هي كبيرة بما يكفي لاحتواء أيّ محرف من UTF16 أو UTF32 على الترتيب.
</p>

<h2>
	الموازنة المعجمية
</h2>

<p>
	يمكن موازنة سلسلتين نصّيتين معجميًا باستخدام المعاملات <code>‎==‎</code> و <code>‎!=‎</code> و <code>‎&lt;‎</code> و <code>‎&lt;=‎</code> و <code>‎&gt;‎</code> و <code>‎&gt;=‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_46" style=""><span class="pln">std</span><span class="pun">::</span><span class="pln">string str1 </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Foo"</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">string str2 </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Bar"</span><span class="pun">;</span><span class="pln">

assert</span><span class="pun">(!(</span><span class="pln">str1 </span><span class="pun">&lt;</span><span class="pln"> str2</span><span class="pun">));</span><span class="pln">
assert</span><span class="pun">(</span><span class="pln">str </span><span class="pun">&gt;</span><span class="pln"> str2</span><span class="pun">);</span><span class="pln">
assert</span><span class="pun">(!(</span><span class="pln">str1 </span><span class="pun">&lt;=</span><span class="pln"> str2</span><span class="pun">));</span><span class="pln">
assert</span><span class="pun">(</span><span class="pln">str1 </span><span class="pun">&gt;=</span><span class="pln"> str2</span><span class="pun">);</span><span class="pln">
assert</span><span class="pun">(!(</span><span class="pln">str1 </span><span class="pun">==</span><span class="pln"> str2</span><span class="pun">));</span><span class="pln">
assert</span><span class="pun">(</span><span class="pln">str1 </span><span class="pun">!=</span><span class="pln"> str2</span><span class="pun">);</span></pre>

<p>
	تستخدِم كل هذه الدوالّ التابع <code>‎std::string::compare()‎</code> لإجراء المقارنات وإعادة القيمة البوليانية المناسبة.
</p>

<p>
	وفيما يلي شرح عامّ لمعَاملات الموازنة:
</p>

<ul>
	<li>
		<strong>المُعامل <code>‎==‎</code></strong>
	</li>
</ul>

<p>
	إذا كانت <code>‎str1.length() == str2.length()‎</code>، وتطابقت أزواج المحارف (character pairs)، فسيعيد المُعاملُ القيمةَ <code>‎true‎</code>، وإلا فسَيعيد <code>‎false‎</code>.
</p>

<ul>
	<li>
		<strong>المُعامل <code>‎!=‎</code></strong>
	</li>
</ul>

<p>
	إذا كانت <code>‎str1.length() != str2.length()‎</code> أو لم تتطابق أزواج المحارف، فسَيعيد المُعامل القيمة <code>‎true‎</code>، وإلا فسيعيد <code>‎false‎</code>.
</p>

<ul>
	<li>
		<strong>المُعامل <code>‎&lt;‎</code> أو المُعامل <code>‎&gt;‎</code></strong>
	</li>
</ul>

<p>
	 يبحثان عن أول زوج غير متطابق من المحارف، ويقارن بينهما ثم يعيد النتيجة البوليانية تبعًا لنتيجَة الموازنة.
</p>

<ul>
	<li>
		<strong>المُعامل <code>‎&lt;=‎</code> أو المُعامل <code>‎&gt;=‎</code></strong>
	</li>
</ul>

<p>
	 يبحث عن أول زوج غير متطابق من المحارف، ويقارن بينهما ثم يعيد النتيجة البوليانية.
</p>

<p>
	<strong>ملاحظة</strong>: يشير مصطلح زوج المحارف (character pair) إلى المحارف المتقابلة في كلا السلسلتين، أي الحرفين الذين يوجَدين في نفس الموضع من السلسلتين النّصّيتين. مثلًا، لنفترض أنّ لدينا سلسلتين نصّيتين <code>‎str1‎</code> و <code>‎str2‎</code>، وطولاهما <code>‎n‎</code> و <code>‎m‎</code> على التوالي، في هذه الحالة ستكون أزواج المحارف في كلتَي السلسلتين النصّيتين هي الأزواج <code>‎str1‎</code> و <code>‎str2‎</code> حيث i = 0, 1, 2, …, max(n,m)‎. في حال عدم وجود حرف يقابل الفهرس i، أي عندما يكون i أكبر من أو يساوي <code>‎n‎</code> أو <code>‎m‎</code>، فسيتم اعتبارُه القيمةَ الأصغر.
</p>

<p>
	فيما يلي مثال على استخدام <code>‎&lt;‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_48" style=""><span class="pln">std</span><span class="pun">::</span><span class="pln">string str1 </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Barr"</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">string str2 </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Bar"</span><span class="pun">;</span><span class="pln">

assert</span><span class="pun">(</span><span class="pln">str2 </span><span class="pun">&lt;</span><span class="pln"> str1</span><span class="pun">);</span></pre>

<p>
	خطوات الموازنة هي كالتالي:
</p>

<ol>
	<li>
		موازنة الحرفين الأوّلين، <code>‎'B' == 'B'‎</code> - ثم متابعة.
	</li>
	<li>
		موازنة بين الحرفين الثانيين، <code>‎'a' == 'a'‎</code> - ثم متابعة.
	</li>
	<li>
		موازنة بين الحرفين الثّالثين، <code>‎'r' == 'r'‎</code> - ثم متابعة.
	</li>
	<li>
		استُنفِذ نطاق <code>‎str2‎</code> الآن، في حين أنّ نطاق <code>‎str1‎</code> ما يزال فيه محارف زائدة. وبالتالي يكون لدينا: <code>‎str2 &lt; str1‎</code>.
	</li>
</ol>

<h2>
	تقليم المحارف في بداية أو نهاية السلسلة النصية
</h2>

<p>
	يتطلب هذا المثال الترويسات <algorithm> و <locale> و <utility>. </utility></locale></algorithm>
</p>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	تقليم (trim) تسلسل أو سلسلة نصّية يعني إزالة جميع العناصر الأولى أو الأخيرة التي تحقق شرطًا معينًا، ونقلّم أولًا العناصر الأخيرة لأنها لا تتطلب تحريك أيّ عنصر، ثم نقلّم العناصر الأولى.
</p>

<p>
	لاحظ أنّ التعميمات أدناه تعمل مع جميع أنواع السلاسل النصّية الأساسية <code>‎std::basic_string‎</code>، مثل <code>‎std::string‎</code> و <code>‎std::wstring‎</code>، وأيضًا على الحاويات مثل <code>‎std::vector‎</code> و <code>‎std::list‎</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_50" style=""><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">Sequence</span><span class="pun">,</span><span class="pln"> </span><span class="com">// list أو  vector أي سلسلة نصّية أساسية، مثل     </span><span class="pln">
    </span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">Pred</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="com">// شرط</span><span class="pln">
    </span><span class="typ">Sequence</span><span class="pun">&amp;</span><span class="pln"> trim</span><span class="pun">(</span><span class="typ">Sequence</span><span class="pun">&amp;</span><span class="pln"> seq</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Pred</span><span class="pln"> pred</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> trim_start</span><span class="pun">(</span><span class="pln">trim_end</span><span class="pun">(</span><span class="pln">seq</span><span class="pun">,</span><span class="pln"> pred</span><span class="pun">),</span><span class="pln"> pred</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span></pre>

<p>
	يعتمد تقليم العناصر الأخيرة على إيجاد العنصر الأخير غير المطابق للشّرط، وبدء عملية المحو من هناك:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_52" style=""><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">Sequence</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">Pred</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="typ">Sequence</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> trim_end</span><span class="pun">(</span><span class="typ">Sequence</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> seq</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Pred</span><span class="pln"> pred</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">auto</span><span class="pln"> last </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">find_if_not</span><span class="pun">(</span><span class="pln">seq</span><span class="pun">.</span><span class="pln">rbegin</span><span class="pun">(),</span><span class="pln">
            seq</span><span class="pun">.</span><span class="pln">rend</span><span class="pun">(),</span><span class="pln">
            pred</span><span class="pun">);</span><span class="pln">
        seq</span><span class="pun">.</span><span class="pln">erase</span><span class="pun">(</span><span class="pln">last</span><span class="pun">.</span><span class="pln">base</span><span class="pun">(),</span><span class="pln"> seq</span><span class="pun">.</span><span class="pln">end</span><span class="pun">());</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> seq</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span></pre>

<p>
	أمّا تقليم العناصر الأولية، فيعتمد على تحديد العنصر الأوّل الذي لا يحقّق الشرط وبدء عملية المحو من بداية السلسلة وحتى هناك:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_54" style=""><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">Sequence</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">Pred</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="typ">Sequence</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> trim_start</span><span class="pun">(</span><span class="typ">Sequence</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> seq</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Pred</span><span class="pln"> pred</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">auto</span><span class="pln"> first </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">find_if_not</span><span class="pun">(</span><span class="pln">seq</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln">
            seq</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln">
            pred</span><span class="pun">);</span><span class="pln">
        seq</span><span class="pun">.</span><span class="pln">erase</span><span class="pun">(</span><span class="pln">seq</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> first</span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> seq</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span></pre>

<p>
	استخدم الدالّة <code>‎std::isspace()‎</code> كشرط إذا أردت تقليم المسافات الفارغة في سلسلة نصّية :
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_56" style=""><span class="pln">std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">&amp;</span><span class="pln"> trim</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">&amp;</span><span class="pln"> str</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">locale</span><span class="pun">&amp;</span><span class="pln"> loc </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">locale</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> trim</span><span class="pun">(</span><span class="pln">str</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[&amp;</span><span class="pln">loc</span><span class="pun">](</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> c</span><span class="pun">){</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">isspace</span><span class="pun">(</span><span class="pln">c</span><span class="pun">,</span><span class="pln"> loc</span><span class="pun">);</span><span class="pln"> </span><span class="pun">});</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">&amp;</span><span class="pln"> trim_start</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">&amp;</span><span class="pln"> str</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">locale</span><span class="pun">&amp;</span><span class="pln"> loc </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">locale</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> trim_start</span><span class="pun">(</span><span class="pln">str</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[&amp;</span><span class="pln">loc</span><span class="pun">](</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> c</span><span class="pun">){</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">isspace</span><span class="pun">(</span><span class="pln">c</span><span class="pun">,</span><span class="pln"> loc</span><span class="pun">);</span><span class="pln"> </span><span class="pun">});</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">&amp;</span><span class="pln"> trim_end</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">&amp;</span><span class="pln"> str</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">locale</span><span class="pun">&amp;</span><span class="pln"> loc </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">locale</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> trim_end</span><span class="pun">(</span><span class="pln">str</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[&amp;</span><span class="pln">loc</span><span class="pun">](</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> c</span><span class="pun">){</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">isspace</span><span class="pun">(</span><span class="pln">c</span><span class="pun">,</span><span class="pln"> loc</span><span class="pun">);</span><span class="pln"> </span><span class="pun">});</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	وبالمثل، يمكننا استخدام الدالّة <code>‎std::iswspace()‎</code> مع السلاسل النصّية <code>‎std::wstring‎</code>.
</p>

<p>
	إذا كنت ترغب في إنشاء تسلسل جديد عبر إنشاء نسخة مُقلَّمة، فيمكنك استخدام دالّة منفصلة على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_58" style=""><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">Sequence</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">Pred</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="typ">Sequence</span><span class="pln"> trim_copy</span><span class="pun">(</span><span class="typ">Sequence</span><span class="pln"> seq</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Pred</span><span class="pln"> pred</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">// بالقيمة seq  تمرير</span><span class="pln">
        trim</span><span class="pun">(</span><span class="pln">seq</span><span class="pun">,</span><span class="pln"> pred</span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> seq</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span></pre>

<h2>
	استبدال السلاسل الصّية
</h2>

<h3>
	الاستبدال بالموضع
</h3>

<p>
	استخدم التابع <code>‎replace‎</code> الخاص بالصنف <code>‎std::string‎</code> لاستبدال جزء من سلسلة نصّية. أيضًا، التابع <code>‎replace‎</code> له الكثير من <a data-ss1617022524="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-22-%D8%A7%D9%84%D8%AA%D8%AD%D9%85%D9%8A%D9%84-%D8%A7%D9%84%D8%B2%D8%A7%D8%A6%D8%AF-overloading-%D8%AA%D8%AD%D9%84%D9%8A%D9%84%D9%87-%D9%88%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D9%87-%D8%B9%D9%84%D9%89-%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-%D9%81%D9%8A-cpp-r934/" rel="">التحميلات الزائدة</a> (overloads) المفيدة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_60" style=""><span class="com">// عرِّف سلسلة نصّية</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">string str </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Hello foo, bar and world!"</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">string alternate </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Hello foobar"</span><span class="pun">;</span><span class="pln">

</span><span class="com">//1)</span><span class="pln">
str</span><span class="pun">.</span><span class="pln">replace</span><span class="pun">(</span><span class="lit">6</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="str">"bar"</span><span class="pun">);</span><span class="pln"> </span><span class="com">//"Hello bar, bar and world!"</span><span class="pln">

</span><span class="com">//2)</span><span class="pln">
str</span><span class="pun">.</span><span class="pln">replace</span><span class="pun">(</span><span class="pln">str</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">()</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">6</span><span class="pun">,</span><span class="pln"> str</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> </span><span class="str">"nobody!"</span><span class="pun">);</span><span class="pln"> </span><span class="com">//"Hello nobody!"</span><span class="pln">

</span><span class="com">//3)</span><span class="pln">
str</span><span class="pun">.</span><span class="pln">replace</span><span class="pun">(</span><span class="lit">19</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">,</span><span class="pln"> alternate</span><span class="pun">,</span><span class="pln"> </span><span class="lit">6</span><span class="pun">,</span><span class="pln"> </span><span class="lit">6</span><span class="pun">);</span><span class="pln"> </span><span class="com">//"Hello foo, bar and foobar!"</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 14</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_62" style=""><span class="com">//4)</span><span class="pln">
str</span><span class="pun">.</span><span class="pln">replace</span><span class="pun">(</span><span class="lit">19</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">,</span><span class="pln"> alternate</span><span class="pun">,</span><span class="pln"> </span><span class="lit">6</span><span class="pun">);</span><span class="pln"> </span><span class="com">//"Hello foo, bar and foobar!"</span><span class="pln">

</span><span class="com">//5)</span><span class="pln">
str</span><span class="pun">.</span><span class="pln">replace</span><span class="pun">(</span><span class="pln">str</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> str</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">()</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">5</span><span class="pun">,</span><span class="pln"> str</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">()</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">6</span><span class="pun">,</span><span class="pln"> str</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">()</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">9</span><span class="pun">);</span><span class="pln">
</span><span class="com">//"foo foo, bar and world!"</span><span class="pln">

</span><span class="com">//6)</span><span class="pln">
str</span><span class="pun">.</span><span class="pln">replace</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="str">'z'</span><span class="pun">);</span><span class="pln"> </span><span class="com">//"zzz foo, bar and world!"</span><span class="pln">

</span><span class="com">//7)</span><span class="pln">
str</span><span class="pun">.</span><span class="pln">replace</span><span class="pun">(</span><span class="pln">str</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">()</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">6</span><span class="pun">,</span><span class="pln"> str</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">()</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">9</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="str">'x'</span><span class="pun">);</span><span class="pln"> </span><span class="com">//"Hello xxx, bar and world!"</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_64" style=""><span class="com">//8)</span><span class="pln">
str</span><span class="pun">.</span><span class="pln">replace</span><span class="pun">(</span><span class="pln">str</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> str</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">()</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="str">'x'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'y'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'z'</span><span class="pln"> </span><span class="pun">});</span><span class="pln"> </span><span class="com">//"xyz foo, bar and world!"</span></pre>

<h3>
	استبدال سلسلة نصّية بأخرى
</h3>

<p>
	استبدل بالظهور الأول فقط للسلسلة النصّية <code>‎with‎</code> السلسلة <code>‎replace‎</code> في <code>‎str‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_66" style=""><span class="pln">std</span><span class="pun">::</span><span class="pln">string replaceString</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string str</span><span class="pun">,</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">&amp;</span><span class="pln"> replace</span><span class="pun">,</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">&amp;</span><span class="pln"> with</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> pos </span><span class="pun">=</span><span class="pln"> str</span><span class="pun">.</span><span class="pln">find</span><span class="pun">(</span><span class="pln">replace</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">pos </span><span class="pun">!=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">::</span><span class="pln">npos</span><span class="pun">)</span><span class="pln">
        str</span><span class="pun">.</span><span class="pln">replace</span><span class="pun">(</span><span class="pln">pos</span><span class="pun">,</span><span class="pln"> replace</span><span class="pun">.</span><span class="pln">length</span><span class="pun">(),</span><span class="pln"> with</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> str</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	استبدال السّلسلة النصّية <code>‎with‎</code> بالسلسلة <code>‎replace‎</code> أينما ظهرت في <code>‎str‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_68" style=""><span class="pln">std</span><span class="pun">::</span><span class="pln">string replaceStringAll</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string str</span><span class="pun">,</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">&amp;</span><span class="pln"> replace</span><span class="pun">,</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">&amp;</span><span class="pln"> with</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">replace</span><span class="pun">.</span><span class="pln">empty</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> pos </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">((</span><span class="pln">pos </span><span class="pun">=</span><span class="pln"> str</span><span class="pun">.</span><span class="pln">find</span><span class="pun">(</span><span class="pln">replace</span><span class="pun">,</span><span class="pln"> pos</span><span class="pun">))</span><span class="pln"> </span><span class="pun">!=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">::</span><span class="pln">npos</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            str</span><span class="pun">.</span><span class="pln">replace</span><span class="pun">(</span><span class="pln">pos</span><span class="pun">,</span><span class="pln"> replace</span><span class="pun">.</span><span class="pln">length</span><span class="pun">(),</span><span class="pln"> with</span><span class="pun">);</span><span class="pln">
            pos </span><span class="pun">+=</span><span class="pln"> with</span><span class="pun">.</span><span class="pln">length</span><span class="pun">();</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> str</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	التحويل إلى سلسلة نصية
</h2>

<p>
	استخدم <code><a data-ss1617022524="1" href="https://en.cppreference.com/w/cpp/io/basic_ostringstream" rel="external nofollow">std::ostringstream</a></code> لتحويل أيّ نوع قابل للإجراء (streamable type) إلى تمثيله النصي -أي إلى سلسلة نصّية-، عن طريق إدراج الكائن المُراد تحويله في كائن <code>‎std::ostringstream‎</code> (عبر معامل إدراج المجرى <code>‎&lt;&lt;‎</code>)، ثم تحويل <code>‎std::ostringstream‎</code> بأكملها إلى سلسلة نصّية.
</p>

<p>
	مثلًا، بالنسبة للأعداد الصحيحة <code>‎int‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_70" style=""><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;sstream&gt;</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> val </span><span class="pun">=</span><span class="pln"> </span><span class="lit">4</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">ostringstream str</span><span class="pun">;</span><span class="pln">
    str </span><span class="pun">&lt;&lt;</span><span class="pln"> val</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">string converted </span><span class="pun">=</span><span class="pln"> str</span><span class="pun">.</span><span class="pln">str</span><span class="pun">();</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	اكتب دالّة التحويل الخاصة بك:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_73" style=""><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">string toString</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> T </span><span class="pun">&amp;</span><span class="pln"> x</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">ostringstream ss</span><span class="pun">;</span><span class="pln">
        ss </span><span class="pun">&lt;&lt;</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> ss</span><span class="pun">.</span><span class="pln">str</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span></pre>

<p>
	هذه الدالّة ستعمل بنجاح، لكنّ أداءها أقلّ كفاءة. يمكن أن تنفذ الأصناف المُعرَّفة من قبل المستخدم عاملَ إدراج المجرى، انظر المثال التالي حيث نكتب تمثيلًا نصيًا ل <code>a</code> في <code>out</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_75" style=""><span class="pln">std</span><span class="pun">::</span><span class="pln">ostream </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">ostream </span><span class="pun">&amp;</span><span class="pln"> out</span><span class="pun">,</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> A </span><span class="pun">&amp;</span><span class="pln"> a</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> out</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	بصرف النظر عن مجاري التدفق، أصبح ممكنًا منذ الإصدار C++‎ 11 أن نستخدم الدالّة <code>‎std::to_string‎</code> (و <code>‎std::to_wstring‎</code>) والتي حُمِّلت تحميلًا زائدًا في جميع الأنواع الأساسية، وصارت تعيد تمثيلًا نصيًّا للمعامل المُمرّر إليها.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_77" style=""><span class="pln">std</span><span class="pun">::</span><span class="pln">string s </span><span class="pun">=</span><span class="pln"> to_string</span><span class="pun">(</span><span class="lit">0x12f3</span><span class="pun">);</span><span class="pln"> </span><span class="com">// "4851" القيمة s بعد هذا ستحتوي</span></pre>

<h2>
	التقسيم (Splitting)
</h2>

<p>
	استخدم <code><a data-ss1617022524="1" href="https://en.cppreference.com/w/cpp/string/basic_string/substr" rel="external nofollow">‎std::string::substr‎</a></code> لتقسِيم السلاسل النصّية. هناك نوعان من هذا التابع، يأخذ الأول موضع البداية، والذي ستبدأ منه السلسلة النصّية الفرعية (substring) المُعادة. يجب أن يكون موضع البداية جزءًا من النطاق <code>(0, str.length()]‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_79" style=""><span class="pln">std</span><span class="pun">::</span><span class="pln">string str </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Hello foo, bar and world!"</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">string newstr </span><span class="pun">=</span><span class="pln"> str</span><span class="pun">.</span><span class="pln">substr</span><span class="pun">(</span><span class="lit">11</span><span class="pun">);</span><span class="pln"> </span><span class="com">// "bar and world!"</span></pre>

<p>
	فيما يأخذ التابع الثاني موضع البداية والطول الإجمالي للسّلسلة النصّية الفرعية الجديدة. ولن تتجاوز السلسلة النصّية الفرعية نهاية السلسلة النصّية المصدرية مهما كان الطول المُمرَّر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_82" style=""><span class="pln">std</span><span class="pun">::</span><span class="pln">string str </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Hello foo, bar and world!"</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">string newstr </span><span class="pun">=</span><span class="pln"> str</span><span class="pun">.</span><span class="pln">substr</span><span class="pun">(</span><span class="lit">15</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">);</span><span class="pln"> </span><span class="com">// "and"</span></pre>

<p>
	لاحظ أنّك تستطيع استدعاء <code>‎substr‎</code> بدون أي وسائط، وفي هذه الحالة ستُعاد نسخة مضبوطة من السلسلة النصية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_84" style=""><span class="pln">std</span><span class="pun">::</span><span class="pln">string str </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Hello foo, bar and world!"</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">string newstr </span><span class="pun">=</span><span class="pln"> str</span><span class="pun">.</span><span class="pln">substr</span><span class="pun">();</span><span class="pln"> </span><span class="com">// "Hello foo, bar and world!"</span></pre>

<h2>
	الوصول إلى محرف من السلسلة النصية
</h2>

<p>
	هناك عدة طرق لاستِخراج الحروف من السلاسل النصّية، ولكلّ منها خصوصياتها.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_86" style=""><span class="pln">std</span><span class="pun">::</span><span class="pln">string str</span><span class="pun">(</span><span class="str">"Hello world!"</span><span class="pun">);</span></pre>

<h3>
	operator‎
</h3>

<p>
	يعيد مرجعًا إلى الحرف الموجود عند الفهرس n. لا يتحقّق المُعامل <code>td::string::operator[]‎</code> من حدود السلسلة النصّية، ولا يرفع اعتراضًا (exception) في حال تجاوزها، لذلك فالمُستدعي هو المسؤول عن التحقق من أنّ الفهرس يقع في حدود السلسلة النصّية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_88" style=""><span class="kwd">char</span><span class="pln"> c </span><span class="pun">=</span><span class="pln"> str</span><span class="pun">[</span><span class="lit">6</span><span class="pun">];</span><span class="pln"> </span><span class="com">// 'w'</span></pre>

<h3>
	at(n)‎
</h3>

<p>
	يعيد مرجعًا إلى الحرف الموجود عند الفهرس n. يتحقق المُعامل <code>‎std::string::at‎</code> من الحدود، ويرفع اعتراض <code>‎std::out_of_range‎</code> إذا لم يكن الفهرس ضمن حدود السلسلة النصّية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_90" style=""><span class="kwd">char</span><span class="pln"> c </span><span class="pun">=</span><span class="pln"> str</span><span class="pun">.</span><span class="pln">at</span><span class="pun">(</span><span class="lit">7</span><span class="pun">);</span><span class="pln"> </span><span class="com">// 'o'</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	<strong>ملاحظة</strong>: في كلا المثالين أعلاه، سيكون السّلوك غير محدد في حال كانت السلسلة النصية فارغة.
</p>

<h3>
	front()‎
</h3>

<p>
	يعيد مرجعًا إلى الحرف الأول:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_92" style=""><span class="kwd">char</span><span class="pln"> c </span><span class="pun">=</span><span class="pln"> str</span><span class="pun">.</span><span class="pln">front</span><span class="pun">();</span><span class="pln"> </span><span class="com">// 'H'</span></pre>

<h3>
	back()‎
</h3>

<p>
	يعيد مرجعًا إلى الحرف الأخير:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_94" style=""><span class="kwd">char</span><span class="pln"> c </span><span class="pun">=</span><span class="pln"> str</span><span class="pun">.</span><span class="pln">back</span><span class="pun">();</span><span class="pln"> </span><span class="com">// '!'</span></pre>

<h2>
	التحقق من كون سلسلة نصية سابقة (preﬁx) لسلسلة أخرى
</h2>

<p>
	<strong>الإصدار ≥ C++‎ 14</strong>
</p>

<p>
	في الإصدار C++‎ 14، يمكن إنجاز ذلك بسهولة عبر <a data-ss1617022524="1" href="https://en.cppreference.com/w/cpp/algorithm/mismatch" rel="external nofollow">‎std::mismatch‎</a>، والذي يُعيد الزوج الأوّل غير المتطابق من النطاقين:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_96" style=""><span class="pln">std</span><span class="pun">::</span><span class="pln">string prefix </span><span class="pun">=</span><span class="pln"> </span><span class="str">"foo"</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">string string </span><span class="pun">=</span><span class="pln"> </span><span class="str">"foobar"</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">bool</span><span class="pln"> isPrefix </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">mismatch</span><span class="pun">(</span><span class="pln">prefix</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> prefix</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln">
string</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> string</span><span class="pun">.</span><span class="pln">end</span><span class="pun">()).</span><span class="pln">first </span><span class="pun">==</span><span class="pln"> prefix</span><span class="pun">.</span><span class="pln">end</span><span class="pun">();</span></pre>

<p>
	قبل الإصدار C++‎ 14، كان هناك ما يُسمّى إصدار النطاق ونصف (range-and-a-half version) من التابع <code>‎mismatch()‎</code>، ولكنه لم يكن آمنًا في حال كانت السلسلة النصّية الثانية أقصر من الأولى.
</p>

<p>
	<strong>الإصدار &lt; C++‎ 14</strong>
</p>

<p>
	 
</p>

<p>
	<strong><c><strong> </strong></c>++‎&gt;</strong>
</p>

<p>
	لا زال بإمكاننا استخدام إصدار النطاق ونصف من التابع <code>‎std::mismatch()‎</code>، لكن سيكون عليك التحقّق أولًا من أنّ السلسلة النصّية الأولى أقصر من الثانية أو تعادلها:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_98" style=""><span class="kwd">bool</span><span class="pln"> isPrefix </span><span class="pun">=</span><span class="pln"> prefix</span><span class="pun">.</span><span class="pln">size</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;=</span><span class="pln"> string</span><span class="pun">.</span><span class="pln">size</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">mismatch</span><span class="pun">(</span><span class="pln">prefix</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> prefix</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln">
string</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> string</span><span class="pun">.</span><span class="pln">end</span><span class="pun">()).</span><span class="pln">first </span><span class="pun">==</span><span class="pln"> prefix</span><span class="pun">.</span><span class="pln">end</span><span class="pun">();</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 17 </strong>
</p>

<p>
	يمكننا كتابة الموازنة التي نريدها مباشرة مع <code>‎std::string_view‎</code>، دون الحاجة إلى القلق بشأن الحِمل الزائد في الذاكرة (allocation overhead) أو إنشاء النُّسخ:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_100" style=""><span class="kwd">bool</span><span class="pln"> isPrefix</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string_view prefix</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string_view full</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> prefix </span><span class="pun">==</span><span class="pln"> full</span><span class="pun">.</span><span class="pln">substr</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> prefix</span><span class="pun">.</span><span class="pln">size</span><span class="pun">());</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	التكرار على المحارف
</h2>

<p>
	<strong>الإصدار ≥ C++‎ 17 </strong>
</p>

<p>
	تدعم السلاسل النصّية <a data-ss1617022524="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-8-%D8%A7%D9%84%D9%85%D9%83%D8%B1%D8%A7%D8%B1%D8%A7%D8%AA-iterators-%D9%81%D9%8A-cpp-r892/" rel="">المُكرّرات</a>، وعليه تستطيع استخدام حلقة نطاقية (ranged based loop) للتكرار على المحارف:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_102" style=""><span class="pln">std</span><span class="pun">::</span><span class="pln">string str </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Hello World!"</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln"> c</span><span class="pun">:</span><span class="pln"> str</span><span class="pun">)</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> c</span><span class="pun">;</span></pre>

<p>
	يمكنك أيضًا استخدام حلقة <code>‎for‎</code> "تقليدية" للتكرار على المحارف:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_104" style=""><span class="pln">std</span><span class="pun">::</span><span class="pln">string str </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Hello World!"</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> str</span><span class="pun">.</span><span class="pln">length</span><span class="pun">();</span><span class="pln"> </span><span class="pun">++</span><span class="pln">i</span><span class="pun">)</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> str</span><span class="pun">[</span><span class="pln">i</span><span class="pun">];</span></pre>

<h2>
	التحويل إلى الأعداد الصحيحة أو العَشرية
</h2>

<p>
	يمكن تحويل سلسلة نصّية تحتوي على عدد إلى نوع عددي صحيح أو عشري باستخدام دوالّ التحويل.
</p>

<p>
	ملاحظة: تتوقف جميع هذه الدوالّ عن تحليل السلسلة النصّية المُدخلة بمجرد أن تصادف محرفًا غير رقمي. مثلاً، ستُحوّل السلسلة النصّية <code>‎"123abc"‎</code> إلى 123.
</p>

<p>
	تحوّل مجموعة الدوالّ <code>‎std::ato*‎</code> السلاسل النصّية من نمط لغة C (مصفوفات المحارف) إلى أنواع عددية صحيحة أو عشرية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_106" style=""><span class="pln">std</span><span class="pun">::</span><span class="pln">string ten </span><span class="pun">=</span><span class="pln"> </span><span class="str">"10"</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">double</span><span class="pln"> num1 </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">atof</span><span class="pun">(</span><span class="pln">ten</span><span class="pun">.</span><span class="pln">c_str</span><span class="pun">());</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> num2 </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">atoi</span><span class="pun">(</span><span class="pln">ten</span><span class="pun">.</span><span class="pln">c_str</span><span class="pun">());</span><span class="pln">
</span><span class="kwd">long</span><span class="pln"> num3 </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">atol</span><span class="pun">(</span><span class="pln">ten</span><span class="pun">.</span><span class="pln">c_str</span><span class="pun">());</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 11 </strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_108" style=""><span class="kwd">long</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> num4 </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">atoll</span><span class="pun">(</span><span class="pln">ten</span><span class="pun">.</span><span class="pln">c_str</span><span class="pun">());</span></pre>

<p>
	إلا أنّه يفضَّل تجنّب استخدام هذه الدوالّ لأنها تُعيد <code>‎0‎</code> في حال فشلت في تحليل السلسلة النصّية. وهذا سيء لأنّ القيمة <code>‎0‎</code> قد تُفسَّر على أنّها نتيجة عددية صالحة. مثلًا، إن كانت السلسلة النصية المُدخلة هي "0"، فسيكون من المستحيل تحديد ما إذا كان التحويل قد فشل أم لا بغضّ النظر عن النتيجة.
</p>

<p>
	وتحوّل الدوالّ الحديثة <code>‎std::sto*‎</code> السلاسل النصّية إلى أعداد صحيحة أو عشرية، وتطلق استثناءً في حال فشلت في تحليل السلسلة النصية. استخدم هذه الدّوال كلما أمكن:
</p>

<p>
	<strong>الإصدار ≥ C++‎ 11 </strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_110" style=""><span class="pln">std</span><span class="pun">::</span><span class="pln">string ten </span><span class="pun">=</span><span class="pln"> </span><span class="str">"10"</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> num1 </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">stoi</span><span class="pun">(</span><span class="pln">ten</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">long</span><span class="pln"> num2 </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">stol</span><span class="pun">(</span><span class="pln">ten</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">long</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> num3 </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">stoll</span><span class="pun">(</span><span class="pln">ten</span><span class="pun">);</span><span class="pln">

</span><span class="typ">float</span><span class="pln"> num4 </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">stof</span><span class="pun">(</span><span class="pln">ten</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">double</span><span class="pln"> num5 </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">stod</span><span class="pun">(</span><span class="pln">ten</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">long</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> num6 </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">stold</span><span class="pun">(</span><span class="pln">ten</span><span class="pun">);</span></pre>

<p>
	كذلك، فإنّ هذه الدوالّ يمكنها أن تتعامل أيضًا مع السلاسل النصّية الثُمانية (octal) والست عشرية (hex)، وذلك على عكس دوالّ <code>‎std::ato*‎</code>. والمعامل الثاني هو مؤشّر يشير إلى أوّل حرف غير مُحوَّل في السلسلة النصية المُدخَلَة، أمّا المعامل الثالث فيمثّل الأساس الرقمي (base) الذي يجب استخدامه. يُستخدَم الحرف <code>‎0‎</code> للرصد التلقائي للأعداد الثُمانية (تبدأ بـ <code>‎0‎</code>) والست عشرية (تبدأ بـ <code>‎0x‎</code> أو <code>‎0X‎</code>)، أما القيم الأخرى فتمثّل الأساس الذي يجب استخدامه.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_112" style=""><span class="pln">std</span><span class="pun">::</span><span class="pln">string ten </span><span class="pun">=</span><span class="pln"> </span><span class="str">"10"</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">string ten_octal </span><span class="pun">=</span><span class="pln"> </span><span class="str">"12"</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">string ten_hex </span><span class="pun">=</span><span class="pln"> </span><span class="str">"0xA"</span><span class="pun">;</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> num1 </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">stoi</span><span class="pun">(</span><span class="pln">ten</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">);</span><span class="pln"> </span><span class="com">// 2</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> num2 </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">stoi</span><span class="pun">(</span><span class="pln">ten_octal</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pun">);</span><span class="pln"> </span><span class="com">// 10</span><span class="pln">
</span><span class="kwd">long</span><span class="pln"> num3 </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">stol</span><span class="pun">(</span><span class="pln">ten_hex</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">16</span><span class="pun">);</span><span class="pln"> </span><span class="com">// 10</span><span class="pln">
</span><span class="kwd">long</span><span class="pln"> num4 </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">stol</span><span class="pun">(</span><span class="pln">ten_hex</span><span class="pun">);</span><span class="pln"> </span><span class="com">// 0</span><span class="pln">
</span><span class="kwd">long</span><span class="pln"> num5 </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">stol</span><span class="pun">(</span><span class="pln">ten_hex</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">);</span><span class="pln"> </span><span class="com">// 0x تعيد 10 لأنها رصدت</span></pre>

<h2>
	ضم السلاسل النصّية
</h2>

<p>
	يمكنك ضمّ (concatenate) السلاسل النصّية باستخدام المُعاملين <a data-ss1617022524="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-23-%D8%A7%D9%84%D8%AA%D8%AD%D9%85%D9%8A%D9%84-%D8%A7%D9%84%D8%B2%D8%A7%D8%A6%D8%AF-%D9%84%D9%84%D8%B9%D9%88%D8%A7%D9%85%D9%84-operator-overloading-%D9%81%D9%8A-cpp-r935/" rel="">المُحمَّلين تحميلًا زائدًا</a> <code>‎+‎</code> و <code>‎+=‎</code>.
</p>

<p>
	استخدام المُعامل <code>‎+‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_114" style=""><span class="pln">std</span><span class="pun">::</span><span class="pln">string hello </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Hello"</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">string world </span><span class="pun">=</span><span class="pln"> </span><span class="str">"world"</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">string helloworld </span><span class="pun">=</span><span class="pln"> hello </span><span class="pun">+</span><span class="pln"> world</span><span class="pun">;</span><span class="pln"> </span><span class="com">// "Helloworld"</span></pre>

<p>
	استخدام المُعامل <code>‎+=‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_116" style=""><span class="pln">std</span><span class="pun">::</span><span class="pln">string hello </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Hello"</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">string world </span><span class="pun">=</span><span class="pln"> </span><span class="str">"world"</span><span class="pun">;</span><span class="pln">
hello </span><span class="pun">+=</span><span class="pln"> world</span><span class="pun">;</span><span class="pln"> </span><span class="com">// "Helloworld"</span></pre>

<p>
	يمكنك أيضًا ضمّ السلاسل النصّية من نمط لغة C، بما في ذلك السلاسل النصّية المجردة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_118" style=""><span class="pln">std</span><span class="pun">::</span><span class="pln">string hello </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Hello"</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">string world </span><span class="pun">=</span><span class="pln"> </span><span class="str">"world"</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> </span><span class="pun">*</span><span class="pln">comma </span><span class="pun">=</span><span class="pln"> </span><span class="str">", "</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">string newhelloworld </span><span class="pun">=</span><span class="pln"> hello </span><span class="pun">+</span><span class="pln"> comma </span><span class="pun">+</span><span class="pln"> world </span><span class="pun">+</span><span class="pln"> </span><span class="str">"!"</span><span class="pun">;</span><span class="pln"> </span><span class="com">// "Hello, world!"</span></pre>

<p>
	يمكنك أيضًا استخدام <code>‎push_back()‎</code> لإضافة حرف واحد إلى السلسلة النصية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_120" style=""><span class="pln">std</span><span class="pun">::</span><span class="pln">string s </span><span class="pun">=</span><span class="pln"> </span><span class="str">"a, b, "</span><span class="pun">;</span><span class="pln">
s</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="str">'c'</span><span class="pun">);</span><span class="pln"> </span><span class="com">// "a, b, c"</span></pre>

<p>
	لدينا يوجد أيضًا تابع <code>‎append()‎</code>، والذي يشبه إلى حد كبير <code>‎+=‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_122" style=""><span class="pln">std</span><span class="pun">::</span><span class="pln">string app </span><span class="pun">=</span><span class="pln"> </span><span class="str">"test and "</span><span class="pun">;</span><span class="pln">
app</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="str">"test"</span><span class="pun">);</span><span class="pln"> </span><span class="com">// "test and test"</span></pre>

<h2>
	التحويل بين ترميزات المحارف
</h2>

<p>
	التحويل بين الترميزات (encodings) أمر سهل في C++‎ 11، ويمكن لمعظم المصرّفات إنجازه بطريقة مستقلّة عن المنصة (cross-platform) عبر الترويستين <codecvt> و <locale>. </locale></codecvt>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_124" style=""><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;codecvt&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;locale&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;string&gt;</span><span class="pln">

</span><span class="kwd">using</span><span class="pln"> </span><span class="kwd">namespace</span><span class="pln"> std</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// wstring  و utf8 يحول بين سلاسل</span><span class="pln">
    wstring_convert </span><span class="pun">&lt;</span><span class="pln"> codecvt_utf8_utf16 </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">wchar_t</span><span class="pln"> </span><span class="pun">&gt;&gt;</span><span class="pln"> wchar_to_utf8</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// utf16 وسلاسل utf8 يحول بين سلاسل</span><span class="pln">
    wstring_convert </span><span class="pun">&lt;</span><span class="pln"> codecvt_utf8_utf16 </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">char16_t</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">,</span><span class="pln"> </span><span class="typ">char16_t</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> utf16_to_utf8</span><span class="pun">;</span><span class="pln">

    wstring wstr </span><span class="pun">=</span><span class="pln"> L</span><span class="str">"foobar"</span><span class="pun">;</span><span class="pln">
    string utf8str </span><span class="pun">=</span><span class="pln"> wchar_to_utf8</span><span class="pun">.</span><span class="pln">to_bytes</span><span class="pun">(</span><span class="pln">wstr</span><span class="pun">);</span><span class="pln">
    wstring wstr2 </span><span class="pun">=</span><span class="pln"> wchar_to_utf8</span><span class="pun">.</span><span class="pln">from_bytes</span><span class="pun">(</span><span class="pln">utf8str</span><span class="pun">);</span><span class="pln">

    wcout </span><span class="pun">&lt;&lt;</span><span class="pln"> wstr </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">
    cout </span><span class="pun">&lt;&lt;</span><span class="pln"> utf8str </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">
    wcout </span><span class="pun">&lt;&lt;</span><span class="pln"> wstr2 </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">

    u16string u16str </span><span class="pun">=</span><span class="pln"> u</span><span class="str">"foobar"</span><span class="pun">;</span><span class="pln">
    string utf8str2 </span><span class="pun">=</span><span class="pln"> utf16_to_utf8</span><span class="pun">.</span><span class="pln">to_bytes</span><span class="pun">(</span><span class="pln">u16str</span><span class="pun">);</span><span class="pln">
    u16string u16str2 </span><span class="pun">=</span><span class="pln"> utf16_to_utf8</span><span class="pun">.</span><span class="pln">from_bytes</span><span class="pun">(</span><span class="pln">utf8str2</span><span class="pun">);</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لاحظ أنّ Visual Studio 2015 يدعم مثل هذه التحويلات، ولكن بسبب خلل موجود في مكتبتها، فينبغي استخدام قالب مختلف لـ <code>‎wstring_convert‎</code> عند التعامل مع الترميز <code>‎char16_t‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_126" style=""><span class="kwd">using</span><span class="pln"> utf16_char </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">unsigned</span><span class="pln"> </span><span class="kwd">short</span><span class="pun">;</span><span class="pln">
wstring_convert</span><span class="pun">&lt;</span><span class="pln">codecvt_utf8_utf16</span><span class="str">&lt;utf16_char&gt;</span><span class="pun">,</span><span class="pln"> utf16_char</span><span class="pun">&gt;</span><span class="pln"> conv_utf8_utf16</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> strings</span><span class="pun">::</span><span class="pln">utf16_to_utf8</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">u16string</span><span class="pun">&amp;</span><span class="pln"> utf16</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">&amp;</span><span class="pln"> utf8</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">basic_string</span><span class="str">&lt;utf16_char&gt;</span><span class="pln"> tmp</span><span class="pun">;</span><span class="pln">
tmp</span><span class="pun">.</span><span class="pln">resize</span><span class="pun">(</span><span class="pln">utf16</span><span class="pun">.</span><span class="pln">length</span><span class="pun">());</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">copy</span><span class="pun">(</span><span class="pln">utf16</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> utf16</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> tmp</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">());</span><span class="pln">
utf8 </span><span class="pun">=</span><span class="pln"> conv_utf8_utf16</span><span class="pun">.</span><span class="pln">to_bytes</span><span class="pun">(</span><span class="pln">tmp</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	البحث عن محرف أو أكثر في السلسلة النصية
</h2>

<p>
	استخدام التابع <code>‎std::string::find‎</code>لإيجاد حرف أو سلسلة نصّية أخرى، والذي يعيد موضع الحرف الأوّل من التطابق الأوّل. أما إن لم يُعثر على أيّ تطابق، فستُعاد القيمة <code>‎std::string::npos‎</code>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_128" style=""><span class="pln">std</span><span class="pun">::</span><span class="pln">string str </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Curiosity killed the cat"</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> it </span><span class="pun">=</span><span class="pln"> str</span><span class="pun">.</span><span class="pln">find</span><span class="pun">(</span><span class="str">"cat"</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">it </span><span class="pun">!=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">::</span><span class="pln">npos</span><span class="pun">)</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Found at position: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> it </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">else</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Not found!\n"</span><span class="pun">;</span></pre>

<p>
	ستكون النتيجة 21.
</p>

<p>
	تُوسَّع فرص البحث بالدوال التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_130" style=""><span class="pln">find_first_of     </span><span class="com">// إيجاد أول ظهور للمحارف</span><span class="pln">
find_first_not_of </span><span class="com">// إيجاد أول غياب للمحارف</span><span class="pln">
find_last_of      </span><span class="com">// إيجارد آخر ظهور للمحارف</span><span class="pln">
find_last_not_of  </span><span class="com">// إيجاد آخر غياب للمحارف</span></pre>

<p>
	تتيح لك لك هذه الدوالّ أن تبحث عن المحارف من نهاية السلسلة النصّية، وكذلك البحث عن الحالات السلبية (أي المحارف غير الموجودة في السلسلة). انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5033_132" style=""><span class="pln">std</span><span class="pun">::</span><span class="pln">string str </span><span class="pun">=</span><span class="pln"> </span><span class="str">"dog dog cat cat"</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Found at position: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> str</span><span class="pun">.</span><span class="pln">find_last_of</span><span class="pun">(</span><span class="str">"gzx"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span></pre>

<p>
	ستكون النتيجة 6.
</p>

<p>
	ملاحظة: لا تبحث الدوالّ المذكورة أعلاه عن السلاسل النصّية الفرعية (substrings)، بل عن المحارف الموجودة في سلسلة البحث، ففي المثال أعلاه عُثِر على الظهور الأخير لـ <code>‎'g'‎</code> في الموضع <code>‎6‎</code> بينما لم يُعثر على المحارف الأخرى.
</p>

<p>
	هذا الدرس جزء من <a data-ss1617022524="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة مقالات عن C++‎</a>.
</p>

<p>
	ترجمة -بتصرّف- للفصل Chapter 47: std::string من كتاب <a data-ss1617022524="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>

<p>
	 
</p>
]]></description><guid isPermaLink="false">940</guid><pubDate>Sun, 26 Jul 2020 13:09:00 +0000</pubDate></item><item><title><![CDATA[ملفات الترويسات (Header Files) ومعالجة التاريخ والوقت باستخدام الترويسة <chrono> في Cpp]]></title><link>https://academy.hsoub.com/programming/cpp/%D9%85%D9%84%D9%81%D8%A7%D8%AA-%D8%A7%D9%84%D8%AA%D8%B1%D9%88%D9%8A%D8%B3%D8%A7%D8%AA-header-files-%D9%88%D9%85%D8%B9%D8%A7%D9%84%D8%AC%D8%A9-%D8%A7%D9%84%D8%AA%D8%A7%D8%B1%D9%8A%D8%AE-%D9%88%D8%A7%D9%84%D9%88%D9%82%D8%AA-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A7%D9%84%D8%AA%D8%B1%D9%88%D9%8A%D8%B3%D8%A9-%D9%81%D9%8A-cpp-r939/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_06/27.jpg.893c745688fae3d2842fb7824b399cbb.jpg" /></p>

<h2>
	مثال بسيط
</h2>

<p>
	يحتوي المثال التالي على شيفرة يُراد تقسيمها إلى عدّة ملفّات مصدرية، سننظر الآن في كل ملف على حدة:
</p>

<h3>
	الملفات المصدرية
</h3>

<ul>
<li>
		<strong>my_function.h</strong>
	</li>
</ul>
<p>
	في هذا الملف، لاحظ أن الترويسة التالية تحتوي على تصريح للدالة فقط، ولا تعرِّف دوال الترويسة تطبيقات للتصريحات إلا إن وجب معالجة الشيفرة أكثر أثناء التصريف، كما هو الحال في القوالب. وعادة ما تحتوي ملفات الترويسة على واقيات معالج مسبق (Preprocessor Guards) حتى لا تضاف نفس الترويسة مرتين. ويُنفَّذ الواقي بالتحقق من كون المفتاح الرمزي (Token) الفريد للمعالج المسبق معرَّفًا أم لا، ولا تُضمَّن الترويسة إلا إن كانت غير مضمَّنة من قبل. سيتم التعرف على كل من <code>global_value</code> و <code>()my_function</code> على أنهما نفس البُنية إن أضيفت هذه الترويسة من قبَل عدة ملفات.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_985_7" style="">
<span class="com">// my_function.h</span><span class="pln">
</span><span class="com">#ifndef</span><span class="pln"> MY_FUNCTION_H
</span><span class="com">#define</span><span class="pln"> MY_FUNCTION_H

</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> global_value </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> my_function</span><span class="pun">();</span><span class="pln">
</span><span class="com">#endif</span><span class="pln"> </span><span class="com">// MY_FUNCTION_H</span></pre>

<ul>
<li>
		<strong>my_function.cpp</strong>
	</li>
</ul>
<p>
	في هذا الملف، لاحظ أن الملف المصدري المقابل للترويسة يدرِج الواجهة المعرَّفة في الترويسة، كي ينتبه المصرِّف إلى ما ينفذه الملف المصدري. ويتطلب الملف المصدري في هذا الحالة معرفة الثابت العام <code>global_value</code> المعرَّف في ملف <code>my_function.h</code> الذي استعرضناه قبل قليل، ولن يصرَّف هذا الملف المصدري بدون الترويسة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_985_9" style="">
<span class="com">// my_function.cpp</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">"my_function.h"</span><span class="pln"> </span><span class="com">// or #include "my_function.hpp"</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> my_function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> global_value</span><span class="pun">;</span><span class="pln"> </span><span class="com">// 42;</span><span class="pln">
</span><span class="pun">}</span></pre>

<ul>
<li>
		<strong>main.cpp</strong>
	</li>
</ul>
<p>
	تُدرج ملفّات الترويسة بعد ذلك في الملفّات المصدرية الأخرى التي ترغب في استخدام الوظائف المُعرّفة في واجهة الترويسة، دون الحاجة إلى معرفة تفاصيل تنفيذها، مما يساعد على اختزال الشيفرة. يستخدم البرنامج التالي الترويسة <code>‎my_function.h‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_985_11" style="">
<span class="com">// main.cpp</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">       </span><span class="com">// ترويسة مكتبة قياسية</span><span class="pln">

</span><span class="com">#include</span><span class="pln"> </span><span class="str">"my_function.h"</span><span class="pln">  </span><span class="com">// ترويسة خاصة</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> argc</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">**</span><span class="pln"> argv</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> my_function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	عملية التصريف (The Compilation Process)
</h3>

<p>
	تكون ملفّات الترويسة غالبًا جزءًا من عملية التصريف، لذا يحدث ما يلي خلال عملية التصريف في العادةً:
</p>

<p>
	على افتراض أنّ ملفّ الترويسة وملفّّ الشيفرة المصدرية موجودان في نفس المجلّد، فيمكن تصريف البرنامج عبر تنفيذ الأوامر التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_985_25" style="">
<span class="pln">g</span><span class="pun">++</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> c my_function</span><span class="pun">.</span><span class="pln">cpp 
g</span><span class="pun">++</span><span class="pln">main</span><span class="pun">.</span><span class="pln">cpp my_function</span><span class="pun">.</span><span class="pln">o</span></pre>

<p>
	السطر الأولُ في الشيفرة السابقة يصرِّف الملفَّ المصدري <code>my_function.cpp</code> إلى <code>my_function.o</code>، ويربط السطر الثاني ملفَّ الكائن الذي يتحوي تنفيذ <code>()int my_function</code> إلى نسخة الكائن المصرَّفة من <code>main.cpp</code> ثم ينتج النسخة التنفيذية النهائية <code>a.out</code>.
</p>

<p>
	بالمقابل، إذا رغبت في تصريف <code>‎main.cpp‎</code> إلى ملفّ كائنٍ أولًا، ثم ربط ملفّات التعليمات المصرّفة في النهاية، فيمكنك ذلك عبر الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_985_27" style="">
<span class="pln">g</span><span class="pun">++</span><span class="pln"> </span><span class="pun">-</span><span class="pln">c my_function</span><span class="pun">.</span><span class="pln">cpp
g</span><span class="pun">++</span><span class="pln"> </span><span class="pun">-</span><span class="pln">c main</span><span class="pun">.</span><span class="pln">cpp

g</span><span class="pun">++</span><span class="pln"> main</span><span class="pun">.</span><span class="pln">o my_function</span><span class="pun">.</span><span class="pln">o</span></pre>

<h2>
	القوالب في ملفات الترويسات
</h2>

<p>
	تتطلّب القوالب إنشاء الشيفرة وقت التصريف: على سبيل المثال، تُحوّل دالّة مُقولَبة (templated function) إلى عدة دوالّ مختلفة بمجرد جعل الدالّة المُقَولبة معامِلًا (parameter) عبر استخدامها في الشيفرة المصدرية.
</p>

<p>
	هذا يعني أنّه لا يمكن تفويض الدوالّ والتوابع وتعريفات الأصناف في القوالب إلى ملفّ مصدري آخر، ذلك أنّ أيّ شيفرة تستخدم بنية مُقولَبَة تحتاج إلى أن تَطَّلِع على تعريف تلك البنية لإنشاء الشيفرة المشتقّة. وعليه يجب أن تحتوي الشيفرة المُقولبَة على تعريفها في حال وُضِعت في الترويسات. هذا مثال على ذلك:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_985_29" style="">
<span class="com">// templated_function.h</span><span class="pln">

</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln">
    T</span><span class="pun">*</span><span class="pln"> null_T_pointer</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        T</span><span class="pun">*</span><span class="pln"> type_point </span><span class="pun">=</span><span class="pln"> NULL</span><span class="pun">;</span><span class="pln"> </span><span class="com">// وما بعدها C++11 في NULL بدلا من nullptr أو </span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> type_point</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span></pre>

<h2>
	معالجة التاريخ والوقت باستخدام الترويسة &lt;chrono&gt;<chrono></chrono>
</h2>

<h3>
	قياس الوقت باستخدام &lt;chrono&gt;<chrono></chrono>
</h3>

<p>
	يمكن استخدام <code>‎system_clock‎</code> لقيَاس الوقت المنقضي منذ مرحلة معيّنة من تنفيذ البرنامج.
</p>

<p>
	<strong>الإصدار = C++‎ 11</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_985_31" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;chrono&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;thread&gt;</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> start </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">chrono</span><span class="pun">::</span><span class="pln">system_clock</span><span class="pun">::</span><span class="pln">now</span><span class="pun">();</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">// الشيفرة المراد اختبارها</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">this_thread</span><span class="pun">::</span><span class="pln">sleep_for</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">chrono</span><span class="pun">::</span><span class="pln">seconds</span><span class="pun">(</span><span class="lit">2</span><span class="pun">));</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> end </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">chrono</span><span class="pun">::</span><span class="pln">system_clock</span><span class="pun">::</span><span class="pln">now</span><span class="pun">();</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">chrono</span><span class="pun">::</span><span class="pln">duration </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> elapsed </span><span class="pun">=</span><span class="pln"> end </span><span class="pun">-</span><span class="pln"> start</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Elapsed time: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> elapsed</span><span class="pun">.</span><span class="pln">count</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"s"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	استخدمنا في هذا المثال <code>‎sleep_for‎</code> لجعل الخيط النشط ينام (sleep) لفترة زمنية مُقاسة بالثواني <code>std::chrono::seconds</code>.
</p>

<h3>
	حساب عدد الأيام بين تاريخين
</h3>

<p>
	يوضّح هذا المثال كيفية حساب عدد الأيّام بين تاريخين، ويُحدَّد التاريخ بالصيغة سنة/شهر/يوم (year/month/day)، بالإضافة إلى ساعة/دقيقة/ثانية (hour/minute/second).
</p>

<p>
	يحسب <a data-ss1617022523="1" href="http://en.cppreference.com/w/cpp/chrono/c/tm" rel="external nofollow">البرنامج التالي المستوحى من موقع cppreference</a> عدد الأيام منذ عام 2000. سننشئ بُنية <code>std::tm</code> من التاريخ الخام على النحو التالي:
</p>

<ul>
<li>
		<code>year</code> يجب أن تكون 1900 أو أكبر.
	</li>
	<li>
		<code>month</code> من يناير (1 - 12).
	</li>
	<li>
		<code>day</code> اليوم من الشهر (1 - 31).
	</li>
	<li>
		<code>minutes</code> الدقائق بعد الساعة (0 - 59).
	</li>
	<li>
		<code>seconds</code> الثواني بعد الدقيقة (0 - 61)، و (0 - 60) منذ C++ 11.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_985_33" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;string&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;chrono&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;ctime&gt;</span><span class="pln">

std</span><span class="pun">::</span><span class="pln">tm </span><span class="typ">CreateTmStruct</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> year</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> month</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> day</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> hour</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> minutes</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> seconds</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> tm tm_ret </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="lit">0</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">

    tm_ret</span><span class="pun">.</span><span class="pln">tm_sec </span><span class="pun">=</span><span class="pln"> seconds</span><span class="pun">;</span><span class="pln">
    tm_ret</span><span class="pun">.</span><span class="pln">tm_min </span><span class="pun">=</span><span class="pln"> minutes</span><span class="pun">;</span><span class="pln">
    tm_ret</span><span class="pun">.</span><span class="pln">tm_hour </span><span class="pun">=</span><span class="pln"> hour</span><span class="pun">;</span><span class="pln">
    tm_ret</span><span class="pun">.</span><span class="pln">tm_mday </span><span class="pun">=</span><span class="pln"> day</span><span class="pun">;</span><span class="pln">
    tm_ret</span><span class="pun">.</span><span class="pln">tm_mon </span><span class="pun">=</span><span class="pln"> month </span><span class="pun">-</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
    tm_ret</span><span class="pun">.</span><span class="pln">tm_year </span><span class="pun">=</span><span class="pln"> year </span><span class="pun">-</span><span class="pln"> </span><span class="lit">1900</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> tm_ret</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> get_days_in_year</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> year</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

    </span><span class="kwd">using</span><span class="pln"> </span><span class="kwd">namespace</span><span class="pln"> std</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">using</span><span class="pln"> </span><span class="kwd">namespace</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">chrono</span><span class="pun">;</span><span class="pln">

    </span><span class="com">// نريد أن تكون النتيجة بالأيام</span><span class="pln">
    </span><span class="kwd">typedef</span><span class="pln"> duration </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pun">,</span><span class="pln"> ratio_multiply </span><span class="pun">&lt;</span><span class="pln"> hours</span><span class="pun">::</span><span class="pln">period</span><span class="pun">,</span><span class="pln"> ratio </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">24</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="pln">type </span><span class="pun">&gt;</span><span class="pln"> days</span><span class="pun">;</span><span class="pln">

    </span><span class="com">// بداية الوقت</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">tm tm_start </span><span class="pun">=</span><span class="pln"> </span><span class="typ">CreateTmStruct</span><span class="pun">(</span><span class="pln">year</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> tms </span><span class="pun">=</span><span class="pln"> system_clock</span><span class="pun">::</span><span class="typ">from_time_t</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">mktime</span><span class="pun">(</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> tm_start</span><span class="pun">));</span><span class="pln">

    </span><span class="com">// نهاية الوقت</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">tm tm_end </span><span class="pun">=</span><span class="pln"> </span><span class="typ">CreateTmStruct</span><span class="pun">(</span><span class="pln">year </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> tme </span><span class="pun">=</span><span class="pln"> system_clock</span><span class="pun">::</span><span class="typ">from_time_t</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">mktime</span><span class="pun">(</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> tm_end</span><span class="pun">));</span><span class="pln">

    </span><span class="com">// حساب الوقت الذي مرّ بين التاريخين</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> diff_in_days </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">chrono</span><span class="pun">::</span><span class="pln">duration_cast </span><span class="pun">&lt;</span><span class="pln"> days </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">tme </span><span class="pun">-</span><span class="pln"> tms</span><span class="pun">);</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> diff_in_days</span><span class="pun">.</span><span class="pln">count</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> year </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2000</span><span class="pun">;</span><span class="pln"> year </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="lit">2016</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">year</span><span class="pun">)</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"There are "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> get_days_in_year</span><span class="pun">(</span><span class="pln">year</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" days in "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> year </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	هذا الدرس جزء من <a data-ss1617022523="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة دروس عن C++‎</a>.
</p>

<p>
	ترجمة -بتصرّف- للفصل Chapter 45: Header Files والفصل Chapter 66: Date and time using <chrono> header من كتاب <a data-ss1617022523="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a> </chrono></p>
]]></description><guid isPermaLink="false">939</guid><pubDate>Fri, 24 Jul 2020 13:00:00 +0000</pubDate></item><item><title>&#x641;&#x636;&#x627;&#x621;&#x627;&#x62A; &#x627;&#x644;&#x623;&#x633;&#x645;&#x627;&#x621; (Namespaces) &#x641;&#x64A; Cpp</title><link>https://academy.hsoub.com/programming/cpp/%D9%81%D8%B6%D8%A7%D8%A1%D8%A7%D8%AA-%D8%A7%D9%84%D8%A3%D8%B3%D9%85%D8%A7%D8%A1-namespaces-%D9%81%D9%8A-cpp-r938/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_06/26.jpg.b70dbddb1acdee3b9d8e5c9a5b82ace5.jpg" /></p>

<p>
	تُستخدم فضاءات الأسماء (Namespaces) لمنع التضارب الذي قد يحدث عند استخدام عدّة مكتبات في نفس البرنامج، وفضاء الاسم سابقةٌ (prefix) تعريفية للدوالّ والأصناف والأنواع وغيرها.
</p>

<h2>
	ما هي فضاءات الاسم؟
</h2>

<p>
	فضاء الاسم في لغة ++C هو مجموعة من كيانات C++‎ سواءً كانت دوالًا أو أصنافًا أو متغيرات، وتُسبق أسماءها باسم "فضاء الاسم"، وعند كتابة شيفرة ضمن فضاء الاسم فلا يلزم إسباق الكيانات المسمّاة التي تنتمي إلى فضاء الاسم باسم ذلك الفضاء، أمّا الكيانات الموجودة خارجه فيجب أن تُؤهّل أسماؤها (أي تُسبق باسم "فضاء الاسم").
</p>

<p>
	الاسم المؤهّل يأخذ الشكل التالي <code>‎&lt;namespace&gt;::&lt;entity&gt;‎</code>. انظر الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8752_7" style="">
<span class="kwd">namespace</span><span class="pln"> </span><span class="typ">Example</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> test </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> test2 </span><span class="pun">=</span><span class="pln"> test </span><span class="pun">+</span><span class="pln"> </span><span class="lit">12</span><span class="pun">;</span><span class="pln">        </span><span class="com">// `Example` تعمل داخل فضاء الاسم</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> test3 </span><span class="pun">=</span><span class="pln"> test </span><span class="pun">+</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;</span><span class="pln">             </span><span class="com">// غير موجودة خارج فضاء الاسم `test` خطأ، لأن</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> test3 </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Example</span><span class="pun">::</span><span class="pln">test </span><span class="pun">+</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;</span><span class="pln">    </span><span class="com">// هذا يعمل لأنّ المتغير مؤهل</span></pre>

<p>
	فضاءات الاسم مفيدة لتجميع التعريفات المرتبطة ببعضها معًا، ويمكن تشبيهها بمراكز التسوف التي تُقسّم إلى عدة متاجر يبيع كل منها سلعًا من صنف محدد، فقد يكون أحد المتاجر متخصصًأ في الإلكترونيات بينما يكون مجال الآخر في بيع الأحذية.
</p>

<p>
	هذا التصنيف المنطقي لأنواع المتاجر يساعد المتسوّقين على العثور على السلع التي يبحثون عنها. وبالمثل فإن فضاءات الاسم تساعد مبرمجي C++‎ في العثور على الدوالّ والأصناف والمتغيرات التي يبحثون عنها من خلال تنظيمها بطريقة منطقية. مثلًا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8752_9" style="">
<span class="kwd">namespace</span><span class="pln"> </span><span class="typ">Electronics</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> </span><span class="typ">TotalStock</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Headphones</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// (color, brand, model number) وصف السماعات</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
    </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Television</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// (color, brand, model number) وصف التلفاز</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">Shoes</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> </span><span class="typ">TotalStock</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Sandal</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// (color, brand, model number) وصف الصندل</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
    </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Slipper</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// (color, brand, model number) وصف الخُف</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لدينا فضاء اسم معرّف مسبقًا وهو فضاء الاسم العام ( global namespace)، وليس لهذا الفضاء اسم، لكن يُرمَز إليه بـ <code>‎::‎</code>. مثلًا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8752_11" style="">
<span class="kwd">void</span><span class="pln"> bar</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// مُعرّفة في فضاء الاسم العام</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">namespace</span><span class="pln"> foo </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> bar</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// foo مُعرّفة في فضاء الاسم  </span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> barbar</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        bar</span><span class="pun">();</span><span class="pln"> </span><span class="com">// foo::bar() استدعاء</span><span class="pln">
        </span><span class="pun">::</span><span class="pln">bar</span><span class="pun">();</span><span class="pln"> </span><span class="com">// المُعرّفة في فضاء الاسم العام  bar() استدعاء</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	البحث القائم على الوسائط
</h2>

<p>
	عند استدعاء دالّة ليس لها مؤهّلُ فضاءِ اسمٍ (namespace qualifier) صريح، فإن للمصرّف الحرية في استدعاء تلك الدالّة داخل فضاء اسم ما إن وُجد أحد أنواع المعاملات الخاصّة بتلك الدالّة في هذا الفضاء، وهذا يُسمّى "البحث القائم على الوسائط" (Argument Dependent Lookup أو ADL)، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8752_13" style="">
<span class="kwd">namespace</span><span class="pln"> </span><span class="typ">Test</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> call</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">SomeClass</span><span class="pln"> </span><span class="pun">{...};</span><span class="pln">

    </span><span class="typ">int</span><span class="pln"> call_too</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">SomeClass</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> data</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

call</span><span class="pun">(</span><span class="lit">5</span><span class="pun">);</span><span class="pln"> </span><span class="com">// خطأ: اسم دالّة غير مؤهل</span><span class="pln">

</span><span class="typ">Test</span><span class="pun">::</span><span class="typ">SomeClass</span><span class="pln"> data</span><span class="pun">;</span><span class="pln">

call_too</span><span class="pun">(</span><span class="pln">data</span><span class="pun">);</span><span class="pln"> </span><span class="com">// ناجح.</span></pre>

<p>
	تفشل <code>‎call‎</code> لأنّ أنواع المعاملات الخاصة بها لا تنتمي إلى فضاء الاسم <code>‎Test‎</code>، على عكس <code>‎call_too‎</code> التي تعمل بنجاح لأنّ <code>‎SomeClass‎</code> عضو في <code>‎Test‎</code>، ومن ثم فإنه مؤهّل للبحث القائم على الوسائط.
</p>

<h3>
	ما الذي يمنع البحث القائم على الوسائط (ADL)
</h3>

<p>
	لا يحدث البحث القائم على الوسائط إذا كان البحث العادي غير المؤهّل (normal unqualiﬁed lookup) يجد عضوًا من صنف أو دالّة مُصرَّحة في نطاق الكتلة أو كائنًا من غير نوع الدالّة. انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8752_15" style="">
<span class="kwd">void</span><span class="pln"> foo</span><span class="pun">();</span><span class="pln">
</span><span class="kwd">namespace</span><span class="pln"> N </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> X </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">(</span><span class="pln">X </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'1'</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> qux</span><span class="pun">(</span><span class="pln">X </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'2'</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">struct</span><span class="pln"> C </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> bar</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
           </span><span class="com">// لا تأخذ أي وسائط C::foo() خطأ: البحث القائم على الوسائط معطّل والدالّة</span><span class="pln">
foo</span><span class="pun">(</span><span class="pln">N</span><span class="pun">::</span><span class="pln">X</span><span class="pun">{});</span><span class="pln"> 
</span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> bar</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">extern</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">();</span><span class="pln"> </span><span class="com">// ‫إعادة تعريف ‎::foo</span><span class="pln">
 </span><span class="com">// لا تأخذ أي وسائط ::foo() خطأ: البحث القائم على الوسائط معطّل والدالّة</span><span class="pln">
foo</span><span class="pun">(</span><span class="pln">N</span><span class="pun">::</span><span class="pln">X</span><span class="pun">{});</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> qux</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">void</span><span class="pln"> baz</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
qux</span><span class="pun">(</span><span class="pln">N</span><span class="pun">::</span><span class="pln">X</span><span class="pun">{});</span><span class="pln"> </span><span class="com">// qux خطأ: إعلان المتغير يعطل البحث القائم على الوسائط بالنسبة لـ </span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	توسيع فضاءات الاسم
</h2>

<p>
	إحدى الميزات المفيدة لفضاءات الاسم <code>‎namespace‎</code> هو أنّه يمكنك توسيعها، أي إضافة أعضاء إليها.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8752_17" style="">
<span class="kwd">namespace</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> bar</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="com">// أشياء أخرى</span><span class="pln">
</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> bar2</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	المُوجّه 'using'
</h2>

<p>
	كلمة <code>using</code> المفتاحية لها ثلاث نكهات، وعندما نجمعها مع كلمة <code>namespace</code> فإننا نكتب موجِّهَ <code>using</code> أو (Using Directive)، فإذا لم ترد أن تكتب <code>‎Foo::‎</code> قبل كلّ كيان في فضاء الاسم <code>‎Foo‎</code>، فيمكنك استخدام التعبير <code>‎using namespace Foo;‎</code> لاستيراد كل ما تحتويه <code>‎Foo‎</code>. انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8752_19" style="">
<span class="kwd">namespace</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> bar</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> baz</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="com">// Foo::bar() ينبغي استخدام</span><span class="pln">
</span><span class="typ">Foo</span><span class="pun">::</span><span class="pln">bar</span><span class="pun">();</span><span class="pln">
</span><span class="com">// Foo استيراد</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">Foo</span><span class="pun">;</span><span class="pln">
bar</span><span class="pun">();</span><span class="pln"> </span><span class="com">// جيد</span><span class="pln">
baz</span><span class="pun">();</span><span class="pln"> </span><span class="com">// جيد</span></pre>

<p>
	من الممكن أيضًا استيراد كيانات محدّدة في فضاء الاسم بدلاً من استيراد فضاء الاسم بأكمله:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8752_21" style="">
<span class="kwd">using</span><span class="pln"> </span><span class="typ">Foo</span><span class="pun">::</span><span class="pln">bar</span><span class="pun">;</span><span class="pln">
bar</span><span class="pun">();</span><span class="pln"> </span><span class="com">// جيد، تم استيراده بنجاح.</span><span class="pln">
baz</span><span class="pun">();</span><span class="pln"> </span><span class="com">// خطأ، لم يُستورَد.</span></pre>

<p>
	<strong>تحذير</strong>: غالبًا ما يُعدّ وضع <code>‎using namespace‎</code> في ملفات الترويسة من الممارسات السيئة لأنّ ذلك سيؤدي إلى استيراد فضاء الاسم في كلّ ملف يتضمن تلك الترويسة. ونظرًا لعدم وجود أيّ طريقة لتعطيل استيراد فضاء الاسم، فقد يؤدي ذلك إلى تلويث فضاء الاسم (أي حشو فضاء الاسم العام برموز كثيرة أو غير متوقعة)، أو قد يؤدّي إلى التضارب بين الأسماء. انظر المثال التالي لتوضيح هذا الأمر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8752_23" style="">
<span class="com">/***** foo.h *****/</span><span class="pln">
</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">class</span><span class="pln"> C</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="com">/***** bar.h *****/</span><span class="pln">
</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">Bar</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">class</span><span class="pln"> C</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="com">/***** baz.h *****/</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">"foo.h"</span><span class="pln">

</span><span class="kwd">using</span><span class="pln"> </span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">Foo</span><span class="pun">;</span><span class="pln">
</span><span class="com">/***** main.cpp *****/</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">"bar.h"</span><span class="pln">

</span><span class="com">#include</span><span class="pln"> </span><span class="str">"baz.h"</span><span class="pln">

</span><span class="kwd">using</span><span class="pln"> </span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">Bar</span><span class="pun">;</span><span class="pln">
C c</span><span class="pun">;</span><span class="pln"> </span><span class="com">// Foo::C و  Bar::C خطأ: تضارب بين</span></pre>

<p>
	كما ترى، فلا يمكن استخدام الموجّه <code>using</code> في نطاق الصنف.
</p>

<h3>
	التصريح عبر using
</h3>

<p>
	عندما تصرّح عن كائنٍ ما باستخدام <code>‎using‎</code> فسيؤدّي ذلك إلى إدخال اسم سبق تصريحه في موضع آخر إلى النطاق الحالي.
</p>

<h4>
	استيراد الأسماء فرديًّا من فضاء اسم
</h4>

<p>
	انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8752_25" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">using</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">cout</span><span class="pun">;</span><span class="pln">
    cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Hello, worlبd!\n"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	عند استخدام <code>‎using‎</code> لإدخال الاسم <code>‎cout‎</code> من فضاء اسم <code>‎std‎</code> في نطاق دالّة <code>‎main‎</code>، سنتمكن من الإشارة إلى الكائن <code>std::cout</code> بالاسم <code>cout</code> فقط.
</p>

<h4>
	إعادة التصريح عن أعضاء صنف أساسي لتجنّب إخفاء الأسماء
</h4>

<p>
	لا يُسمح بإعادة تعريف الأعضاء خلا أعضاء الصنف الأساسي عند التصريح عن أعضاء عبر <code>using</code> في نطاق الصنف. على سبيل المثال، <code>‎using std::cout‎</code> غير مسموح بها في نطاق الصنف.
</p>

<p>
	الاسم المُعاد تصريحه كان سيُخفى غالبًا، على سبيل المثال، تشير <code>‎d1.foo‎</code> في المثال أدناه إلى <code>‎Derived1::foo(const char*)‎</code> وحسب، لذلك سيحدث خطأ في التصريف.
</p>

<p>
	مسألة أنّ الدالّة <code>‎Base::foo(int)‎</code> ستُخفى ليس لها تأثير. لكن من الناحية الأخرى فإن <code>‎d2.foo(42)‎</code> صحيحة لأنّ التصريح باستخدام <code>using</code> يُدرِج <code>‎Base::foo(int)‎</code> في مجموعة الكيانات المُسمّاة <code>‎foo‎</code> في <code>‎Derived2‎</code>. ستنتهي عملية البحث عن الأسماء بإيجاد كلا الدالّتين المُسمّاتين <code>‎foo‎</code>، وبعد تحليل زيادة التحميل (overload resolution)، يُختار <code>‎Base::foo‎</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8752_27" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">(</span><span class="typ">int</span><span class="pun">);</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Derived1</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Derived2</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">using</span><span class="pln"> </span><span class="typ">Base</span><span class="pun">::</span><span class="pln">foo</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Derived1</span><span class="pln"> d1</span><span class="pun">;</span><span class="pln">
    d1</span><span class="pun">.</span><span class="pln">foo</span><span class="pun">(</span><span class="lit">42</span><span class="pun">);</span><span class="pln"> </span><span class="com">// خطأ</span><span class="pln">
    </span><span class="typ">Derived2</span><span class="pln"> d2</span><span class="pun">;</span><span class="pln">
    d2</span><span class="pun">.</span><span class="pln">foo</span><span class="pun">(</span><span class="lit">42</span><span class="pun">);</span><span class="pln"> </span><span class="com">// صحيح</span><span class="pln">
</span><span class="pun">}</span></pre>

<h4>
	وراثة المُنشئات
</h4>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	كحالة خاصة، يمكن أن يشير استخدام <code>using</code> للتصريح في نطاق الصنف إلى مُنشئات (constructors) صنف أبٍ مباشر (direct base class)، ثم تُورَّث تلك المُنشئات إلى الصنف المشتقّ، ويمكن استخدامها لتهيئة ذلك الصنف. انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8752_29" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Base</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">,</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> s</span><span class="pun">);</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Derived1</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Derived1</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">,</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> s</span><span class="pun">):</span><span class="pln"> </span><span class="typ">Base</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> s</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Derived2</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">using</span><span class="pln"> </span><span class="typ">Base</span><span class="pun">::</span><span class="typ">Base</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Derived1</span><span class="pln"> d1</span><span class="pun">(</span><span class="lit">42</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Hello, world"</span><span class="pun">);</span><span class="pln">
    </span><span class="typ">Derived2</span><span class="pln"> d2</span><span class="pun">(</span><span class="lit">42</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Hello, world"</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	في الشيفرة أعلاه، يحتوي كل من <code>‎Derived1‎</code> و <code>‎Derived2‎</code> على مُنشئات تعيد توجيه الوسائط مباشرةً إلى المُنشئ المقابل للصنف <code>‎Base‎</code>. وينفّذ الصنف <code>‎Derived1‎</code> إعادة التوجيه بشكل صريح، بينما يستخدم الصنف <code>‎Derived2‎</code> ميزة توريث المُنشئات الموجودة في C++‎ 11 لفعل ذلك ضمنيًا.
</p>

<h2>
	إنشاء فضاءات الاسم
</h2>

<p>
	من السهل إنشاء فضاءات الاسم، انظر المثال التالي إذ سننشئ فضاء الاسم <code>foo</code> ثم نصرح عن الدالة <code>bar</code> فيه:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8752_31" style="">
<span class="kwd">namespace</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> bar</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لاستدعاء <code>‎bar‎</code>، يجب عليك تحديد فضاء الاسم أولاً، متبوعًا بعامل تحليل النطاق (scope resolution operator‏‏) وهو <code>‎::‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8752_33" style="">
<span class="typ">Foo</span><span class="pun">::</span><span class="pln">bar</span><span class="pun">();</span></pre>

<p>
	يُسمح بإنشاء فضاء اسمٍ داخل فضاء اسم آخر، مثلًا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8752_35" style="">
<span class="kwd">namespace</span><span class="pln"> A </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">namespace</span><span class="pln"> B </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">namespace</span><span class="pln"> C </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">void</span><span class="pln"> bar</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 17</strong>
</p>

<p>
	يمكن تبسيط الشيفرة أعلاه على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8752_37" style="">
<span class="kwd">namespace</span><span class="pln"> A</span><span class="pun">::</span><span class="pln">B</span><span class="pun">::</span><span class="pln">C </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> bar</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	فضاءات الاسم غير المُسمّاة أو المجهولة
</h2>

<p>
	يمكن استخدام فضاء اسم غير مُسمَّى (unnamed namespace) لضمان وجود ارتباط داخلي بين الأسماء التي لا يمكن الإشارة إليها إلّا بوحدة الترجمة الحالية (translation unit)، وتُعرّف فضاءات الاسم غير المسمّاة بنفس طريقة تعريف فضاءات الاسم الأخرى، ولكن من دون اسم:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8752_39" style="">
<span class="kwd">namespace</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> foo </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لن تكون <code>‎foo‎</code> مرئيّة إلّا في وحدة الترجمة التي تظهر فيها، ويوصى بعدم استخدام فضاءات-الاسم-غير-المُسمّاة في ملفات الترويسة (Header Files) لأنّ هذا سيعطي إصدارًا من المحتوى لكل وحدة ترجمة أُدرِج فيها، وهذا مهم جدًا خاصّة عند تعريف متغيرات-عامة-غير-ثابتة. انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8752_41" style="">
<span class="com">// foo.h</span><span class="pln">
</span><span class="kwd">namespace</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">string globalString</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// 1.cpp</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">"foo.h"</span><span class="pln"> </span><span class="com">//&lt; تولّد: unnamed_namespace{1.cpp}::globalString ...</span><span class="pln">

globalString </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Initialize"</span><span class="pun">;</span><span class="pln">

</span><span class="com">// 2.cpp</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">"foo.h"</span><span class="pln"> </span><span class="com">//&lt; تولّد: unnamed_namespace{2.cpp}::globalString ...</span><span class="pln">

std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> globalString</span><span class="pun">;</span><span class="pln"> </span><span class="com">//&lt; ستطبع دائما سلسلة نصية فارغة</span></pre>

<h2>
	فضاءات الاسم المضغوطة والمتشعبة
</h2>

<p>
	<strong>الإصدار ≥ C++‎ 17</strong>
</p>

<p>
	انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8752_43" style="">
<span class="kwd">namespace</span><span class="pln"> a </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">namespace</span><span class="pln"> b </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln">
            </span><span class="kwd">struct</span><span class="pln"> qualifies</span><span class="pun">:</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">false_type </span><span class="pun">{};</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">namespace</span><span class="pln"> other </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> bob </span><span class="pun">{};</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">namespace</span><span class="pln"> a</span><span class="pun">::</span><span class="pln">b </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
        </span><span class="kwd">struct</span><span class="pln"> qualifies </span><span class="pun">&lt;</span><span class="pln"> </span><span class="pun">::</span><span class="pln">other</span><span class="pun">::</span><span class="pln">bob </span><span class="pun">&gt;:</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">true_type </span><span class="pun">{};</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ابتداءً من C++‎ 17، صار بإمكانك الدخول إلى فضاء الاسم <code>‎a‎</code> و كذلك <code>‎b‎</code> بخطوة واحدة عبر التعبير <code>‎namespace a::b‎</code>.
</p>

<h2>
	كنية فضاء الاسم
</h2>

<p>
	يمكن إعطاء فضاء الاسم كُنيةً أو اسمًا بديلًا (alias)، أي اسمًا آخر يمثّل فضاء الاسم نفسه باستخدام الصيغة <code>‎namespace identifier =‎</code>، ويمكن الوصول إلى أعضاء فضاء الاسم المُكَنَّى عبر تأهيلهم (أي إسباقهم) بالكُنية.
</p>

<p>
	في المثال التالي، فضاء الاسم الُمتشعّب <code>‎AReallyLongName::AnotherReallyLongName‎</code> طويل جدًّا، لذا تصرح الدالّة <code>‎qux‎</code> عن الكُنية <code>‎N‎</code>. يمكن الآن الوصول إلى أعضاء فضاء الاسم باستخدام <code>‎N::‎</code>. انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8752_45" style="">
<span class="kwd">namespace</span><span class="pln"> </span><span class="typ">AReallyLongName</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">AnotherReallyLongName</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> foo</span><span class="pun">();</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> bar</span><span class="pun">();</span><span class="pln">
        </span><span class="kwd">void</span><span class="pln"> baz</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> y</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> qux</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">namespace</span><span class="pln"> N </span><span class="pun">=</span><span class="pln"> </span><span class="typ">AReallyLongName</span><span class="pun">::</span><span class="typ">AnotherReallyLongName</span><span class="pun">;</span><span class="pln">
    N</span><span class="pun">::</span><span class="pln">baz</span><span class="pun">(</span><span class="pln">N</span><span class="pun">::</span><span class="pln">foo</span><span class="pun">(),</span><span class="pln"> N</span><span class="pun">::</span><span class="pln">bar</span><span class="pun">());</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	فضاء الاسم المضمن (Inline namespace)
</h2>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	تُدرِج <code>‎inline ‎namespace‎</code> محتوى فضاء الاسم المُضمّن في فضاء الاسم المحيط (Enclosing)، لذلك فإنّ الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8752_47" style="">
<span class="kwd">namespace</span><span class="pln"> </span><span class="typ">Outer</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">inline</span><span class="pln"> </span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">Inner</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تكافئ بشكل كبير الشيفرة أدناه:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8752_49" style="">
<span class="kwd">namespace</span><span class="pln"> </span><span class="typ">Outer</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">Inner</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">using</span><span class="pln"> </span><span class="typ">Inner</span><span class="pun">::</span><span class="pln">foo</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	غير أن عناصر <code>‎Outer::Inner::‎</code> وعناصر <code>‎Outer::‎</code> متطابقة، لذلك فإن السَّطرن التالين متكافئان:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8752_51" style="">
<span class="typ">Outer</span><span class="pun">::</span><span class="pln">foo</span><span class="pun">();</span><span class="pln">
</span><span class="typ">Outer</span><span class="pun">::</span><span class="typ">Inner</span><span class="pun">::</span><span class="pln">foo</span><span class="pun">();</span></pre>

<p>
	لكنّ التعبير <code>‎using namespace Inner;‎</code> لن يكون مكافئًا لبعض الأجزاء مثل تخصيص القوالب (template specialization):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8752_53" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;outer.h&gt;</span><span class="pln"> </span><span class="com">// انظر أسفله</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">MyCustomType</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">Outer</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
        </span><span class="kwd">void</span><span class="pln"> foo </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">MyCustomType</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Specialization"</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يسمح فضاء الاسم المُضمَّن بتخصيص <code>‎Outer::foo‎</code>، انظر المثال التالي حيث أهملنا <code>include guard</code> من أجل التبسيط:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8752_55" style="">
<span class="com">// outer.h</span><span class="pln">
</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">Outer</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">inline</span><span class="pln"> </span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">Inner</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln">
            </span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Generic"</span><span class="pun">;</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	بينما لا يسمح التعبير <code>‎using namespace‎</code> بتخصيص <code>‎Outer::foo‎</code>، انظر أدناه أيضًا حيث أهملنا <code>include guard</code> من أجل التبسيط:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8752_57" style="">
<span class="com">// outer.h</span><span class="pln">
</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">Outer</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">Inner</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln">
            </span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Generic"</span><span class="pun">;</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">using</span><span class="pln"> </span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">Inner</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// `Outer::foo` لا يمكن تخصيص</span><span class="pln">
    </span><span class="com">// `Outer::Inner::foo` الصيغة الصحيحة هي</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تتيح فضاءات الاسم المُضمّنة لعدة إصدارات أن تتواجد في نفس الوقت بحيث تعود كلها افتراضيًّا إلى فضاء الاسم المُضمّن (<code>‎inline‎</code>):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8752_59" style="">
<span class="kwd">namespace</span><span class="pln"> </span><span class="typ">MyNamespace</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// تضمين الإصدار الأخير</span><span class="pln">
    </span><span class="kwd">inline</span><span class="pln"> </span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">Version2</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">();</span><span class="pln"> </span><span class="com">// إصدار جديد</span><span class="pln">
        </span><span class="kwd">void</span><span class="pln"> bar</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">Version1</span><span class="pln"> </span><span class="com">// الإصدار القديم</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ومع استخدام:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8752_61" style="">
<span class="typ">MyNamespace</span><span class="pun">::</span><span class="typ">Version1</span><span class="pun">::</span><span class="pln">foo</span><span class="pun">();</span><span class="pln"> </span><span class="com">// الإصدار القديم</span><span class="pln">
</span><span class="typ">MyNamespace</span><span class="pun">::</span><span class="typ">Version2</span><span class="pun">::</span><span class="pln">foo</span><span class="pun">();</span><span class="pln"> </span><span class="com">// الاصدار الجديد</span><span class="pln">
</span><span class="typ">MyNamespace</span><span class="pun">::</span><span class="pln">foo</span><span class="pun">();</span><span class="pln"> </span><span class="com">// MyNamespace::Version1::foo(); الاصدار الافتراضي</span></pre>

<h2>
	تكنية فضاء اسم طويل
</h2>

<p>
	من الممكن تكنِية فضاءات الاسم الطويلة في ++C، وهو مفيد مثلًا في حال أردت الإشارة إلى مكوّنات مكتبة ما. انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8752_63" style="">
<span class="kwd">namespace</span><span class="pln"> boost </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">namespace</span><span class="pln"> multiprecision </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Number</span><span class="pun">...</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">Name1</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> boost</span><span class="pun">::</span><span class="pln">multiprecision</span><span class="pun">;</span><span class="pln">

</span><span class="com">// كلا التصريحين متكافئين</span><span class="pln">
boost</span><span class="pun">::</span><span class="pln">multiprecision</span><span class="pun">::</span><span class="typ">Number</span><span class="pln"> X    </span><span class="com">// كتابة فضاء الاسم بأكمله</span><span class="pln">
</span><span class="typ">Name1</span><span class="pun">::</span><span class="typ">Number</span><span class="pln"> Y            </span><span class="com">// استخدام الكنية</span></pre>

<h2>
	نطاق تصريح الكنية
</h2>

<p>
	يتأثّر تصريح الكنية باستخدام تعليمات <code>using</code> الموجودة قبله:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8752_65" style="">
<span class="kwd">namespace</span><span class="pln"> boost </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">namespace</span><span class="pln"> multiprecision </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Number</span><span class="pun">...</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">using</span><span class="pln"> </span><span class="kwd">namespace</span><span class="pln"> boost</span><span class="pun">;</span><span class="pln">

</span><span class="com">// فضاءا الاسم متكافئان</span><span class="pln">
</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">Name1</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> boost</span><span class="pun">::</span><span class="pln">multiprecision</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">Name2</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> multiprecision</span><span class="pun">;</span></pre>

<p>
	لكن قد تكون عمليّة تكنية فضاء الاسم مربكة أحيانًا حول اختيار الفضاء الذي تريد وضع اسم بديل أو كنية له، كما في المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8752_67" style="">
<span class="kwd">namespace</span><span class="pln"> boost </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">namespace</span><span class="pln"> multiprecision </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Number</span><span class="pun">...</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">namespace</span><span class="pln"> numeric </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">namespace</span><span class="pln"> multiprecision </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Number</span><span class="pun">...</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">using</span><span class="pln"> </span><span class="kwd">namespace</span><span class="pln"> numeric</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="kwd">namespace</span><span class="pln"> boost</span><span class="pun">;</span></pre>

<p>
	لا يُنصح بهذا لأنه ليس واضحًا إن كان <code>Name1</code> يشير إلى <code>numeric::multiprecision</code> أم <code>boost::multiprecision</code>، نتابع:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8752_69" style="">
<span class="kwd">namespace</span><span class="pln"> </span><span class="typ">Name1</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> multiprecision</span><span class="pun">;</span><span class="pln">
</span><span class="com">// يُفضل استخدام المسار الكامل</span><span class="pln">
</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">Name2</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> numeric</span><span class="pun">::</span><span class="pln">multiprecision</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">Name3</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> boost</span><span class="pun">::</span><span class="pln">multiprecision</span><span class="pun">;</span></pre>

<p>
	هذا الدرس جزء من <a data-ss1617022522="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة دروس عن C++‎</a>.
</p>

<p>
	ترجمة -بتصرّف- للفصل Chapter 44: Namespaces والفصل Chapter 46: Using declaration من كتاب <a data-ss1617022522="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">938</guid><pubDate>Tue, 21 Jul 2020 13:01:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x62F;&#x648;&#x627;&#x644; &#x627;&#x644;&#x645;&#x636;&#x645;&#x646;&#x629; (Inline functions) &#x648;&#x627;&#x644;&#x62F;&#x648;&#x627;&#x644; &#x627;&#x644;&#x62A;&#x627;&#x628;&#x639;&#x629; (Member Functions) &#x641;&#x64A; Cpp</title><link>https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-%D8%A7%D9%84%D9%85%D8%B6%D9%85%D9%86%D8%A9-inline-functions-%D9%88%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-%D8%A7%D9%84%D8%AA%D8%A7%D8%A8%D8%B9%D8%A9-member-functions-%D9%81%D9%8A-cpp-r937/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_06/25.jpg.d31d4bc4d7ead054eeb1b51003b9c638.jpg" /></p>

<p>
	تُسمى الدوال المُعرّفة بالكلمة المفتاحية <code>‎inline‎</code> دوالًا مُضمّنة (inline functions)، ويمكن تعريفها أكثر من مرة دون انتهاك قاعدة التعريف الواحد (One Definition Rule)، وعليه يمكن تعريفها في الترويسة مع الارتباطات الخارجية.
</p>

<p>
	التصريح عن دالّة ما بأنها مضمّنة يُخبر المصرّف أنّ تلك الدالّة يجب أن تُضمَّن أثناء توليد الشِّيفرة البرمجية (لكنّ ذلك غير مضمون).
</p>

<h2>
	الدوال المضمنة
</h2>

<h3>
	تعريف الدوال غير التابعة المضمنة (Non-member inline function deﬁnition)
</h3>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_7" style="">
<span class="kwd">inline</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> add</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> y</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> x </span><span class="pun">+</span><span class="pln"> y</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	الدوال التابعة المضمنة (Member inline functions)
</h3>

<p>
	انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_9" style="">
<span class="com">// header (.hpp)</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> A </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> i_am_inlined</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> B </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> i_am_NOT_inlined</span><span class="pun">();</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="com">// source (.cpp)</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> B</span><span class="pun">::</span><span class="pln">i_am_NOT_inlined</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span></pre>

<p>
	<strong>ما المقصود بتضمين دالّة؟</strong>
</p>

<p>
	نظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_11" style="">
<span class="kwd">inline</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> add</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> y</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> x </span><span class="pun">+</span><span class="pln"> y</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> c </span><span class="pun">=</span><span class="pln"> add</span><span class="pun">(</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> b</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	في الشيفرة أعلاه، عندما تكون <code>‎add‎</code> مضمّنة، فستصبح الشيفرة الناتجة كما يلي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_13" style="">
<span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> c </span><span class="pun">=</span><span class="pln"> a </span><span class="pun">+</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لا يمكن رؤية الدالة المضمّنة إذ يُضمَّن متنها في متن المُستدعي، ولو لم يكن التابع <code>‎add‎</code> مضمّنًا، لاستدعيَت الدالّة. الحِمل الإضافي (overhead) الناتج عن استدعاء دالة -مثل إنشاء <a data-ss1617022520="1" href="https://s%20tackoverflow.com/questions/10057443/explain-the-concept-of-a-stack-frame-in-a-nutshell" rel="external nofollow">إطار مكدِّس</a> (stack frame) جديدة، ونسخ الوسائط، وإنشاء المتغيرات المحلية، وغير ذلك - سيكون مكلفًا.
</p>

<h3>
	التصريح عن الدوال المضمنة غير التابعة
</h3>

<p>
	يمكن التصريح عن الدوالّ المضّمنة غير التابعة على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_17" style="">
<span class="kwd">inline</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> add</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> y</span><span class="pun">);</span></pre>

<h2>
	الدوال التابعة الخاصة
</h2>

<h3>
	المنشئ الافتراضي (Default Constructor)
</h3>

<p>
	المُنشئ الافتراضي هو نوع من المُنشئات التي لا تتطلّب أيّ معاملات عند استدعائها وتُسمى باسم النوع الذي تنشئه، كما أنها تُعدّ دالة تابعة من توابعه، كما هو حال جميع المُنشئات.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_19" style="">
<span class="kwd">class</span><span class="pln"> C </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="com">// تعريف المنشئ الافتراضي</span><span class="pln">
        C</span><span class="pun">():</span><span class="pln"> i</span><span class="pun">(</span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">         </span><span class="com">// إلى 0  i قائمة تهيئة العضو، هيئ</span><span class="pln">
                </span><span class="com">// إنشاء جسم الدالّة -- يمكن فعل أشياء أكثر تعقيدا هنا</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

C c1</span><span class="pun">;</span><span class="pln"> 
C c2 </span><span class="pun">=</span><span class="pln"> C</span><span class="pun">();</span><span class="pln"> 
C c3</span><span class="pun">();</span><span class="pln">
C c4 </span><span class="pun">{};</span><span class="pln"> 
C c5</span><span class="pun">[</span><span class="lit">2</span><span class="pun">];</span><span class="pln">
C </span><span class="pun">*</span><span class="pln"> c6 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> C</span><span class="pun">[</span><span class="lit">2</span><span class="pun">];</span><span class="pln"> </span></pre>

<p>
	تحليل الشيفرة السابقة:
</p>

<ul>
<li>
		<code>C c1</code>: يستدعي منشئ C الافتراضي لإنشاء الكائن <code>c1</code>.
	</li>
	<li>
		<code>C c2</code>: يستدعي المنشئ الافتراضي صراحة.
	</li>
	<li>
		<code>C c3</code>: خطأ: هذا الإصدار غير ممكن بسبب غموض في التحليل، أو ما يعرف بمشكلة “The most vexing parse”.
	</li>
	<li>
		<code>C c4</code>: يمكن استخدام { } في C++ 11 بطريقة مماثلة.
	</li>
	<li>
		<code>C c5[2]‎</code>: يستدعي المنشئ الافتراضي على عنصري المصفوفة.
	</li>
	<li>
		<code>C * c6</code>: يستدعي المنشئ الافتراضي على عنصري المصفوفة.
	</li>
</ul>
<p>
	هناك طريقة أخرى للاستغناء عن تمرير المعاملات، وهي أن يوفّر المطوِّر قيمًا افتراضية لها جميعًا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_21" style="">
<span class="kwd">class</span><span class="pln"> D </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> j</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="com">// من الممكن أيضا استدعاء منشئ افتراضي بدون معاملات</span><span class="pln">
        D</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> j </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pun">):</span><span class="pln"> i</span><span class="pun">(</span><span class="pln">i</span><span class="pun">),</span><span class="pln"> j</span><span class="pun">(</span><span class="pln">j</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
D d</span><span class="pun">;</span><span class="pln"> </span><span class="com">// مع القيم الافتراضية للوسائط D استدعاء منشئ </span></pre>

<p>
	يوفر المصرِّف منشئًا افتراضيًا فارغًا بشكل ضمني في بعض الحالات، كأن يكون المطور لم يوفر منشئًا ولم تكن ثمة شروط مانعة أخرى.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_23" style="">
<span class="kwd">class</span><span class="pln"> C </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">string s</span><span class="pun">;</span><span class="pln"> </span><span class="com">// تحتاج الأعضاء إلى أن تكون قابلة للإنشاء</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
C c1</span><span class="pun">;</span><span class="pln"> </span><span class="com">// لها منشئ افتراضي معرّف ضمنيا C </span></pre>

<p>
	وجود نوع آخر من المنشئ هو أحد الشروط المانعة المذكورة سابقًا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_25" style="">
<span class="kwd">class</span><span class="pln"> C </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        C</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i</span><span class="pun">):</span><span class="pln"> i</span><span class="pun">(</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
C c1</span><span class="pun">;</span><span class="pln"> </span><span class="com">// ليس لها منشئ افتراضي ضمني C ،خطأ في التصريف</span></pre>

<p>
	<strong>الإصدار &lt;C++‎ 11</strong>
</p>

<p>
	إحدى الطرق الشائعة لمنع إنشاء مُنشئ افتراضي ضمني هي جعله خاصًّا <code>‎private‎</code> (بلا تعريف)، والهدف من ذلك هو إطلاق خطأ تصريفي في حال حاول شخص ما استخدام المنشئ، وينتج عن هذا إمّا خطأ في الوصول (Access to private error) أو خطأ ربط (linker error)، حسب نوع المصرّف.
</p>

<p>
	وللتأكد من أنّ مُنشئًا افتراضيًّا (مشابه وظيفيًا للمنشئ الضمني) قد تمّ تعريفه، يكتب المُطوِّر منشئًا فارغًا بشكل صريح.
</p>

<p>
	<strong>الإصدار C++‎ 11 </strong>
</p>

<p>
	في الإصدار C++‎ 11، يستطيع المطوّر أيضًا استخدام الكلمة المفتاحية <code>‎delete‎</code> لمنع المصرّف من توفير مُنشئ افتراضي.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_27" style="">
<span class="kwd">class</span><span class="pln"> C </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="com">// يُحذف المنشئ الافتراضي بشكل صريح</span><span class="pln">
        C</span><span class="pun">()</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">delete</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
C c1</span><span class="pun">;</span><span class="pln"> </span><span class="com">// C خطأ تصريفي: حذف منشئ</span></pre>

<p>
	أيضًا، إن أردت أن يوفرّ المصرّف مُنشئًا افتراضيًّا، فذلك يكون على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_30" style="">
<span class="kwd">class</span><span class="pln"> C </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="com">// توفير منشئ افتراضي تلقائيا</span><span class="pln">
        C</span><span class="pun">()</span><span class="pln"> </span><span class="pun">=</span><span class="pln">
        </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
    C</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i</span><span class="pun">):</span><span class="pln"> i</span><span class="pun">(</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
C c1</span><span class="pun">;</span><span class="pln"> </span><span class="com">// مُنشأة افتراضيا</span><span class="pln">
C c2</span><span class="pun">(</span><span class="lit">1</span><span class="pun">);</span><span class="pln"> </span><span class="com">// int مُنشأة عبر المنشئ</span></pre>

<p>
	<strong>الإصدار C++‎ 14 </strong>
</p>

<p>
	يمكنك تحديد ما إذا كان لنوعٍ ما مُنشئ افتراضي (أو أنه نوع أولي - primitive type) باستخدام
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_34" style="">
<span class="pun">‎</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_default_constructible from </span><span class="str">&lt;type_traits&gt;</span><span class="pun">‎</span></pre>

<p>
	إليك الشيفرة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_32" style="">
<span class="kwd">class</span><span class="pln"> C1 </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> C2 </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln"> C2</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> C3 </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln"> C3</span><span class="pun">(</span><span class="typ">int</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">using</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">cout</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">boolalpha</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">is_default_constructible</span><span class="pun">;</span><span class="pln">
cout </span><span class="pun">&lt;&lt;</span><span class="pln"> boolalpha </span><span class="pun">&lt;&lt;</span><span class="pln"> is_default_constructible </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln"> </span><span class="com">// true</span><span class="pln">
cout </span><span class="pun">&lt;&lt;</span><span class="pln"> boolalpha </span><span class="pun">&lt;&lt;</span><span class="pln"> is_default_constructible </span><span class="pun">&lt;</span><span class="pln"> C1 </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln"> </span><span class="com">// true</span><span class="pln">
cout </span><span class="pun">&lt;&lt;</span><span class="pln"> boolalpha </span><span class="pun">&lt;&lt;</span><span class="pln"> is_default_constructible </span><span class="pun">&lt;</span><span class="pln"> C2 </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln"> </span><span class="com">// true</span><span class="pln">
cout </span><span class="pun">&lt;&lt;</span><span class="pln"> boolalpha </span><span class="pun">&lt;&lt;</span><span class="pln"> is_default_constructible </span><span class="pun">&lt;</span><span class="pln"> C3 </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln"> </span><span class="com">// false</span></pre>

<p>
	<strong>الإصدار = C++‎ 11 </strong>
</p>

<p>
	في الإصدار C++‎ 11، من الممكن استخدام الإصدار غير الدّالي (non-functor) لـ <code>‎std::is_default_constructible‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_36" style="">
<span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> boolalpha </span><span class="pun">&lt;&lt;</span><span class="pln"> is_default_constructible</span><span class="pun">&lt;</span><span class="pln">C1</span><span class="pun">&gt;::</span><span class="pln">value </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln"> </span><span class="com">// true</span></pre>

<h3>
	المُدمِّر (Destructor)
</h3>

<p>
	المُدمّر هو دالّة بدون وسائط تُستدعى قُبيْل تدمير كائن مُعرّف من المستخدم (user-deﬁned object)، ويُسمّى باسم النوع الذي يدمِّره مسبوقًا بـ <code>‎~‎</code> .
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_38" style="">
<span class="kwd">class</span><span class="pln"> C </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pun">*</span><span class="pln"> is</span><span class="pun">;</span><span class="pln">
    string s</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        C</span><span class="pun">():</span><span class="pln"> is</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">int</span><span class="pun">[</span><span class="lit">10</span><span class="pun">])</span><span class="pln"> </span><span class="pun">{}~</span><span class="pln">C</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">// تعريف المُدمّر</span><span class="pln">
            </span><span class="kwd">delete</span><span class="pun">[]</span><span class="pln"> is</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> C_child</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> C </span><span class="pun">{</span><span class="pln">
    string s_ch</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        C_child</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}~</span><span class="pln">C_child</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln"> </span><span class="com">// مدمّر الصنف الفرعي</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    C c1</span><span class="pun">;</span><span class="pln"> 
    C c2</span><span class="pun">[</span><span class="lit">2</span><span class="pun">];</span><span class="pln">
    C</span><span class="pun">*</span><span class="pln"> c3 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> C</span><span class="pun">[</span><span class="lit">2</span><span class="pun">];</span><span class="pln">
    C_child c_ch</span><span class="pun">;</span><span class="pln"> 
    </span><span class="kwd">delete</span><span class="pun">[]</span><span class="pln"> c3</span><span class="pun">;</span><span class="pln"> 
</span><span class="pun">}</span><span class="pln"> </span><span class="com">// يتم تدمير المتغيرات التلقائية هنا</span></pre>

<p>
	تحليل الشيفرة السابقة:
</p>

<ul>
<li>
		<code>C c1</code>: استدعاء المدمر الافتراضي.
	</li>
	<li>
		<code>[C c2[2</code>: استدعاء المُدمّر الافتراضي على العنصرين.
	</li>
	<li>
		<code>[C* c3 = new C[2</code>: استدعاء المُدمّر الافتراضي على عنصرَي المصفوفة
	</li>
	<li>
		<code>C_child c_ch</code>: عند تدميره يستدعي مدمر <code>s_ch</code> من قاعدة C (ومن ثم، s)
	</li>
	<li>
		<code>delete[] c3</code>: يستدعي المدمرات على <code>[c3[0</code> و <code>[c3[1</code>.
	</li>
</ul>
<p>
	يوفر المصرِّف مدمرًا افتراضيًا بشكل ضمني في بعض الحالات، كأن يكون المطور لم يوفر مدمرًا ولم تكن ثمة شروط مانعة أخرى.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_40" style="">
<span class="kwd">class</span><span class="pln"> C </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
    string s</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    C</span><span class="pun">*</span><span class="pln"> c1 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> C</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">delete</span><span class="pln"> c1</span><span class="pun">;</span><span class="pln"> </span><span class="com">// له مُدمّر C </span><span class="pln">
</span><span class="pun">}</span></pre>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_42" style="">
<span class="kwd">class</span><span class="pln"> C </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> m</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
        </span><span class="pun">~</span><span class="pln">C</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln"> </span><span class="com">// لا يوجد مُدمّر عام</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> C_container </span><span class="pun">{</span><span class="pln">
    C c</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    C_container</span><span class="pun">*</span><span class="pln"> c_cont </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> C_container</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">delete</span><span class="pln"> c_cont</span><span class="pun">;</span><span class="pln"> </span><span class="com">// Compile ERROR: C has no accessible destructor</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<strong>الإصدار &gt; C++‎ 11</strong>
</p>

<p>
	في C++‎ 11، يستطيع المُطوِّر تغيير هذا السلوك عن طريق منع المُصرّف من توفير مدمِّر افتراضي.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_44" style="">
<span class="kwd">class</span><span class="pln"> C </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> m</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="pun">~</span><span class="pln">C</span><span class="pun">()</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">delete</span><span class="pun">;</span><span class="pln"> </span><span class="com">// لا يوجد مُدمّر ضمني</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f </span><span class="pun">{</span><span class="pln">
    C c1</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="com">// Compile ERROR: C has no destructor</span></pre>

<p>
	يمكنك أن تجعل المصرّف يوفّر مدمّرًا افتراضيًّا، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_46" style="">
<span class="kwd">class</span><span class="pln"> C </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> m</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="pun">~</span><span class="pln">C</span><span class="pun">()</span><span class="pln"> </span><span class="pun">=</span><span class="pln">
        </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    C c1</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="com">// بنجاح c1 لها مُدمّر وقد تم تدمير  C</span></pre>

<p>
	<strong>الإصدار&gt; C++‎ 11</strong>
</p>

<p>
	يمكنك تحديد ما إذا كان لنوعٍ ما مدمّرٌ ما (أو أنّه نوع أولي) باستخدام <code>‎std::is_destructible‎</code> من <code>&lt;type_traits&gt;</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_48" style="">
<span class="kwd">class</span><span class="pln"> C1 </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> C2 </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln"> </span><span class="pun">~</span><span class="pln">C2</span><span class="pun">()</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">delete</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> C3</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> C2 </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">cout</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">boolalpha</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">is_destructible</span><span class="pun">;</span><span class="pln">
cout </span><span class="pun">&lt;&lt;</span><span class="pln"> boolalpha </span><span class="pun">&lt;&lt;</span><span class="pln"> is_destructible </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln"> </span><span class="com">// true</span><span class="pln">
cout </span><span class="pun">&lt;&lt;</span><span class="pln"> boolalpha </span><span class="pun">&lt;&lt;</span><span class="pln"> is_destructible </span><span class="pun">&lt;</span><span class="pln"> C1 </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln"> </span><span class="com">// true</span><span class="pln">
cout </span><span class="pun">&lt;&lt;</span><span class="pln"> boolalpha </span><span class="pun">&lt;&lt;</span><span class="pln"> is_destructible </span><span class="pun">&lt;</span><span class="pln"> C2 </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln"> </span><span class="com">// false</span><span class="pln">
cout </span><span class="pun">&lt;&lt;</span><span class="pln"> boolalpha </span><span class="pun">&lt;&lt;</span><span class="pln"> is_destructible </span><span class="pun">&lt;</span><span class="pln"> C3 </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln"> </span><span class="com">// false</span></pre>

<h3>
	النسخ والمبادلة (Copy and swap)
</h3>

<p>
	إذا أردت كتابة صنف لإدارة الموارد فستحتاج إلى تنفيذ جميع الدوال التابعة الخاصّة (انظر <a data-ss1617022520="1" href="https://en.cppreference.com/w/cpp/language/rule_of_three" rel="external nofollow">قاعدة الثلاثة/خمسة/صفر</a>). والطريقة الأبسط لكتابة مُنشئ النسخ (copy constructor) وعامل الإسناد (assignment operator) هي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_50" style="">
<span class="pln">person</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> person </span><span class="pun">&amp;</span><span class="pln">other</span><span class="pun">):</span><span class="pln"> name</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">[</span><span class="pln">std</span><span class="pun">::</span><span class="pln">strlen</span><span class="pun">(</span><span class="pln">other</span><span class="pun">.</span><span class="pln">name</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">]),</span><span class="pln"> age</span><span class="pun">(</span><span class="pln">other</span><span class="pun">.</span><span class="pln">age</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">strcpy</span><span class="pun">(</span><span class="pln">name</span><span class="pun">,</span><span class="pln"> other</span><span class="pun">.</span><span class="pln">name</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

person</span><span class="pun">&amp;</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">person
    </span><span class="kwd">const</span><span class="pun">&amp;</span><span class="pln"> rhs</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">this</span><span class="pln"> </span><span class="pun">!=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">other</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">delete</span><span class="pun">[]</span><span class="pln"> name</span><span class="pun">;</span><span class="pln">
        name </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">[</span><span class="pln">std</span><span class="pun">::</span><span class="pln">strlen</span><span class="pun">(</span><span class="pln">other</span><span class="pun">.</span><span class="pln">name</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">];</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">strcpy</span><span class="pun">(</span><span class="pln">name</span><span class="pun">,</span><span class="pln"> other</span><span class="pun">.</span><span class="pln">name</span><span class="pun">);</span><span class="pln">
        age </span><span class="pun">=</span><span class="pln"> other</span><span class="pun">.</span><span class="pln">age</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="kwd">this</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لكنّ هذه المقاربة تعتريها بعض العيوب، فهي تفشل في ضمان الاعتراض القوي (strong exception guarantee) إذا أطلق <code>‎new[]‎</code> فسنكون قد محونا الموارد التي يملكها <code>‎this‎</code> سلفًا، ولن نستطيع استردادها.
</p>

<p>
	وهناك الكثير من التكرار في شيفرتي إنشاء النسخ (copy construction) وإسناد النسخ (copy assignment)، ولا ننسى كذلك التحقّق من الإسناد الذاتي (self-assignment) الذي يضيف حِملًا زائدًا إلى عملية النسخ عادة، لكنّه يبقى ضروريًّا.
</p>

<p>
	يمكننا استخدام أسلوب النسخ والمبادلة (copy-and-swap idiom) لتلبية ضمان الاستثناء القوي (strong exception guarantee) وتجنّب تكرار الشيفرة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_52" style="">
<span class="kwd">class</span><span class="pln"> person </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">char</span><span class="pun">*</span><span class="pln"> name</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> age</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="com">/* كل الدوالّ الأخرى */</span><span class="pln">
        </span><span class="kwd">friend</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> swap</span><span class="pun">(</span><span class="pln">person </span><span class="pun">&amp;</span><span class="pln"> lhs</span><span class="pun">,</span><span class="pln"> person </span><span class="pun">&amp;</span><span class="pln"> rhs</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">using</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">swap</span><span class="pun">;</span><span class="pln"> </span><span class="com">// enable ADL</span><span class="pln">
            swap</span><span class="pun">(</span><span class="pln">lhs</span><span class="pun">.</span><span class="pln">name</span><span class="pun">,</span><span class="pln"> rhs</span><span class="pun">.</span><span class="pln">name</span><span class="pun">);</span><span class="pln">
            swap</span><span class="pun">(</span><span class="pln">lhs</span><span class="pun">.</span><span class="pln">age</span><span class="pun">,</span><span class="pln"> rhs</span><span class="pun">.</span><span class="pln">age</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    person </span><span class="pun">&amp;</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">person rhs</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        swap</span><span class="pun">(</span><span class="pln"> </span><span class="pun">*</span><span class="kwd">this</span><span class="pun">,</span><span class="pln"> rhs</span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="kwd">this</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	إن عجبت من سبب نجاح الشيفرة السابقة، فانظر ما سيحدث حين يكون لدينا ما يلي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_54" style="">
<span class="pln">person p1 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">...;</span><span class="pln">
person p2 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">...;</span><span class="pln">
p1 </span><span class="pun">=</span><span class="pln"> p2</span><span class="pun">;</span></pre>

<p>
	أولاً، ننسخ <code>‎rhs‎</code> من <code>‎p2‎</code> (والذي لم يكن علينا تكراره هنا). لن يكون علينا فعل أيّ شيء في <code>‎operator=‎</code> في حال رفع اعتراض (throwing an exception) وسيبقى <code>‎p1‎</code> دون تغيير. بعد ذلك، سنُبادل الأعضاء بين <code>‎*this‎</code> و <code>‎rhs‎</code>، ثم سيخرُج <code>‎rhs‎</code> عن النطاق. ستُنظّف المواردَ الأصلية الخاصّة بالمؤشّر <code>this</code> ضمنيًا داخل العامل <code>‎operator=‎</code>من خلال المدمّر، والذي لم يكن علينا أن نكرره.
</p>

<p>
	حتى الإسناد الذاتي (self-assignment) سيعمل بلا مشاكل - لكنّه سيكون أقل كفاءة باستخدام النسخ والمبادلة (إذ يتطلّب تخصيصًا - allocation - وإلغاء تخصيص - deallocation - إضافي)، ولكن إذا كان هذا الأمر مستبعدًا، فلن يؤثّر على الأداء العامّ.
</p>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	تعمل الصيغة أعلاه كما هي بالنسبة لإسناد النقل (move assignment).
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_56" style="">
<span class="pln">p1 </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">move</span><span class="pun">(</span><span class="pln">p2</span><span class="pun">);</span></pre>

<p>
	هنا، ننقل/ننشئ <code>‎rhs‎</code> من <code>‎p2‎</code>، وتبقى الشيفرة الأخرى صالحة، فإذا كان صنفٌ ما قابلًا للنقل لكن غير قابل للنسخ، فلا داعي لحذف إسناد النسخ، لأنّ عامل الإسناد سيكون معطوبَ الصياغة بسبب مُنشئ النسخ المحذوف.
</p>

<h3>
	النقل والنسخ الضمني
</h3>

<p>
	اعلم أنّ التصريح عن مدمِّر يمنع المصرّف من إنشاء مُنشئات النقل (move constructors) وعوامل إسناد النقل (move assignment operators) ضمنيًّا، وتذكر في حال صرّحت بمدمّر أن تضيف التعريفات المناسبة لعمليات النقل.
</p>

<p>
	وسيؤدّي التصريح عن عمليات النقل إلى منع إنشاء عمليات النسخ، لذا يجب إضافتها هي أيضًا (إذا كانت كائنات هذا الصنف تحتاج إلى عمليات النسخ).
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_58" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Movable</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">virtual</span><span class="pun">~</span><span class="typ">Movable</span><span class="pun">()</span><span class="pln"> noexcept </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// المنشئ لن ينشئ هذا التعبير الخاطئ لأننا عرّفنا مُدمّرا</span><span class="pln">
    </span><span class="typ">Movable</span><span class="pun">(</span><span class="typ">Movable</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> noexcept </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">Movable</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Movable</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> noexcept </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// التصريح عن عمليات النقل سيمنع إنشاء عمليات النسخ إلا إن قمنا بتمكين ذلك صراحة</span><span class="pln">
    </span><span class="typ">Movable</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Movable</span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">Movable</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Movable</span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span></pre>

<h2>
	الدوال التابعة غير الساكنة (Non-static member functions)
</h2>

<p>
	من الممكن أن يكون للأصناف (<code>‎class‎</code>) والبنيات (<code>‎struct‎</code>) دوال تابعة أو متغيرات عضوية، وصياغة الدوالّ التابعة تشبه صياغة الدوالّ المستقلة، ويمكن تعريفها إمّا داخل الصنف أو خارجه، فإذا عُرِّفت خارج تعريف الصنف فإنّ اسم الدالّة سيُسبَق باسمِ الصنف ومعامل النطاق (<code>‎::‎</code>).
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_60" style="">
<span class="kwd">class</span><span class="pln"> CL </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> definedInside</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> definedOutside</span><span class="pun">();</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> CL</span><span class="pun">::</span><span class="pln">definedOutside</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span></pre>

<p>
	تُستدعى هذه الدوالّ على نسخة (أو مرجع إلى نسخة) من الصنف باستخدام العامل النُّقَطي (dot operator -‏‏ (<code>‎.‎</code>))، أو مؤشّر إلى نسخة باستخدام عامل السهم (arrow operator -‏‏ (<code>‎-&gt;‎</code>))، ويرتبط كل استدعاء بالنسخة التي استُدعِيت عليها الدالّة.
</p>

<p>
	وعندما يُستدعى تابع على نسخة فسيكون له حقّ الوصول إلى كافّة حقول تلك النسخة (عبر المؤشّر <code>‎this‎</code>)، ولكن لا يمكنه الوصول إلى حقول النسخ الأخرى إلا إذا مُرِّرت كمعاملات.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_62" style="">
<span class="kwd">struct</span><span class="pln"> ST </span><span class="pun">{</span><span class="pln">
    ST</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&amp;</span><span class="pln"> ss </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Wolf"</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> ii </span><span class="pun">=</span><span class="pln"> </span><span class="lit">359</span><span class="pun">):</span><span class="pln"> s</span><span class="pun">(</span><span class="pln">ss</span><span class="pun">),</span><span class="pln"> i</span><span class="pun">(</span><span class="pln">ii</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> get_i</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">bool</span><span class="pln"> compare_i</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> ST </span><span class="pun">&amp;</span><span class="pln"> other</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="pln">i </span><span class="pun">==</span><span class="pln"> other</span><span class="pun">.</span><span class="pln">i</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">string s</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
ST st1</span><span class="pun">;</span><span class="pln">
ST st2</span><span class="pun">(</span><span class="str">"Species"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8472</span><span class="pun">);</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> st1</span><span class="pun">.</span><span class="pln">get_i</span><span class="pun">();</span><span class="pln">            </span><span class="com">// st2.i ولكن ليس إلى st1.i يمكن الوصول إلى </span><span class="pln">
</span><span class="kwd">bool</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> st1</span><span class="pun">.</span><span class="pln">compare_i</span><span class="pun">(</span><span class="pln">st2</span><span class="pun">);</span><span class="pln">    </span><span class="com">// st1 و  st2 يمكن الوصول إلى</span></pre>

<p>
	يُسمح لهذه الدوالّ بالوصول إلى الحقول و/أو التوابع الأخرى بغضّ النظر عن مُحدِّدات الوصول (access modifiers) الخاصّة بالمتغيرات والتوابع. كذلك يمكن كتابتها والوصول إلى الحقول و/أو استدعاء التوابع المُصرّحة قبلها، إذ يجب تحليل تعريف الصنف بأكمله قبل أن يبدأ المصرّف في تصريفه.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_64" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Access</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">Access</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i_ </span><span class="pun">=</span><span class="pln"> </span><span class="lit">8088</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> j_ </span><span class="pun">=</span><span class="pln"> </span><span class="lit">8086</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> k_ </span><span class="pun">=</span><span class="pln"> </span><span class="lit">6502</span><span class="pun">):</span><span class="pln"> i</span><span class="pun">(</span><span class="pln">i_</span><span class="pun">),</span><span class="pln"> j</span><span class="pun">(</span><span class="pln">j_</span><span class="pun">),</span><span class="pln"> k</span><span class="pun">(</span><span class="pln">k_</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> get_k</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> k</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">bool</span><span class="pln"> private_no_more</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> i_be_private</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> j</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> get_i</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> k</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> get_j</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> j</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">bool</span><span class="pln"> i_be_private</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">((</span><span class="pln">i </span><span class="pun">&gt;</span><span class="pln"> j</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">k </span><span class="pun">&lt;</span><span class="pln"> j</span><span class="pun">));</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<h2>
	التغليف (Encapsulation)
</h2>

<p>
	هُنالك عدّة استعمالات للتوابع، من ذلك أنها تُستخدم للتغليف (encapsulation)، وذلك باستخدام جالِب (getter) ومُعيِّن (setter) بدلاً من السماح بالوصول إلى الحقول مباشرة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_66" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Encapsulator</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> encapsulated</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> get_encapsulated</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> encapsulated</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> set_encapsulated</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> e</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        encapsulated </span><span class="pun">=</span><span class="pln"> e</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> some_func</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        do_something_with</span><span class="pun">(</span><span class="pln">encapsulated</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	يمكن الوصول إلى الحقل <code>‎encapsulated‎</code> داخل الصنف من قِبل أيّ دالة تابعة غير ساكنة، أمّا خارج الصنف، فيُنظّم حق الوصول إليه بواسطة الدوال التابعة إذ يُستخدم <code>‎get_encapsulated()‎</code> لقراءته و <code>‎set_encapsulated()‎</code> لتعديله، هذا يمنع التعديلات غير المقصودة على المتغيّر (هناك العديد من النقاشات حول ما إذا كانت الجوالب والمعيّنات تدعم التغليف أم تكسره، ولكلٍّ من الطرفين وجهة نظرة وجيهة).
</p>

<h2>
	إخفاء الأسماء واستيرادها
</h2>

<p>
	عندما يوفّر صنف أساسي مجموعة من الدوالّ زائدة التحميل (overloaded functions)، ثم يضيف صنفٌ مشتق تحميلًا زائدًا آخر إلى المجموعة، فإنّ ذلك سيخفي كل التحميلات الزائدة الخاصّة بالصنف الأساسي.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_68" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">HiddenBase</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="typ">int</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"int"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="kwd">bool</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"bool"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"std::string"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">HidingDerived</span><span class="pun">:</span><span class="pln"> </span><span class="typ">HiddenBase</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="typ">float</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"float"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="com">// ...</span><span class="pln">
</span><span class="typ">HiddenBase</span><span class="pln"> hb</span><span class="pun">;</span><span class="pln">
</span><span class="typ">HidingDerived</span><span class="pln"> hd</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">string s</span><span class="pun">;</span><span class="pln">
hb</span><span class="pun">.</span><span class="pln">f</span><span class="pun">(</span><span class="lit">1</span><span class="pun">);</span><span class="pln"> </span><span class="com">// الخرج:  int</span><span class="pln">
hb</span><span class="pun">.</span><span class="pln">f</span><span class="pun">(</span><span class="kwd">true</span><span class="pun">);</span><span class="pln"> </span><span class="com">// الخرج: bool</span><span class="pln">
hb</span><span class="pun">.</span><span class="pln">f</span><span class="pun">(</span><span class="pln">s</span><span class="pun">);</span><span class="pln"> </span><span class="com">// الخرج: std::string;</span><span class="pln">
hd</span><span class="pun">.</span><span class="pln">f</span><span class="pun">(</span><span class="lit">1.</span><span class="pln"> f</span><span class="pun">);</span><span class="pln"> </span><span class="com">// الخرج: float</span><span class="pln">
hd</span><span class="pun">.</span><span class="pln">f</span><span class="pun">(</span><span class="lit">3</span><span class="pun">);</span><span class="pln"> </span><span class="com">// الخرج: float</span><span class="pln">
hd</span><span class="pun">.</span><span class="pln">f</span><span class="pun">(</span><span class="kwd">true</span><span class="pun">);</span><span class="pln"> </span><span class="com">// الخرج: float</span><span class="pln">
hd</span><span class="pun">.</span><span class="pln">f</span><span class="pun">(</span><span class="pln">s</span><span class="pun">);</span><span class="pln"> </span><span class="com">// Error: Can't convert from std::string to float.</span></pre>

<p>
	هذا السلوك ناتج عن قواعد تحليل الاسم (name resolution rules): فأثناء البحث عن الاسم، يتوقف البحث بمجّرد العثور على الاسم الصحيح حتى لو لم يُعثَر على الإصدار الصحيح للكيان الذي يحمل ذلك الاسم (مثل <code>‎hd.f(s)‎</code>)، ونتيجة لهذا، تؤدي زيادة تحميل دالّة في الصنف المشتق إلى منع الوصول إلى التحميل الزائد الموجود في الصنف الأساسي. ولكي لتجنّب ذلك، يمكن استخدام <code>using</code> لأجل "استيراد" الأسماء من الصنف الأساسي إلى الصنف المشتق حتى تكون متاحة أثناء البحث عن الاسم. انظر المثال التالي حيث يجب أن تُعد جميع الأعضاء المسمّاة <code>HiddenBase::f</code> أعضاءً من <code>HidingDerived</code> أثناء البحث:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_70" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">HidingDerived</span><span class="pun">:</span><span class="pln"> </span><span class="typ">HiddenBase</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">using</span><span class="pln"> </span><span class="typ">HiddenBase</span><span class="pun">::</span><span class="pln">f</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="typ">float</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"float"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="com">// ...</span><span class="pln">
</span><span class="typ">HidingDerived</span><span class="pln"> hd</span><span class="pun">;</span><span class="pln">
hd</span><span class="pun">.</span><span class="pln">f</span><span class="pun">(</span><span class="lit">1.</span><span class="pln"> f</span><span class="pun">);</span><span class="pln"> </span><span class="com">//  الخرج: float</span><span class="pln">
hd</span><span class="pun">.</span><span class="pln">f</span><span class="pun">(</span><span class="lit">3</span><span class="pun">);</span><span class="pln"> </span><span class="com">// الخرج: int</span><span class="pln">
hd</span><span class="pun">.</span><span class="pln">f</span><span class="pun">(</span><span class="kwd">true</span><span class="pun">);</span><span class="pln"> </span><span class="com">// الخرج:  bool</span><span class="pln">
hd</span><span class="pun">.</span><span class="pln">f</span><span class="pun">(</span><span class="pln">s</span><span class="pun">);</span><span class="pln"> </span><span class="com">// الخرج: std::string</span></pre>

<p>
	إذ كان الصنف المشتق يستورد الأسماء باستخدام <code>using</code> ولكن يُصرّح كذلك عن دوالّ لها نفس بصمات الدوالّ في الصنف الأساسي، فسيُعاد تعريف دوالّ الصنف الأساسي بصمت أو تُخفى.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_72" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">NamesHidden</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">virtual</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> hide_me</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="kwd">virtual</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> hide_me</span><span class="pun">(</span><span class="typ">float</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> hide_me</span><span class="pun">(</span><span class="typ">int</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> hide_me</span><span class="pun">(</span><span class="kwd">bool</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">NameHider</span><span class="pun">:</span><span class="pln"> </span><span class="typ">NamesHidden</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">using</span><span class="pln"> </span><span class="typ">NamesHidden</span><span class="pun">::</span><span class="pln">hide_me</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> hide_me</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln"> </span><span class="com">// NamesHidden::hide_me() إعادة تعريف</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> hide_me</span><span class="pun">(</span><span class="typ">int</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln"> </span><span class="com">// NamesHidden::hide_me(int) إخفاء</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	يمكن أيضًا استخدام تصريح <code>using</code> لتغيير معدِّلات الوصول (Access Modifiers)، بشرط أن يكون الكيان المستورد إمّا عامًّا (<code>‎public‎</code>) أو محميًا (<code>‎protected‎</code>) في الصنف الأساسي.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_74" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">ProMem</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> func</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">BecomesPub</span><span class="pun">:</span><span class="pln"> </span><span class="typ">ProMem</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">using</span><span class="pln"> </span><span class="typ">ProMem</span><span class="pun">::</span><span class="pln">func</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="com">// ...</span><span class="pln">
</span><span class="typ">ProMem</span><span class="pln"> pm</span><span class="pun">;</span><span class="pln">
</span><span class="typ">BecomesPub</span><span class="pln"> bp</span><span class="pun">;</span><span class="pln">
pm</span><span class="pun">.</span><span class="pln">func</span><span class="pun">();</span><span class="pln"> </span><span class="com">// خطأ: محميّ</span><span class="pln">
bp</span><span class="pun">.</span><span class="pln">func</span><span class="pun">();</span><span class="pln"> </span><span class="com">// جيد</span></pre>

<p>
	وبالمثل إذا أردنا استدعاء دالة تابعة من صنف محدد في التسلسل الهرمي الوراثي (inheritance hierarchy) بشكل صريح، فيمكننا تأهيل اسم الدالّة عند استدعائها، وتحديد ذلك الصنف بالاسم.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_76" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">One</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">virtual</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"One."</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Two</span><span class="pun">:</span><span class="pln"> </span><span class="typ">One</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">()</span><span class="pln"> override </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">One</span><span class="pun">::</span><span class="pln">f</span><span class="pun">();</span><span class="pln"> </span><span class="com">// this-&gt;One::f();</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Two."</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Three</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Two</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">()</span><span class="pln"> override </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Two</span><span class="pun">::</span><span class="pln">f</span><span class="pun">();</span><span class="pln"> </span><span class="com">// this-&gt;Two::f();</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Three."</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="com">// ...</span><span class="pln">

</span><span class="typ">Three</span><span class="pln"> t</span><span class="pun">;</span><span class="pln">

t</span><span class="pun">.</span><span class="pln">f</span><span class="pun">();</span><span class="pln"> 
t</span><span class="pun">.</span><span class="typ">Two</span><span class="pun">::</span><span class="pln">f</span><span class="pun">();</span><span class="pln">
t</span><span class="pun">.</span><span class="typ">One</span><span class="pun">::</span><span class="pln">f</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تحليل الشيفرة السابقة:
</p>

<ul>
<li>
		<code>()t.f</code>: الصيغة العادية.
	</li>
	<li>
		<code>()t.Two::f</code>: استدعاء إصدار <code>()f</code> المعرَّف في Two.
	</li>
	<li>
		<code>()t.One::f</code>: استدعاء إصدار <code>()f</code> المعرَّف في One.
	</li>
</ul>
<h2>
	الدوال التابعة الوهميّة
</h2>

<p>
	الدوال التوابع يمكن أن تكون وهمية (<code>‎virtual‎</code>)، وإن استُدعِيت على مؤشّر أو مرجع إلى نسخة فلن يتم الوصول إليها مباشرة، بل سيُبحَث عن الدالّة في جدول الدوالّ الوهمية (قائمة من المؤشّرات-إلى-الدوال التابعة التي تشير إلى الدوالّ الوهمية، والمعروفة باسم <code>‎vtable‎</code> أو <code>‎vftable‎</code>)، ثم تُستخدَم لاستدعاء الإصدار المناسب للنوع (الفعلي) الديناميكي للنسخة. ولن يتم أي بحث إذا استُدعيت الدالّة مباشرة من متغير داخل صنف ما.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_78" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">virtual</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> func</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"In Base."</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Derived</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> func</span><span class="pun">()</span><span class="pln"> override </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"In Derived."</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> slicer</span><span class="pun">(</span><span class="typ">Base</span><span class="pln"> x</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    x</span><span class="pun">.</span><span class="pln">func</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="com">// ...</span><span class="pln">
</span><span class="typ">Base</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
</span><span class="typ">Derived</span><span class="pln"> d</span><span class="pun">;</span><span class="pln">
</span><span class="typ">Base</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> pb </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> b</span><span class="pun">,</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> pd </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> d</span><span class="pun">;</span><span class="pln"> </span><span class="com">// مؤشّرات</span><span class="pln">
</span><span class="typ">Base</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> rb </span><span class="pun">=</span><span class="pln"> b</span><span class="pun">,</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> rd </span><span class="pun">=</span><span class="pln"> d</span><span class="pun">;</span><span class="pln"> </span><span class="com">// مراجع</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

b</span><span class="pun">.</span><span class="pln">func</span><span class="pun">();</span><span class="pln"> </span><span class="com">// الخرج: In Base.</span><span class="pln">
d</span><span class="pun">.</span><span class="pln">func</span><span class="pun">();</span><span class="pln"> </span><span class="com">// الخرج: In Derived.</span><span class="pln">

pb </span><span class="pun">-&gt;</span><span class="pln"> func</span><span class="pun">();</span><span class="pln"> </span><span class="com">// الخرج: In Base.</span><span class="pln">
pd </span><span class="pun">-&gt;</span><span class="pln"> func</span><span class="pun">();</span><span class="pln"> </span><span class="com">// الخرج: In Derived.</span><span class="pln">

rb</span><span class="pun">.</span><span class="pln">func</span><span class="pun">();</span><span class="pln"> </span><span class="com">// الخرج: In Base.</span><span class="pln">
rd</span><span class="pun">.</span><span class="pln">func</span><span class="pun">();</span><span class="pln"> </span><span class="com">// الخرج: In Derived.</span><span class="pln">

slicer</span><span class="pun">(</span><span class="pln">b</span><span class="pun">);</span><span class="pln"> </span><span class="com">// الخرج: In Base.</span><span class="pln">
slicer</span><span class="pun">(</span><span class="pln">d</span><span class="pun">);</span><span class="pln"> </span><span class="com">// الخرج: In Base.</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ورغم أن <code>‎pd‎</code> من النوع <code>‎Base*‎</code> و<code>‎rd‎</code> من النّوع <code>‎Base&amp;‎</code>، إلا أن استدعاء <code>‎func()‎</code> على أيّ منهما سيؤدّي إلى استدعاء <code>‎Derived::func()‎</code> بدلاً من <code>Base::func()‎</code>؛ وذلك لأنّ جدول <code>‎vtable‎</code> الخاصّ بالبنية <code>‎Derived‎</code> يُحدِّث المدخل <code>‎Base::func()‎</code> بدلاً من الإشارة إلى <code>‎Derived::func()‎</code>.
</p>

<p>
	ومن ناحية أخرى، لاحظ كيف يؤدّي تمرير نسخة إلى <code>‎slicer()‎</code> إلى استدعاء <code>‎Base::func()‎</code> حتى عندما تكون النسخة المُمرَّرة من نوع <code>‎Derived‎</code>، وهذا بسبب مفهوم يُعرف بتشريح البيانات (Data Slicing)، وفيه يؤدّي تمرير نسخة من <code>‎Derived‎</code> إلى مُعامل من النوع <code>‎Base‎</code> بالقيمة (by value) إلى عرض ذلك الجزء من <code>‎Derived‎</code> الذي يمكنه الوصول إلى نسخة <code>Base</code>.
</p>

<p>
	حين تُعرَّف دالة تابعة على أنّها وهمية فإنّ جميع دوال الصنف التابعة المشتقة التي تحمل نفس البصمة ستعيد تعريفه (override) بغضّ النظر عمّا إذا كانت الدالّة التي أعادت تعريفه وهمية أم لا، هذا سيُصعِّب عملية تحليل الأصناف المشتقّة على المبرمجين لعدم وجود أيّ إشارة تحدّد أيٌّ من تلك دوالّ وهمية.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_80" style="">
<span class="kwd">struct</span><span class="pln"> B </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">virtual</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> D</span><span class="pun">:</span><span class="pln"> B </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln"> </span><span class="com">// B::f وهمية بشكل ضمني، إعادة تعريف</span><span class="pln">
    </span><span class="com">// B لكن عليك التحقق من</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	لاحظ أنّ الدالّة مشتقة (Derived Function) لا يمكنها أن تعيد تعريف دالّة أساسية (Base Function) إلا إذا تطابقت بصماتهما، حتى لو صُرِّح بأنّ الدالّة المشتقة وهمية (<code>‎virtual‎</code>)، فستنشئ دالّةً وهمية جديدة إن لم لتطابق البصمات.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_82" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">BadB</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">virtual</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">BadD</span><span class="pun">:</span><span class="pln"> </span><span class="typ">BadB</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">virtual</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln"> </span><span class="com">// BadB::f لا تُعِد تعريف</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	اعتبارًا من الإصدار C++‎ 11، يمكن التصريح بنِيَّة إعادة التعريف (override) باستخدام الكلمة المفتاحية <code>‎override‎</code>، واعلم أن هذه الكلمة حساسة للسياق، وسيخبر ذلك المصرّف أنّ المبرمج يتوقع منه أن يعيد تعريف دالّة الصنف الأساسي، وعليه يطلق المصرِّف خطأً إذا لم تحدث عملية إعادة التعريف.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_84" style="">
<span class="kwd">struct</span><span class="pln"> CPP11B </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">virtual</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> CPP11D</span><span class="pun">:</span><span class="pln"> CPP11B </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">()</span><span class="pln"> override </span><span class="pun">{}</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i</span><span class="pun">)</span><span class="pln"> override </span><span class="pun">{}</span><span class="pln"> </span><span class="com">// Error: Doesn't actually override anything.</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	وفائدة هذا أنه يخبر المبرمجين بأنّ الدالّة وهمية، وأنها كذلك مُصرَّحة في صنف أساسي واحد على الأقل، مما يسهّل تحليل الأصناف المعقّدة.
</p>

<p>
	يجب تضمين المُحدِّد <code>‎virtual‎</code> في تصريح الدالّة وعدم تكراره في التعريف عند التصريح بأنّ دالّة ما وهمية <code>‎virtual‎</code> وتكون معرَّفة خارج تعريف الصنف.
</p>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	ينطبق هذا أيضًا على الكلمة المفتاحية <code>‎override‎</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_86" style="">
<span class="kwd">struct</span><span class="pln"> VB </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">virtual</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">();</span><span class="pln"> </span><span class="com">// هنا "virtual" ضع</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> g</span><span class="pun">();</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="com">/* virtual */</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> VB</span><span class="pun">::</span><span class="pln">f</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln"> </span><span class="com">// لكن ليس هنا</span><span class="pln">
</span><span class="kwd">virtual</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> VB</span><span class="pun">::</span><span class="pln">g</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln"> </span><span class="com">// خطأ </span></pre>

<p>
	وإن نفذ الصنف الأساسي <a data-ss1617022520="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-22-%D8%A7%D9%84%D8%AA%D8%AD%D9%85%D9%8A%D9%84-%D8%A7%D9%84%D8%B2%D8%A7%D8%A6%D8%AF-overloading-%D8%AA%D8%AD%D9%84%D9%8A%D9%84%D9%87-%D9%88%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D9%87-%D8%B9%D9%84%D9%89-%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-%D9%81%D9%8A-cpp-r934/" rel="">زيادة تحميل</a> على دالّة وهمية، فإن التحميلات التي حُدِّدَت على أنها وهمية بشكل صريح هي وحدها التي ستكون وهمية.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_88" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">BOverload</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">virtual</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> func</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> func</span><span class="pun">(</span><span class="typ">int</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">DOverload</span><span class="pun">:</span><span class="pln"> </span><span class="typ">BOverload</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> func</span><span class="pun">()</span><span class="pln"> override </span><span class="pun">{}</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> func</span><span class="pun">(</span><span class="typ">int</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="com">// ...</span><span class="pln">
</span><span class="typ">BOverload</span><span class="pun">*</span><span class="pln"> bo </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">DOverload</span><span class="pun">;</span><span class="pln">
bo </span><span class="pun">-</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> func</span><span class="pun">();</span><span class="pln"> </span><span class="com">// DOverload::func() استدعاء</span><span class="pln">
bo </span><span class="pun">-</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> func</span><span class="pun">(</span><span class="lit">1</span><span class="pun">);</span><span class="pln"> </span><span class="com">// BOverload::func(int) استدعاء</span></pre>

<h2>
	الثباتية (Const Correctness)
</h2>

<p>
	أحد الاستخدامات الرئيسية لمؤهلات المؤشّر <code>‎this‎</code> هو الصحة الثباتية، أو الثباتية باختصار (const correctness). تضمن هذه الممارسة عدم تعديل الكائن إلا عند الحاجة لهذا، وأنّ أيّ دالّة (عضوة أو غير عضوة) لا تحتاج إلى تعديل كائن ما لن تملك حق الكتابة في ذلك الكائن (سواء بشكل مباشر أو غير مباشر). هذا يمنع التعديلات غير المقصودة مما يجعل الشيفرة أكثر متانة، كما يسمح لأيّ دالّة لا تحتاج إلى تعديل الحالة لأن تقبل الكائنات سواء كانت ثابتة (<code>‎const‎</code>) أو غير ثابتة دون الحاجة إلى إعادة كتابة أو تحميل الدالّة.
</p>

<p>
	تبدأ الثباتية من أسفل إلى أعلى، وذلك بسبب طبيعتها، إذ تُصرَّح أيّ دالة تابعة في الصنف لا تحتاج إلى تغيير الحالة على أنها ثابتة (<code>‎const‎</code>)، وذلك كي يمكنَ استدعاؤها على النسخ الثابتة. هذا يسمح بدوره بالتصريح أنّ المُعاملات المُمرّرة بالمرجع (passed-by-reference) ثابتة عندما لا تكون هناك حاجة إلى تعديلها، ممّا يسمح للدوالّ بأخذ كائنات ثابتة أو غير ثابتة دون مشاكل، كما يمكن للثباتيّة أن تنتشر للخارج بهذه الطريقة. وتكون الجالبات (Getters) ثابتة كأي دالّة أخرى لا تحتاج إلى تعديل حالة الكائن المنطقية.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_90" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">ConstIncorrect</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Field</span><span class="pln"> fld</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">ConstIncorrect</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Field</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> f</span><span class="pun">):</span><span class="pln"> fld</span><span class="pun">(</span><span class="pln">f</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln"> </span><span class="com">// تعديل</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Field</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> get_field</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> fld</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln"> </span><span class="com">// لا يوجد تعديل، ينبغي أن تكون ثابتة</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> set_field</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Field</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> f</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        fld </span><span class="pun">=</span><span class="pln"> f</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln"> </span><span class="com">// تعديل</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> do_something</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">// تعديل</span><span class="pln">
        fld</span><span class="pun">.</span><span class="pln">insert_value</span><span class="pun">(</span><span class="pln">i</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> do_nothing</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln"> </span><span class="com">// لا يوجد تعديل، ينبغي أن تكون ثابتة</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">ConstCorrect</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Field</span><span class="pln"> fld</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">ConstCorrect</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Field</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> f</span><span class="pun">):</span><span class="pln"> fld</span><span class="pun">(</span><span class="pln">f</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln"> </span><span class="com">// غير ثابتة: يمكن التعديل</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Field</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> get_field</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> fld</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln"> </span><span class="com">// ثابتة: لا يمكن التعديل</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> set_field</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Field</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> f</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        fld </span><span class="pun">=</span><span class="pln"> f</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln"> </span><span class="com">// غير ثابتة: يمكن التعديل</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> do_something</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">// غير ثابتة: يمكن التعديل</span><span class="pln">
        fld</span><span class="pun">.</span><span class="pln">insert_value</span><span class="pun">(</span><span class="pln">i</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> do_nothing</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{}</span><span class="pln"> </span><span class="com">// ثابتة: لا يمكن التعديل</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="com">// ...</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">ConstIncorrect</span><span class="pln"> i_cant_do_anything</span><span class="pun">(</span><span class="pln">make_me_a_field</span><span class="pun">());</span><span class="pln">
</span><span class="typ">Field</span><span class="pln"> f </span><span class="pun">=</span><span class="pln"> i_cant_do_anything</span><span class="pun">.</span><span class="pln">get_field</span><span class="pun">();</span><span class="pln">
</span><span class="com">// ليست ثابتة get_field() ،خطأ</span><span class="pln">
i_cant_do_anything</span><span class="pun">.</span><span class="pln">do_nothing</span><span class="pun">();</span><span class="pln">
</span><span class="com">// خطأ كالأعلى</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">ConstCorrect</span><span class="pln"> but_i_can</span><span class="pun">(</span><span class="pln">make_me_a_field</span><span class="pun">());</span><span class="pln">
</span><span class="typ">Field</span><span class="pln"> f </span><span class="pun">=</span><span class="pln"> but_i_can</span><span class="pun">.</span><span class="pln">get_field</span><span class="pun">();</span><span class="pln"> </span><span class="com">//جيد </span><span class="pln">
but_i_can</span><span class="pun">.</span><span class="pln">do_nothing</span><span class="pun">();</span><span class="pln"> </span><span class="com">// جيد</span></pre>

<p>
	كما هو موضّح في تعليقات <code>‎ConstIncorrect‎</code> و <code>‎ConstCorrect‎</code>، فإنّ تأهيل الدوالّ يمكن أن يُستخدم في التوثيق. يمكن افتراض أن أي دالة غير ثابتة ستغير الحالة إذا كان صنفُ ما صحيحًا وفق مفهوم الثبات،وكذلك أيّ دالّة ثابتة لن تغيّر الحالة.
</p>

<h2>
	الدوال التابعة الثابتة للأصناف
</h2>

<p>
	يوضّح المثال التالي مفهوم الدوال التابعة الثابتة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1900_92" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;map&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;string&gt;</span><span class="pln">

</span><span class="kwd">using</span><span class="pln"> </span><span class="kwd">namespace</span><span class="pln"> std</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> A </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
</span><span class="typ">map</span><span class="pun">&lt;</span><span class="pln">string</span><span class="pun">,</span><span class="pln"> string</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> mapOfStrings</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
A</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
mapOfStrings </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">map</span><span class="pun">&lt;</span><span class="pln">string</span><span class="pun">,</span><span class="pln"> string</span><span class="pun">&gt;();</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">void</span><span class="pln"> insertEntry</span><span class="pun">(</span><span class="pln">string </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> key</span><span class="pun">,</span><span class="pln"> string </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> value</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="pun">(*</span><span class="pln">mapOfStrings</span><span class="pun">)[</span><span class="pln">key</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> value</span><span class="pun">;</span><span class="pln">            </span><span class="com">// هذا يعمل بنجاح.</span><span class="pln">
</span><span class="kwd">delete</span><span class="pln"> mapOfStrings</span><span class="pun">;</span><span class="pln">                </span><span class="com">// وهذا أيضًا.</span><span class="pln">
mapOfStrings </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">map</span><span class="pun">&lt;</span><span class="pln">string</span><span class="pun">,</span><span class="pln"> string</span><span class="pun">&gt;();</span><span class="pln">     </span><span class="com">// أما هذا فلا يعمل.</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">void</span><span class="pln"> refresh</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">delete</span><span class="pln"> mapOfStrings</span><span class="pun">;</span><span class="pln">
mapOfStrings </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">map</span><span class="pun">&lt;</span><span class="pln">string</span><span class="pun">,</span><span class="pln"> string</span><span class="pun">&gt;();</span><span class="pln"> </span><span class="com">// ليست دالة ثابتة refresh يعمل لأن.</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">void</span><span class="pln"> getEntry</span><span class="pun">(</span><span class="pln">string </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> key</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
cout </span><span class="pun">&lt;&lt;</span><span class="pln"> mapOfStrings</span><span class="pun">-&gt;</span><span class="pln">at</span><span class="pun">(</span><span class="pln">key</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> argc</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">*</span><span class="pln"> argv</span><span class="pun">[])</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

A var</span><span class="pun">;</span><span class="pln">
var</span><span class="pun">.</span><span class="pln">insertEntry</span><span class="pun">(</span><span class="str">"abc"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"abcValue"</span><span class="pun">);</span><span class="pln">
var</span><span class="pun">.</span><span class="pln">getEntry</span><span class="pun">(</span><span class="str">"abc"</span><span class="pun">);</span><span class="pln">
getchar</span><span class="pun">();</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	هذا الدرس جزء من <a data-ss1617022520="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة دروس عن C++‎</a>.
</p>

<p>
	ترجمة -بتصرّف- للفصول:
</p>

<ul>
<li>
		Chapter 39: Inline functions
	</li>
	<li>
		Chapter 40: Special Member Functions
	</li>
	<li>
		Chapter 41: Non-Static Member Functions
	</li>
	<li>
		Chapter 42: Constant class member functions
	</li>
</ul>
<p>
	من كتاب <a data-ss1617022520="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">937</guid><pubDate>Sun, 19 Jul 2020 13:08:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x62A;&#x648;&#x627;&#x628;&#x639; &#x627;&#x644;&#x648;&#x647;&#x645;&#x64A;&#x629; (Virtual Member Functions) &#x641;&#x64A; Cpp</title><link>https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AA%D9%88%D8%A7%D8%A8%D8%B9-%D8%A7%D9%84%D9%88%D9%87%D9%85%D9%8A%D8%A9-virtual-member-functions-%D9%81%D9%8A-cpp-r936/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_06/24.jpg.cddb415acddd9c5964fa7c3290ce329d.jpg" /></p>

<h2>
	الدوال الوهمية النهائية (Final virtual functions)
</h2>

<p>
	قدّمت C++‎ 11 المُحدِّد <code>‎final‎</code> الذي يمنع إعادة تعريف (overriding) تابع في حال ظهر في بصمته (signature):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_816_6" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">virtual</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Base::Foo\n"</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Derived1</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="com">// Base::foo تخطي</span><span class="pln">
       </span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">()</span><span class="pln"> final </span><span class="pun">{</span><span class="pln">
            std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Derived1::Foo\n"</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Derived2</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">Derived1</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="com">// Compilation error: cannot override final method</span><span class="pln">
        </span><span class="kwd">virtual</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Derived2::Foo\n"</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	لا يمكن استخدام المُحدّد <code>‎final‎</code> إلا مع دالة تابعة وهمية (virtual)، ولا يمكن تطبيقه على الدوال التابعة غير الوهمية. وكما في حال <code>‎final‎</code>، فهناك أيضًا مُحدِّدٌ يُسمّى <code>override</code>، وهو يمنع تخطي الدوالّ الوهمية في الصنف المشتق. كذلك يمكن دمج المُحدِّدين <code>‎override‎</code> و <code>‎final‎</code> معًا على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_816_8" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Derived1</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">()</span><span class="pln"> final override </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Derived1::Foo\n"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<h2>
	استخدام override و virtual معًا في C++‎ 11 والإصدارات الأحدث
</h2>

<p>
	يكون للمحدّد <code>‎override‎</code> معنى خاصًّا في الإصدار C++‎ 11 وما بعده عندما يُلحَق بنهاية بصمة الدالّة، فهو يشير إلى أن الدّالة:
</p>

<ul>
<li>
		تتخطى الدالّةَ الحالية في الصنف الأساسي (base class)، وأنّ …
	</li>
	<li>
		دالّة الصنف الأساسي وهمية <code>‎virtual‎</code>.
	</li>
</ul>
<p>
	الهدف الأساسي من هذا المُحدّد هو توجيه المُصرّف، يوضّح المثال أدناه التغيّر في السلوك في حال استخدام <code>‎override‎</code> وفي حال عدم استخدامها:
</p>

<p>
	عند عدم استخدام <code>‎override‎</code>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_816_10" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">

</span><span class="kwd">struct</span><span class="pln"> X </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">virtual</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"X::f()\n"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	<code>()Y::f</code> لن تتخطى <code>()x::f</code> لأن لها بصمة مختلفة، لكن سيقبل المصرِّفُ الشيفرة ويتجاهل <code>()Y::f</code> بصمت. انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_816_12" style="">
<span class="kwd">struct</span><span class="pln"> Y</span><span class="pun">:</span><span class="pln"> X </span><span class="pun">{</span><span class="pln">
     </span><span class="kwd">virtual</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> a </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	مع <code>‎override‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_816_14" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">

</span><span class="kwd">struct</span><span class="pln"> X </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">virtual</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"X::f()\n"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	سينبهك المصرِّف إلى حقيقة أن <code>()Y::f</code> لا تتخطى شيئًا.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_816_16" style="">
<span class="kwd">struct</span><span class="pln"> Y</span><span class="pun">:</span><span class="pln"> X </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">virtual</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">)</span><span class="pln"> override </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> a </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	لاحظ أنّ <code>‎override‎</code> ليست كلمة مفتاحية، بل مُعرِّف خاص لا يظهر إلا في بصمات الدوالّ، ويمكن استخدام ذلك المعرِّف في جميع السياقات الأخرى:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_816_18" style="">
<span class="kwd">void</span><span class="pln"> foo</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> override </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln"> </span><span class="com">// حسنا</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> </span><span class="kwd">virtual</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln"> </span><span class="com">// Compilation error: keywords can't be used as identifiers.</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	الدوال التابعة الوهمية وغير الوهمية
</h2>

<p>
	مع الدوال التابعة الوهمية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_816_20" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">

</span><span class="kwd">struct</span><span class="pln"> X </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">virtual</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"X::f()\n"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	سيكون تحديد <code>virtual</code> هنا اختياريًا لأنها يمكن أن تُستنتج من <code>()X::f</code>، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_816_22" style="">
<span class="kwd">struct</span><span class="pln"> Y</span><span class="pun">:</span><span class="pln"> X </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">virtual</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Y::f()\n"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> call</span><span class="pun">(</span><span class="pln">X </span><span class="pun">&amp;</span><span class="pln"> a</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    a</span><span class="pun">.</span><span class="pln">f</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    X x</span><span class="pun">;</span><span class="pln">
    Y y</span><span class="pun">;</span><span class="pln">
    call</span><span class="pun">(</span><span class="pln">x</span><span class="pun">);</span><span class="pln"> </span><span class="com">// يكون خرجها: "X::f()"</span><span class="pln">
    call</span><span class="pun">(</span><span class="pln">y</span><span class="pun">);</span><span class="pln"> </span><span class="com">// يكون خرجها: "Y::f()"</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	بدون الدوال التابعة الوهمية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_816_24" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">

</span><span class="kwd">struct</span><span class="pln"> X </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"X::f()\n"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> Y</span><span class="pun">:</span><span class="pln"> X </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Y::f()\n"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> call</span><span class="pun">(</span><span class="pln">X </span><span class="pun">&amp;</span><span class="pln"> a</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    a</span><span class="pun">.</span><span class="pln">f</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    X x</span><span class="pun">;</span><span class="pln">
    Y y</span><span class="pun">;</span><span class="pln">
    call</span><span class="pun">(</span><span class="pln">x</span><span class="pun">);</span><span class="pln"> </span><span class="com">// يكون خرجها: "X::f()"</span><span class="pln">
    call</span><span class="pun">(</span><span class="pln">y</span><span class="pun">);</span><span class="pln"> </span><span class="com">// يكون خرجها: "X::f()"</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	سلوك الدوال الوهمية في المنشئات والمدمرات
</h2>

<p>
	قد يكون سلوك الدّوالّ الوهمية في المنشِئات (constructors) والمدمّرات (destructors) مربكًا للوهلة الأولى.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_816_26" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">

</span><span class="kwd">using</span><span class="pln"> </span><span class="kwd">namespace</span><span class="pln"> std</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> base </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        base</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            f</span><span class="pun">(</span><span class="str">"base constructor"</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}~</span><span class="pln">base</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            f</span><span class="pun">(</span><span class="str">"base destructor"</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">virtual</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> v</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="str">"base::v()"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> caller</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"When called from "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> caller </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> v</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" gets called.\n"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> derived</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> base </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln"> derived</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        f</span><span class="pun">(</span><span class="str">"derived constructor"</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}~</span><span class="pln">derived</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        f</span><span class="pun">(</span><span class="str">"derived destructor"</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> v</span><span class="pun">()</span><span class="pln"> override </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="str">"derived::v()"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    derived d</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	الناتج:
</p>

<ul>
<li>
		عندما تُستدعى من مُنشئ أساسي (base constructor)، ستُستدعى <code>base::v()‎</code>.
	</li>
	<li>
		عندما تُستدعى من مُنشئ مشتق (derived constructor)، سيُستدعى مشتقّ <code>derived::v()‎</code>.
	</li>
	<li>
		عندما تُستدعى من مدمِّر مشتق، سيُستدعى <code>derived::v()‎</code>.
	</li>
	<li>
		عندما تُستدعى من مدمِّر أساسي، سيُستدعى <code>base::v()‎</code>.
	</li>
</ul>
<p>
	السبب في هذا هو أنّ الصنف المشتق ربّما يُعرِّف أعضاءً إضافيين لم تتم تهيئتهم بعد (في حالة المُنشئ) أو سبق حذفهم (في حالة المُدمّر)، ما يجعل استدعاء توابعه غير آمن. لذا يكون النوع الديناميكي لـ <code>this*</code> أثناء إنشاء وتدمير كائنات C++‎ هو صنف المنشئ أو المدمِّر، وليس الصنف المشتق. انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_816_28" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;memory&gt;</span><span class="pln">

</span><span class="kwd">using</span><span class="pln"> </span><span class="kwd">namespace</span><span class="pln"> std</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> base </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        base</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"foo is "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> foo</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">virtual</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> foo</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> derived</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> base </span><span class="pun">{</span><span class="pln">
    unique_ptr </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> ptr_</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        derived</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i</span><span class="pun">):</span><span class="pln"> ptr_</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">int</span><span class="pun">(</span><span class="pln">i </span><span class="pun">*</span><span class="pln"> i</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{}</span></pre>

<p>
	لا يمكن استدعاء ما يلي قبل <code>derived::derived</code> بسبب طريقة عمل ++C:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_816_30" style="">
<span class="pln">    </span><span class="typ">int</span><span class="pln"> foo</span><span class="pun">()</span><span class="pln"> override </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="pln">ptr_</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    derived d</span><span class="pun">(</span><span class="lit">4</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	الدوال الوهمية الخالصة (Pure virtual functions)
</h2>

<p>
	تستطيع جعل دالّةً "دالّةً وهمية خالصة" (أو مُجرّدة) عبر إلحاق <code>‎= ‎0‎‎</code> بالتصريح، وتعدُّ الأصناف التي تحتوي على دالّة وهمية خالصة واحدة على الأقل أصنافًا مجرّدة، ولا يمكن إنشاء نسخ منها؛ ولا يمكن كذلك إنشاء نسخ من الأصناف المشتقة منها إلا إن كانت تعرّف، أو ترث تعريفات، كل الدوالّ الوهمية الخالصة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_816_32" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Abstract</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">virtual</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">()</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Concrete</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">()</span><span class="pln"> override </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">Abstract</span><span class="pln"> a</span><span class="pun">;</span><span class="pln"> </span><span class="com">// خطأ</span><span class="pln">
</span><span class="typ">Concrete</span><span class="pln"> c</span><span class="pun">;</span><span class="pln"> </span><span class="com">//جيد </span></pre>

<p>
	حتى لو عُرِّفت دالّة على أنّها وهمية خالصة، فمن الممكن أن تُعطى تطبيقًا (implementation) افتراضيًّا، لكنّ هذا لن يغيّر حقيقة أنها مجرّدة، وسيكون على الأصناف المشتقّة أن تعرّفها قبل أن تنشئ منها نسخًا، وفي هذه الحالة يُسمح لإصدار الصنف المشتق من الدالّة باستدعاء إصدار الصنف الأساسي.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_816_34" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">DefaultAbstract</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">virtual</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">()</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> </span><span class="typ">DefaultAbstract</span><span class="pun">::</span><span class="pln">f</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">WhyWouldWeDoThis</span><span class="pun">:</span><span class="pln"> </span><span class="typ">DefaultAbstract</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">()</span><span class="pln"> override </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">DefaultAbstract</span><span class="pun">::</span><span class="pln">f</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	هناك بعض الأسباب التي تجعلنا نرغب في فعل ذلك:
</p>

<ul>
<li>
		إذا أردنا إنشاء صنف لا يمكن استنساخه لكنّه لا يمنع الأصناف المشتقة منه من أن تُستنسَخ، نستطيع أن نعلن عن المدمّر على أنه تابع وهمي خالص، فهو على أي حال لازم التعريف إذا أردنا أن نكون قادرين على حذف النسخة من الذاكرة. ولكن لمّا كان المدمّر وهميًا، على الأرجح لمنع تسرّب الذاكرة أثناء الاستخدام <a data-ss1617022519="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-16-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-%D8%A7%D9%84%D8%AA%D8%B9%D8%AF%D8%AF%D9%8A%D8%A9-%D8%A7%D9%84%D8%B4%D9%83%D9%84%D9%8A%D8%A9-polymorphism-%D9%81%D9%8A-cpp-r900/" rel="">متعدد الأشكال</a>، فلن يتأثر الأداء بالسلب في حال إعلان دالّة وهمية أخرى، قد يكون هذا مفيدًا عند صنع الواجهات.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_816_36" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Interface</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">virtual</span><span class="pun">~</span><span class="typ">Interface</span><span class="pun">()</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">Interface</span><span class="pun">::~</span><span class="typ">Interface</span><span class="pun">()</span><span class="pln"> </span><span class="pun">=</span><span class="pln">
    </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Implementation</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Interface</span><span class="pln"> </span><span class="pun">{};</span></pre>

<p>
	في الشيفرة السابقة، لاحظ أن <code>()Implementation~</code> تُعرَّف تلقائيًا من قبل المصرِّف إن لم تُحدد بشكل صريح.
</p>

<ul>
<li>
		إذا احتوت معظم أو كلّ تطبيقات الدالّة الوهمية الخالصة على شيفرة مكررة، فيمكن نقل تلك الشيفرة إلى إصدار الدالّة الموجود في الصنف الأساسي، من أجل تسهيل الصيانة.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_816_38" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">SharedBase</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">State</span><span class="pln"> my_state</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">unique_ptr </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Helper</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> my_helper</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// ...</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">virtual</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> config</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Context</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> cont</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// ...</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="com">/* virtual */</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> </span><span class="typ">SharedBase</span><span class="pun">::</span><span class="pln">config</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Context</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> cont</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    my_helper </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Helper</span><span class="pun">(</span><span class="pln">my_state</span><span class="pun">,</span><span class="pln"> cont</span><span class="pun">.</span><span class="pln">relevant_field</span><span class="pun">);</span><span class="pln">
    do_this</span><span class="pun">();</span><span class="pln">
    and_that</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">OneImplementation</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">SharedBase</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// ...</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">void</span><span class="pln"> config</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Context</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> cont</span><span class="pun">)</span><span class="pln"> override</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// ...</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> </span><span class="typ">OneImplementation</span><span class="pun">::</span><span class="pln">config</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Context</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> cont</span><span class="pun">)</span><span class="pln"> </span><span class="com">/* override */</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    my_state </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        cont</span><span class="pun">.</span><span class="pln">some_field</span><span class="pun">,</span><span class="pln">
        cont</span><span class="pun">.</span><span class="pln">another_field</span><span class="pun">,</span><span class="pln">
        i
    </span><span class="pun">};</span><span class="pln">
    </span><span class="typ">SharedBase</span><span class="pun">::</span><span class="pln">config</span><span class="pun">(</span><span class="pln">cont</span><span class="pun">);</span><span class="pln">
    my_unique_setup</span><span class="pun">();</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="com">// SharedBase وهكذا بالنسبة للأصناف الأخرى المشتقة من </span></pre>

<p>
	هذا الدرس جزء من <a data-ss1617022519="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة دروس عن C++‎</a>.
</p>

<p>
	ترجمة -بتصرّف- للفصل Chapter 38: Virtual Member Functions من كتاب <a data-ss1617022519="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">936</guid><pubDate>Fri, 17 Jul 2020 18:02:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x62A;&#x62D;&#x645;&#x64A;&#x644; &#x627;&#x644;&#x632;&#x627;&#x626;&#x62F; &#x644;&#x644;&#x639;&#x648;&#x627;&#x645;&#x644; (Operator Overloading) &#x641;&#x64A; Cpp</title><link>https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AA%D8%AD%D9%85%D9%8A%D9%84-%D8%A7%D9%84%D8%B2%D8%A7%D8%A6%D8%AF-%D9%84%D9%84%D8%B9%D9%88%D8%A7%D9%85%D9%84-operator-overloading-%D9%81%D9%8A-cpp-r935/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_06/23.jpg.3a845259dfae9d3e4ebcfb2e54c01dd4.jpg" /></p>

<p>
	يمكن تعريف عوامل مثل <code>‎+‎</code> و <code>‎-&gt;‎</code> في ++C من أجل استخدامها مع الأنواع المُعرّفة من قِبل المستخدم. فمثلًا، تعرِّف الترويسة <string> العامل <code>‎+‎</code> لضمّ (concatenate) السلاسل النصية، وهذا ممكن عن طريق تعريف عامِل باستخدام الكلمة المفتاحية <code>‎operator‎</code>. </string></p>

<h2>
	العوامل الحسابية (Arithmetic operators)
</h2>

<p>
	من الممكن زيادة تحميل جميع العوامل الحسابية الأساسية:
</p>

<ul>
<li>
		<code>‎+‎</code> ، <code>‎+=‎</code>
	</li>
	<li>
		<code>‎-‎</code> ، <code>‎-=‎</code>
	</li>
	<li>
		<code>‎*‎</code> ، <code>‎*=‎</code>
	</li>
	<li>
		<code>‎/‎</code> ، <code>‎/=‎</code>
	</li>
	<li>
		<code>‎&amp;‎</code> ، <code>‎&amp;=‎</code>
	</li>
	<li>
		<code>‎|‎</code> ، <code>‎|=‎</code>
	</li>
	<li>
		<code>‎^‎</code> ، <code>‎^=‎</code>
	</li>
	<li>
		<code>‎&gt;&gt;‎</code> ، <code>‎&gt;&gt;=‎</code>
	</li>
	<li>
		<code>‎&lt;&lt;‎</code> ، <code>‎&lt;&lt;=‎</code>
	</li>
</ul>
<p>
	يتشابه التحميل الزائد في كل العوامل كما سترى فيما يأتي من الشرح، ولزيادة التحميل خارج الأصناف (<code>‎class‎</code>) والبنيات (<code>‎struct‎</code>)، يجب تطبيق العامل <code>+operator</code> وفق العامل <code>=+operator</code>. انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6826_7" style="">
<span class="pln">T </span><span class="kwd">operator</span><span class="pun">+(</span><span class="pln">T lhs</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> T</span><span class="pun">&amp;</span><span class="pln"> rhs</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    lhs </span><span class="pun">+=</span><span class="pln"> rhs</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> lhs</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
T</span><span class="pun">&amp;</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">+=(</span><span class="pln">T</span><span class="pun">&amp;</span><span class="pln"> lhs</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> T</span><span class="pun">&amp;</span><span class="pln"> rhs</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// إجراء عملية الجمع   </span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> lhs</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	التحميل الزائد داخل الأصناف والبنيات: انظر المثال التالي حيث يجب تطبيق العامل <code>+operator</code> وفق العامل <code>=+operator</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6826_9" style="">
<span class="pln">T </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> T </span><span class="pun">&amp;</span><span class="pln"> rhs</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="pun">*</span><span class="pln"> </span><span class="kwd">this</span><span class="pln"> </span><span class="pun">+=</span><span class="pln"> rhs</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="kwd">this</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
T </span><span class="pun">&amp;</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">+=</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> T </span><span class="pun">&amp;</span><span class="pln"> rhs</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// إجراء عملية الجمع</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="kwd">this</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<strong>ملاحظة</strong>: يجب أن يعيد <code>‎operator+‎</code> قيمة غير ثابتة، إذ أنّ إعادة مرجع لن يكون له معنى -إذ يُرجع كائنًا جديدًا- ولا إعادة قيمة ثابتة <code>‎const‎</code> كذلك إذ يجب أن تتجنّب عمومًا الإعادة بقيمة ثابتة، ويُمرّر الوسيط الأول بالقيمة (by value)، للسببين التاليين:
</p>

<ol>
<li>
		نظرًا لأنّك لا تستطيع تعديل الكائن الأصلي، ذلك أن <code>‎Object foobar = foo + bar;‎</code> لا ينبغي أن يعدّل <code>‎foo‎</code> على أيّ حال لأنه لا فائدة من ذلك.
	</li>
	<li>
		لا يمكنك جعله ثابتًا لأنّك ستحتاج إلى تعديل الكائن لما أن <code>‎operator+‎</code> تُنفَّذ بواسطة <code>‎operator+=‎</code> الذي يعدّل الكائن
	</li>
</ol>
<p>
	التمرير بمرجع ثابت <code>&amp;const</code> هو أحد الخيارات المتاحة، لكن سيتعيّن عليك حينها إنشاء نسخة مؤقّتة من الكائن المُمرّر، أما إن مرّرت الوسيط بقيمته (by value) فسيتكفّل المُصرّف بذلك نيابة عنك. كذلك فإن <code>‎operator+=‎</code> يعيد مرجعًا إلى نفسه، وهكذا يمكن سَلْسَلَته، لكن لا تستخدم المتغيّر نفسه، إذ أنّ ذلك سيؤدي إلى سلوك غير محدّد.
</p>

<p>
	الوسيط الأوّل هو مرجع نريد تعديله لكنه ليس ثابتًا، لأنك لن تستطيع تعديله عندئذ، ولا ينبغي تعديل الوسيط الثاني، ويُمرَّر بمرجِع ثابت <code>‎const&amp;‎</code> لأسباب تتعلق بالأداء، إذ أن تمرير الوسيط بمرجع ثابت أسرع من تمريرِه بالقيمة.
</p>

<h2>
	عامل فهرسة المصفوفات (Array subscript operator)
</h2>

<p>
	يمكن زيادة تحميل عامل فهرسة <a data-ss1617022517="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-7-%D8%A7%D9%84%D9%85%D8%B5%D9%81%D9%88%D9%81%D8%A7%D8%AA-%D9%81%D9%8A-cpp-r891/" rel="">المصفوفات</a> <code>‎[]‎</code>، ويجب عليك دائمًا تطبيق نسختين، إحداهما ثابتة (<code>‎const‎</code>)، والأخرى غير ثابتة، لأنّه إن كان الكائن ثابتًا فلن يستطيع تعديل الكائن المُعاد من قِبل عامل الفهرسة <code>‎[]‎</code>. تُمرَّر الوسائط بمرجع ثابت (<code>‎const&amp;‎</code>) بدلاً من قيَمها لأنّ التمرير بالمرجع أسرع من التمرير بالقيمة، كما أنها تكون ثابتة حتى لا يُغيِّرَ العامِل الفهرسَ عن طريق الخطأ، وتعيد العوامل القيمة بالمرجع، لأنّها مصممة بطريقة تمكِّنك من تعديل الكائن <code>‎[]‎</code> المُعاد، انظر المثال التالي حيث نغير القيمة من 1 إلى 2، إذ لم يكن ذلك ممكنًا إن لم يُعَد بالمرجع.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6826_11" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v</span><span class="pun">{</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
v</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln"> </span></pre>

<p>
	لا يمكنك زيادة التحميل إلا داخل صنف أو بنية، انظر المثال التالي حيث يكون I هو نوع الفهرس، ويكون غالبًا عددًا صحيحًا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6826_13" style="">
<span class="pln">T</span><span class="pun">&amp;</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">[](</span><span class="kwd">const</span><span class="pln"> I</span><span class="pun">&amp;</span><span class="pln"> index</span><span class="pun">)</span><span class="pln">
    </span><span class="com">// افعل شيئا ما</span><span class="pln">
    </span><span class="com">// أعِد شيئًا ما</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> T</span><span class="pun">&amp;</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">[](</span><span class="kwd">const</span><span class="pln"> I</span><span class="pun">&amp;</span><span class="pln"> index</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
    </span><span class="com">// افعل شيئا ما</span><span class="pln">
    </span><span class="com">// إعادة شيء ما</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكن إنشاء عدّة عوامل فهرسة <code>‎</code><code>[][]...</code>‎<code>‎</code> عبر الكائنات الوكيلة (proxy objects). انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6826_15" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">class</span><span class="pln"> matrix </span><span class="pun">{</span><span class="pln">
        </span><span class="com">//  [][] يسمح الصنف بتحميل </span><span class="pln">
        </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> C </span><span class="pun">&gt;</span><span class="pln">
            </span><span class="kwd">class</span><span class="pln"> proxy_row_vector </span><span class="pun">{</span><span class="pln">
                </span><span class="kwd">using</span><span class="pln"> reference </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">declval </span><span class="pun">&lt;</span><span class="pln"> C </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">()[</span><span class="lit">0</span><span class="pun">]);</span><span class="pln">
                </span><span class="kwd">using</span><span class="pln"> const_reference </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">declval </span><span class="pun">&lt;</span><span class="pln"> C
                    </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">()[</span><span class="lit">0</span><span class="pun">]);</span><span class="pln">
                </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
                    proxy_row_vector</span><span class="pun">(</span><span class="pln">C</span><span class="pun">&amp;</span><span class="pln"> _vec</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> _r_ind</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> _cols</span><span class="pun">):</span><span class="pln"> vec</span><span class="pun">(</span><span class="pln">_vec</span><span class="pun">),</span><span class="pln"> row_index</span><span class="pun">(</span><span class="pln">_r_ind</span><span class="pun">),</span><span class="pln"> cols</span><span class="pun">(</span><span class="pln">_cols</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
                const_reference </span><span class="kwd">operator</span><span class="pun">[](</span><span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> _col_index</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                    </span><span class="kwd">return</span><span class="pln"> vec</span><span class="pun">[</span><span class="pln">row_index </span><span class="pun">*</span><span class="pln"> cols </span><span class="pun">+</span><span class="pln"> _col_index</span><span class="pun">];</span><span class="pln">
                </span><span class="pun">}</span><span class="pln">
                reference </span><span class="kwd">operator</span><span class="pun">[](</span><span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> _col_index</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                    </span><span class="kwd">return</span><span class="pln"> vec</span><span class="pun">[</span><span class="pln">row_index </span><span class="pun">*</span><span class="pln"> cols </span><span class="pun">+</span><span class="pln"> _col_index</span><span class="pun">];</span><span class="pln">
                </span><span class="pun">}</span><span class="pln">
                </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
                    C</span><span class="pun">&amp;</span><span class="pln"> vec</span><span class="pun">;</span><span class="pln">
                std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> row_index</span><span class="pun">;</span><span class="pln">    </span><span class="com">// فهرس الصفوف</span><span class="pln">
                std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> cols</span><span class="pun">;</span><span class="pln">        </span><span class="com">// عدد الأعمدة في المصفوفة</span><span class="pln">
            </span><span class="pun">};</span><span class="pln">
        </span><span class="kwd">using</span><span class="pln"> const_proxy </span><span class="pun">=</span><span class="pln"> proxy_row_vector </span><span class="pun">&lt;</span><span class="pln">
            </span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> T </span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">using</span><span class="pln"> proxy </span><span class="pun">=</span><span class="pln"> proxy_row_vector </span><span class="pun">&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> T </span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
            matrix</span><span class="pun">():</span><span class="pln"> mtx</span><span class="pun">(),</span><span class="pln"> rows</span><span class="pun">(</span><span class="lit">0</span><span class="pun">),</span><span class="pln"> cols</span><span class="pun">(</span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
        matrix</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> _rows</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> _cols</span><span class="pun">):</span><span class="pln"> mtx</span><span class="pun">(</span><span class="pln">_rows</span><span class="pun">*</span><span class="pln">_cols</span><span class="pun">),</span><span class="pln"> rows</span><span class="pun">(</span><span class="pln">_rows</span><span class="pun">),</span><span class="pln"> cols</span><span class="pun">(</span><span class="pln">_cols</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
        </span><span class="com">//  []  متبوعا باستدعاء آخر لـ operator[] استدعاء</span><span class="pln">
        const_proxy </span><span class="kwd">operator</span><span class="pun">[](</span><span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> _row_index</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> const_proxy</span><span class="pun">(</span><span class="pln">mtx</span><span class="pun">,</span><span class="pln"> _row_index</span><span class="pun">,</span><span class="pln"> cols</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        proxy </span><span class="kwd">operator</span><span class="pun">[](</span><span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> _row_index</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> proxy</span><span class="pun">(</span><span class="pln">mtx</span><span class="pun">,</span><span class="pln"> _row_index</span><span class="pun">,</span><span class="pln"> cols</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
            std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln"> mtx</span><span class="pun">;</span><span class="pln">
        std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> rows</span><span class="pun">;</span><span class="pln">
        std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> cols</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">};</span></pre>

<h2>
	عوامل التحويل
</h2>

<p>
	يمكنك زيادة تحميل عوامل النوع (type operators) بحيث يمكن تحويل النوع ضمنيًا إلى نوع آخر، ويجب تعريف عامل التحويل في صنف (<code>‎class‎</code>) أو بنية (<code>‎struct‎</code>):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6826_17" style="">
<span class="kwd">operator</span><span class="pln"> T</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">/* إعادة شيء ما */</span><span class="pln"> </span><span class="pun">}</span></pre>

<p>
	*<em>ملاحظة</em>: يكون العامل ثابتًا حتى يسمح بتحويل الكائنات الثابتة. انظر المثال التالي حيث نحول <code>Text</code> ضمنيًا إلى <code>*const char</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6826_19" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Text</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">string text</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// هنا نحوله ضمنيًا:</span><span class="pln">
    </span><span class="com">/*explicit*/</span><span class="pln">
    </span><span class="kwd">operator</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">*()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> text</span><span class="pun">.</span><span class="pln">data</span><span class="pun">();</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
    </span><span class="com">// ^^^^^^^</span><span class="pln">
    </span><span class="com">// لتعطيل التحويل الضمني</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">Text</span><span class="pln"> t</span><span class="pun">;</span><span class="pln">
t</span><span class="pun">.</span><span class="pln">text </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Hello world!"</span><span class="pun">;</span><span class="pln">
</span><span class="com">// OK</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">*</span><span class="pln"> copyoftext </span><span class="pun">=</span><span class="pln"> t</span><span class="pun">;</span></pre>

<h2>
	نظرة أخرى على الأعداد المركبة
</h2>

<p>
	تستخدم الشيفرة التالية نوعًا يمثل الأعداد المركّبة، حيث يُحوَّل الحقل الأساسي (underlying field) تلقائيًا وفقًا لقواعد تحويل الأنواع وبتطبيق العوامل الأساسية الأربعة (+ و - و * و /) مع عضو من حقل آخر (سواء كان من النوع <code>‎complex&lt;T&gt;‎</code>، أو من نوع عددي آخر). لنرى الآن المثال التالي الذي يوضّح مفهوم زيادة تحميل العوامل وكيفية استخدام القوالب:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6826_21" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;type_traits&gt;</span><span class="pln">

</span><span class="kwd">namespace</span><span class="pln"> not_std</span><span class="pun">{</span><span class="pln">

</span><span class="kwd">using</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">decay_t</span><span class="pun">;</span><span class="pln">

</span><span class="com">//----------------------------------------------------------------</span><span class="pln">
</span><span class="com">// complex&lt; value_t &gt;</span><span class="pln">
</span><span class="com">//----------------------------------------------------------------</span><span class="pln">

</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">value_t</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> complex
</span><span class="pun">{</span><span class="pln">
</span><span class="typ">value_t</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
</span><span class="typ">value_t</span><span class="pln"> y</span><span class="pun">;</span><span class="pln">
complex </span><span class="pun">&amp;</span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">+=</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">value_t</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">x</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="kwd">this</span><span class="pun">-&gt;</span><span class="pln">x </span><span class="pun">+=</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="kwd">this</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
complex </span><span class="pun">&amp;</span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">+=</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> complex </span><span class="pun">&amp;</span><span class="pln">other</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="kwd">this</span><span class="pun">-&gt;</span><span class="pln">x </span><span class="pun">+=</span><span class="pln"> other</span><span class="pun">.</span><span class="pln">x</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">this</span><span class="pun">-&gt;</span><span class="pln">y </span><span class="pun">+=</span><span class="pln"> other</span><span class="pun">.</span><span class="pln">y</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="kwd">this</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

complex </span><span class="pun">&amp;</span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">-=</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">value_t</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">x</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="kwd">this</span><span class="pun">-&gt;</span><span class="pln">x </span><span class="pun">-=</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="kwd">this</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
complex </span><span class="pun">&amp;</span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">-=</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> complex </span><span class="pun">&amp;</span><span class="pln">other</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="kwd">this</span><span class="pun">-&gt;</span><span class="pln">x </span><span class="pun">-=</span><span class="pln"> other</span><span class="pun">.</span><span class="pln">x</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">this</span><span class="pun">-&gt;</span><span class="pln">y </span><span class="pun">-=</span><span class="pln"> other</span><span class="pun">.</span><span class="pln">y</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="kwd">this</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

complex </span><span class="pun">&amp;</span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">*=</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">value_t</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">s</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="kwd">this</span><span class="pun">-&gt;</span><span class="pln">x </span><span class="pun">*=</span><span class="pln"> s</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">this</span><span class="pun">-&gt;</span><span class="pln">y </span><span class="pun">*=</span><span class="pln"> s</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="kwd">this</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
complex </span><span class="pun">&amp;</span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">*=</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> complex </span><span class="pun">&amp;</span><span class="pln">other</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="pun">(*</span><span class="kwd">this</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(*</span><span class="kwd">this</span><span class="pun">)</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> other</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="kwd">this</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

complex </span><span class="pun">&amp;</span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">/=</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">value_t</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">s</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="kwd">this</span><span class="pun">-&gt;</span><span class="pln">x </span><span class="pun">/=</span><span class="pln"> s</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">this</span><span class="pun">-&gt;</span><span class="pln">y </span><span class="pun">/=</span><span class="pln"> s</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="kwd">this</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

complex </span><span class="pun">&amp;</span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">/=</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> complex </span><span class="pun">&amp;</span><span class="pln">other</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="pun">(*</span><span class="kwd">this</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(*</span><span class="kwd">this</span><span class="pun">)</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> other</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="kwd">this</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
complex</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">value_t</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">value_t</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">y</span><span class="pun">)</span><span class="pln">
</span><span class="pun">:</span><span class="pln"> x</span><span class="pun">{</span><span class="pln">x</span><span class="pun">}</span><span class="pln">
</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">{</span><span class="pln">y</span><span class="pun">}</span><span class="pln">
</span><span class="pun">{}</span><span class="pln">

</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">other_value_t</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">explicit</span><span class="pln"> complex</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> complex</span><span class="str">&lt;other_value_t&gt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">other</span><span class="pun">)</span><span class="pln">
</span><span class="pun">:</span><span class="pln"> x</span><span class="pun">{</span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">value_t</span><span class="pln"> </span><span class="pun">&amp;&gt;(</span><span class="pln">other</span><span class="pun">.</span><span class="pln">x</span><span class="pun">)}</span><span class="pln">
</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">{</span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">value_t</span><span class="pln"> </span><span class="pun">&amp;&gt;(</span><span class="pln">other</span><span class="pun">.</span><span class="pln">y</span><span class="pun">)}</span><span class="pln">
</span><span class="pun">{}</span><span class="pln">
complex </span><span class="pun">&amp;</span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> complex </span><span class="pun">&amp;)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
complex </span><span class="pun">&amp;</span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">complex </span><span class="pun">&amp;&amp;)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
complex</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> complex </span><span class="pun">&amp;)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
complex</span><span class="pun">(</span><span class="pln">complex </span><span class="pun">&amp;&amp;)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
complex</span><span class="pun">()</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="com">//  تربيع القيمة المطلقة</span><span class="pln">
</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">value_t</span><span class="pun">&gt;</span><span class="pln">
</span><span class="typ">value_t</span><span class="pln"> absqr</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> complex</span><span class="str">&lt;value_t&gt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">z</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> z</span><span class="pun">.</span><span class="pln">x</span><span class="pun">*</span><span class="pln">z</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+</span><span class="pln"> z</span><span class="pun">.</span><span class="pln">y</span><span class="pun">*</span><span class="pln">z</span><span class="pun">.</span><span class="pln">y</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

</span><span class="com">//----------------------------------------------------------------</span><span class="pln">
</span><span class="com">// operator - (negation) - عامل النفي </span><span class="pln">
</span><span class="com">//----------------------------------------------------------------</span><span class="pln">

</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">value_t</span><span class="pun">&gt;</span><span class="pln">
complex</span><span class="str">&lt;value_t&gt;</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> complex</span><span class="str">&lt;value_t&gt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">z</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">{-</span><span class="pln">z</span><span class="pun">.</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> </span><span class="pun">-</span><span class="pln">z</span><span class="pun">.</span><span class="pln">y</span><span class="pun">};</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

</span><span class="com">//----------------------------------------------------------------</span><span class="pln">
</span><span class="com">// + عامل</span><span class="pln">
</span><span class="com">//----------------------------------------------------------------</span><span class="pln">
</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">left_t</span><span class="pun">,</span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">right_t</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> complex</span><span class="str">&lt;left_t&gt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> complex</span><span class="str">&lt;right_t&gt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">b</span><span class="pun">)</span><span class="pln">
</span><span class="pun">-&gt;</span><span class="pln"> complex</span><span class="pun">&lt;</span><span class="typ">decay_t</span><span class="pun">&lt;</span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">a</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+</span><span class="pln"> b</span><span class="pun">.</span><span class="pln">x</span><span class="pun">)&gt;&gt;</span><span class="pln">
</span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pun">{</span><span class="pln">a</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+</span><span class="pln"> b</span><span class="pun">.</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> a</span><span class="pun">.</span><span class="pln">y </span><span class="pun">+</span><span class="pln"> b</span><span class="pun">.</span><span class="pln">y</span><span class="pun">};</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">left_t</span><span class="pun">,</span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">right_t</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">left_t</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> complex</span><span class="str">&lt;right_t&gt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">b</span><span class="pun">)</span><span class="pln">
</span><span class="pun">-&gt;</span><span class="pln"> complex</span><span class="pun">&lt;</span><span class="typ">decay_t</span><span class="pun">&lt;</span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">a </span><span class="pun">+</span><span class="pln"> b</span><span class="pun">.</span><span class="pln">x</span><span class="pun">)&gt;&gt;</span><span class="pln">
</span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pun">{</span><span class="pln">a </span><span class="pun">+</span><span class="pln"> b</span><span class="pun">.</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> b</span><span class="pun">.</span><span class="pln">y</span><span class="pun">};</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">left_t</span><span class="pun">,</span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">right_t</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> complex</span><span class="str">&lt;left_t&gt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">right_t</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">b</span><span class="pun">)</span><span class="pln">
</span><span class="pun">-&gt;</span><span class="pln"> complex</span><span class="pun">&lt;</span><span class="typ">decay_t</span><span class="pun">&lt;</span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">a</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+</span><span class="pln"> b</span><span class="pun">)&gt;&gt;</span><span class="pln">
</span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pun">{</span><span class="pln">a</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+</span><span class="pln"> b</span><span class="pun">,</span><span class="pln"> a</span><span class="pun">.</span><span class="pln">y</span><span class="pun">};</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

</span><span class="com">//----------------------------------------------------------------</span><span class="pln">
</span><span class="com">//  - عامل</span><span class="pln">
</span><span class="com">//----------------------------------------------------------------</span><span class="pln">

</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">left_t</span><span class="pun">,</span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">right_t</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> complex</span><span class="str">&lt;left_t&gt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> complex</span><span class="str">&lt;right_t&gt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">b</span><span class="pun">)</span><span class="pln">
</span><span class="pun">-&gt;</span><span class="pln"> complex</span><span class="pun">&lt;</span><span class="typ">decay_t</span><span class="pun">&lt;</span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">a</span><span class="pun">.</span><span class="pln">x </span><span class="pun">-</span><span class="pln"> b</span><span class="pun">.</span><span class="pln">x</span><span class="pun">)&gt;&gt;</span><span class="pln">
</span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pun">{</span><span class="pln">a</span><span class="pun">.</span><span class="pln">x </span><span class="pun">-</span><span class="pln"> b</span><span class="pun">.</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> a</span><span class="pun">.</span><span class="pln">y </span><span class="pun">-</span><span class="pln"> b</span><span class="pun">.</span><span class="pln">y</span><span class="pun">};</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">left_t</span><span class="pun">,</span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">right_t</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">left_t</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> complex</span><span class="str">&lt;right_t&gt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">b</span><span class="pun">)</span><span class="pln">
</span><span class="pun">-&gt;</span><span class="pln"> complex</span><span class="pun">&lt;</span><span class="typ">decay_t</span><span class="pun">&lt;</span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">a </span><span class="pun">-</span><span class="pln"> b</span><span class="pun">.</span><span class="pln">x</span><span class="pun">)&gt;&gt;</span><span class="pln">
</span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pun">{</span><span class="pln">a </span><span class="pun">-</span><span class="pln"> b</span><span class="pun">.</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> b</span><span class="pun">.</span><span class="pln">y</span><span class="pun">};</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">left_t</span><span class="pun">,</span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">right_t</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> complex</span><span class="str">&lt;left_t&gt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">right_t</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">b</span><span class="pun">)</span><span class="pln">
</span><span class="pun">-&gt;</span><span class="pln"> complex</span><span class="pun">&lt;</span><span class="typ">decay_t</span><span class="pun">&lt;</span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">a</span><span class="pun">.</span><span class="pln">x </span><span class="pun">-</span><span class="pln"> b</span><span class="pun">)&gt;&gt;</span><span class="pln">
</span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pun">{</span><span class="pln">a</span><span class="pun">.</span><span class="pln">x </span><span class="pun">-</span><span class="pln"> b</span><span class="pun">,</span><span class="pln"> a</span><span class="pun">.</span><span class="pln">y</span><span class="pun">};</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

</span><span class="com">//----------------------------------------------------------------</span><span class="pln">
</span><span class="com">// * عامل</span><span class="pln">
</span><span class="com">//----------------------------------------------------------------</span><span class="pln">

</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">left_t</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">right_t</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> complex</span><span class="str">&lt;left_t&gt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> complex</span><span class="str">&lt;right_t&gt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">b</span><span class="pun">)</span><span class="pln">
</span><span class="pun">-&gt;</span><span class="pln"> complex</span><span class="pun">&lt;</span><span class="typ">decay_t</span><span class="pun">&lt;</span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">a</span><span class="pun">.</span><span class="pln">x </span><span class="pun">*</span><span class="pln"> b</span><span class="pun">.</span><span class="pln">x</span><span class="pun">)&gt;&gt;</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
a</span><span class="pun">.</span><span class="pln">x</span><span class="pun">*</span><span class="pln">b</span><span class="pun">.</span><span class="pln">x </span><span class="pun">-</span><span class="pln"> a</span><span class="pun">.</span><span class="pln">y</span><span class="pun">*</span><span class="pln">b</span><span class="pun">.</span><span class="pln">y</span><span class="pun">,</span><span class="pln">
a</span><span class="pun">.</span><span class="pln">x</span><span class="pun">*</span><span class="pln">b</span><span class="pun">.</span><span class="pln">y </span><span class="pun">+</span><span class="pln"> a</span><span class="pun">.</span><span class="pln">y</span><span class="pun">*</span><span class="pln">b</span><span class="pun">.</span><span class="pln">x
</span><span class="pun">};</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">left_t</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">right_t</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">left_t</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> complex</span><span class="str">&lt;right_t&gt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">b</span><span class="pun">)</span><span class="pln">
</span><span class="pun">-&gt;</span><span class="pln"> complex</span><span class="pun">&lt;</span><span class="typ">decay_t</span><span class="pun">&lt;</span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">a </span><span class="pun">*</span><span class="pln"> b</span><span class="pun">.</span><span class="pln">x</span><span class="pun">)&gt;&gt;</span><span class="pln">
</span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">{</span><span class="pln">a </span><span class="pun">*</span><span class="pln"> b</span><span class="pun">.</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> a </span><span class="pun">*</span><span class="pln"> b</span><span class="pun">.</span><span class="pln">y</span><span class="pun">};</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">left_t</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">right_t</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> complex</span><span class="str">&lt;left_t&gt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">right_t</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">b</span><span class="pun">)</span><span class="pln">
</span><span class="pun">-&gt;</span><span class="pln"> complex</span><span class="pun">&lt;</span><span class="typ">decay_t</span><span class="pun">&lt;</span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">a</span><span class="pun">.</span><span class="pln">x </span><span class="pun">*</span><span class="pln"> b</span><span class="pun">)&gt;&gt;</span><span class="pln">
</span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">{</span><span class="pln">a</span><span class="pun">.</span><span class="pln">x </span><span class="pun">*</span><span class="pln"> b</span><span class="pun">,</span><span class="pln"> a</span><span class="pun">.</span><span class="pln">y </span><span class="pun">*</span><span class="pln"> b</span><span class="pun">};</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

</span><span class="com">//----------------------------------------------------------------</span><span class="pln">
</span><span class="com">//  / عامل</span><span class="pln">
</span><span class="com">//----------------------------------------------------------------</span><span class="pln">

</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">left_t</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">right_t</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> complex</span><span class="str">&lt;left_t&gt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> complex</span><span class="str">&lt;right_t&gt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">b</span><span class="pun">)</span><span class="pln">
</span><span class="pun">-&gt;</span><span class="pln"> complex</span><span class="pun">&lt;</span><span class="typ">decay_t</span><span class="pun">&lt;</span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">a</span><span class="pun">.</span><span class="pln">x </span><span class="pun">/</span><span class="pln"> b</span><span class="pun">.</span><span class="pln">x</span><span class="pun">)&gt;&gt;</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> r </span><span class="pun">=</span><span class="pln"> absqr</span><span class="pun">(</span><span class="pln">b</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="pun">(</span><span class="pln"> a</span><span class="pun">.</span><span class="pln">x</span><span class="pun">*</span><span class="pln">b</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+</span><span class="pln"> a</span><span class="pun">.</span><span class="pln">y</span><span class="pun">*</span><span class="pln">b</span><span class="pun">.</span><span class="pln">y</span><span class="pun">)</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> r</span><span class="pun">,</span><span class="pln">
</span><span class="pun">(-</span><span class="pln">a</span><span class="pun">.</span><span class="pln">x</span><span class="pun">*</span><span class="pln">b</span><span class="pun">.</span><span class="pln">y </span><span class="pun">+</span><span class="pln"> a</span><span class="pun">.</span><span class="pln">y</span><span class="pun">*</span><span class="pln">b</span><span class="pun">.</span><span class="pln">x</span><span class="pun">)</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> r
</span><span class="pun">};</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">left_t</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">right_t</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">left_t</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> complex</span><span class="str">&lt;right_t&gt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">b</span><span class="pun">)</span><span class="pln">
</span><span class="pun">-&gt;</span><span class="pln"> complex</span><span class="pun">&lt;</span><span class="typ">decay_t</span><span class="pun">&lt;</span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">a </span><span class="pun">/</span><span class="pln"> b</span><span class="pun">.</span><span class="pln">x</span><span class="pun">)&gt;&gt;</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> s </span><span class="pun">=</span><span class="pln"> a</span><span class="pun">/</span><span class="pln">absqr</span><span class="pun">(</span><span class="pln">b</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
b</span><span class="pun">.</span><span class="pln">x </span><span class="pun">*</span><span class="pln"> s</span><span class="pun">,</span><span class="pln">
</span><span class="pun">-</span><span class="pln">b</span><span class="pun">.</span><span class="pln">y </span><span class="pun">*</span><span class="pln"> s
</span><span class="pun">};</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">left_t</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">right_t</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> complex</span><span class="str">&lt;left_t&gt;</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">right_t</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">b</span><span class="pun">)</span><span class="pln">
</span><span class="pun">-&gt;</span><span class="pln"> complex</span><span class="pun">&lt;</span><span class="typ">decay_t</span><span class="pun">&lt;</span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">a</span><span class="pun">.</span><span class="pln">x </span><span class="pun">/</span><span class="pln"> b</span><span class="pun">)&gt;&gt;</span><span class="pln">
</span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">{</span><span class="pln">a</span><span class="pun">.</span><span class="pln">x </span><span class="pun">/</span><span class="pln"> b</span><span class="pun">,</span><span class="pln"> a</span><span class="pun">.</span><span class="pln">y </span><span class="pun">/</span><span class="pln"> b</span><span class="pun">};</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

</span><span class="pun">}</span><span class="pln">    </span><span class="com">// not_std فضاء الاسم</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> argc</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> </span><span class="pun">**</span><span class="pln">argv</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="kwd">namespace</span><span class="pln"> not_std</span><span class="pun">;</span><span class="pln">

complex</span><span class="str">&lt;float&gt;</span><span class="pln"> fz</span><span class="pun">{</span><span class="lit">4.0f</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1.0f</span><span class="pun">};</span><span class="pln">
</span><span class="com">// complex&lt;double&gt; إنشاء</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> dz </span><span class="pun">=</span><span class="pln"> fz </span><span class="pun">*</span><span class="pln"> </span><span class="lit">1.0</span><span class="pun">;</span><span class="pln">

</span><span class="com">// complex&lt;double&gt; ما يزال</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> idz </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1.0f</span><span class="pun">/</span><span class="pln">dz</span><span class="pun">;</span><span class="pln">

</span><span class="com">// complex&lt;double&gt; ما يزال</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> one </span><span class="pun">=</span><span class="pln"> dz </span><span class="pun">*</span><span class="pln"> idz</span><span class="pun">;</span><span class="pln">

</span><span class="com">// complex&lt;double&gt; أيضا</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> one_again </span><span class="pun">=</span><span class="pln"> fz </span><span class="pun">*</span><span class="pln"> idz</span><span class="pun">;</span><span class="pln">

</span><span class="com">// اختبار العامل للتحقق من أن كل شيء سيُصرّف بلا مشاكل</span><span class="pln">

complex</span><span class="str">&lt;float&gt;</span><span class="pln"> a</span><span class="pun">{</span><span class="lit">1.0f</span><span class="pun">,</span><span class="pln"> </span><span class="pun">-</span><span class="lit">2.0f</span><span class="pun">};</span><span class="pln">
complex</span><span class="str">&lt;double&gt;</span><span class="pln"> b</span><span class="pun">{</span><span class="lit">3.0</span><span class="pun">,</span><span class="pln"> </span><span class="pun">-</span><span class="lit">4.0</span><span class="pun">};</span><span class="pln">

</span><span class="com">// complex&lt;double&gt; كل هذه من النوع</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> c0 </span><span class="pun">=</span><span class="pln"> a </span><span class="pun">+</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> c1 </span><span class="pun">=</span><span class="pln"> a </span><span class="pun">-</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> c2 </span><span class="pun">=</span><span class="pln"> a </span><span class="pun">*</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> c3 </span><span class="pun">=</span><span class="pln"> a </span><span class="pun">/</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">

</span><span class="com">// complex&lt;float&gt; كل هذه من النوع</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> d0 </span><span class="pun">=</span><span class="pln"> a </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> d1 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> a</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> d2 </span><span class="pun">=</span><span class="pln"> a </span><span class="pun">-</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> d3 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> a</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> d4 </span><span class="pun">=</span><span class="pln"> a </span><span class="pun">*</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> d5 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> a</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> d6 </span><span class="pun">=</span><span class="pln"> a </span><span class="pun">/</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> d7 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> a</span><span class="pun">;</span><span class="pln">

</span><span class="com">// complex&lt;double&gt;  كل هذه من النوعauto e0 = b + 1;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> e1 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> e2 </span><span class="pun">=</span><span class="pln"> b </span><span class="pun">-</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> e3 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> e4 </span><span class="pun">=</span><span class="pln"> b </span><span class="pun">*</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> e5 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> e6 </span><span class="pun">=</span><span class="pln"> b </span><span class="pun">/</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> e7 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	العوامل المسماة (Named operators)
</h2>

<p>
	يمكنك توسيع C++‎ بالعوامل المسمّاة المحاطة بعوامل ++C القياسية. سنبدأ أولًا بكتابة شيفرة تشكل مكتبة من بضعة أسطر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6826_23" style="">
<span class="kwd">namespace</span><span class="pln"> named_operator </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> D </span><span class="pun">&gt;</span><span class="pln"> </span><span class="kwd">struct</span><span class="pln"> make_operator </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">constexpr</span><span class="pln"> make_operator</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
    </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> O </span><span class="pun">&gt;</span><span class="pln"> </span><span class="kwd">struct</span><span class="pln"> half_apply </span><span class="pun">{</span><span class="pln">
        T </span><span class="pun">&amp;&amp;</span><span class="pln"> lhs</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
    </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Lhs</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Op</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
        half_apply </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Lhs</span><span class="pun">,</span><span class="pln"> </span><span class="str">'*'</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Op</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Lhs</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> lhs</span><span class="pun">,</span><span class="pln"> make_operator </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Op</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                std</span><span class="pun">::</span><span class="pln">forward </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Lhs</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">lhs</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">};</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Lhs</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Op</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Rhs</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
        </span><span class="kwd">auto</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">*(</span><span class="pln"> half_apply</span><span class="pun">&lt;</span><span class="typ">Lhs</span><span class="pun">,</span><span class="pln"> </span><span class="str">'*'</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Op</span><span class="pun">&gt;&amp;&amp;</span><span class="pln"> lhs</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Rhs</span><span class="pun">&amp;&amp;</span><span class="pln"> rhs </span><span class="pun">)</span><span class="pln"> </span><span class="pun">-&gt;</span><span class="pln"> </span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">named_invoke</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">forward </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Lhs</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">lhs</span><span class="pun">.</span><span class="pln">lhs</span><span class="pun">),</span><span class="pln"> </span><span class="typ">Op</span><span class="pln"> </span><span class="pun">{},</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">forward </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Rhs</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">rhs</span><span class="pun">)))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> named_invoke</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">forward </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Lhs</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">lhs</span><span class="pun">.</span><span class="pln">lhs</span><span class="pun">),</span><span class="pln"> </span><span class="typ">Op</span><span class="pln"> </span><span class="pun">{},</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">forward </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Rhs</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">rhs</span><span class="pun">));</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	هذه الشيفرة لا تفعل أي شيء حتى الآن. سنضيف الآن المتجهات:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6826_25" style="">
<span class="kwd">namespace</span><span class="pln"> my_ns </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">append_t</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> named_operator</span><span class="pun">::</span><span class="pln">make_operator</span><span class="str">&lt;append_t&gt;</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">constexpr</span><span class="pln"> </span><span class="typ">append_t</span><span class="pln"> append</span><span class="pun">{};</span><span class="pln">

</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> A0</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> A1</span><span class="pun">&gt;</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> A0</span><span class="pun">&gt;</span><span class="pln"> named_invoke</span><span class="pun">(</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">vector</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> A0</span><span class="pun">&gt;</span><span class="pln"> lhs</span><span class="pun">,</span><span class="pln"> </span><span class="typ">append_t</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">vector</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> A1</span><span class="pun">&gt;</span><span class="pln"> </span><span class="kwd">const</span><span class="pun">&amp;</span><span class="pln"> rhs
</span><span class="pun">)</span><span class="pln">    </span><span class="pun">{</span><span class="pln">
lhs</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="pln"> lhs</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> rhs</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> rhs</span><span class="pun">.</span><span class="pln">end</span><span class="pun">()</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">move</span><span class="pun">(</span><span class="pln">lhs</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> my_ns</span><span class="pun">::</span><span class="pln">append</span><span class="pun">;</span><span class="pln">

std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> a </span><span class="pun">{</span><span class="lit">1</span><span class="pun">,</span><span class="lit">2</span><span class="pun">,</span><span class="lit">3</span><span class="pun">};</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> b </span><span class="pun">{</span><span class="lit">4</span><span class="pun">,</span><span class="lit">5</span><span class="pun">,</span><span class="lit">6</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">auto</span><span class="pln"> c </span><span class="pun">=</span><span class="pln"> a </span><span class="pun">*</span><span class="pln">append</span><span class="pun">*</span><span class="pln"> b</span><span class="pun">;</span></pre>

<p>
	لقد عرّفنا كائنًا <code>‎append‎</code> من النوع <code>‎append_t:named_operator::make_operator&lt;append_t&gt;‎</code>، ثم زدنا بعد ذلك تحميل <code>append_t:named_operator::make_operator&lt;append_t&gt;‎</code> للأنواع التي نريدها على اليمين واليسار.
</p>

<p>
	ستزيد المكتبةُ تحميل <code>‎lhs*append_t‎</code> لإعادة كائن <code>‎half_apply‎</code> مؤقّت، كما أنها ستزيد تحميل <code>‎half_apply*rhs‎</code> لاستدعاء <code>‎named_invoke( lhs, append_t, rhs )‎</code>.
</p>

<p>
	ويجب أن ننشئ مفتاح <code>‎append_t‎</code> ليستدعي التوقيع المناسب عبر <code>‎named_invoke‎</code> متوافق مع البحث القائم على العامل (ADL-friendly) .
</p>

<p>
	لنفترض الآن أنّك تريد إجراء عملية ضرب عنصرًا بعنصر العناصر المصفوفة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6826_27" style="">
<span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pun">=</span><span class="kwd">void</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pun">...</span><span class="typ">Is</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> indexer</span><span class="pun">(</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">index_sequence</span><span class="pun">&lt;</span><span class="typ">Is</span><span class="pun">...&gt;</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">[](</span><span class="kwd">auto</span><span class="pun">&amp;&amp;</span><span class="pln"> f</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> f</span><span class="pun">(</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">integral_constant</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Is</span><span class="pun">&gt;{}...</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> N</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> indexer</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> indexer</span><span class="pun">(</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">make_index_sequence</span><span class="pun">&lt;</span><span class="pln">N</span><span class="pun">&gt;{}</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

</span><span class="kwd">namespace</span><span class="pln"> my_ns </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">e_times_t</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> named_operator</span><span class="pun">::</span><span class="pln">make_operator</span><span class="str">&lt;e_times_t&gt;</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">constexpr</span><span class="pln"> </span><span class="typ">e_times_t</span><span class="pln"> e_times</span><span class="pun">{};</span><span class="pln">

</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> L</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> R</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> N</span><span class="pun">,</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Out</span><span class="pun">=</span><span class="pln">std</span><span class="pun">::</span><span class="typ">decay_t</span><span class="pun">&lt;</span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">declval</span><span class="pun">&lt;</span><span class="pln">L </span><span class="kwd">const</span><span class="pun">&amp;&gt;()*</span><span class="pln">std</span><span class="pun">::</span><span class="pln">declval</span><span class="pun">&lt;</span><span class="pln">R </span><span class="kwd">const</span><span class="pun">&amp;&gt;()</span><span class="pln"> </span><span class="pun">)&gt;</span><span class="pln">
</span><span class="pun">&gt;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">array</span><span class="pun">&lt;</span><span class="typ">Out</span><span class="pun">,</span><span class="pln"> N</span><span class="pun">&gt;</span><span class="pln"> named_invoke</span><span class="pun">(</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">array</span><span class="pun">&lt;</span><span class="pln">L</span><span class="pun">,</span><span class="pln"> N</span><span class="pun">&gt;</span><span class="pln"> </span><span class="kwd">const</span><span class="pun">&amp;</span><span class="pln"> lhs</span><span class="pun">,</span><span class="pln"> </span><span class="typ">e_times_t</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">array</span><span class="pun">&lt;</span><span class="pln">R</span><span class="pun">,</span><span class="pln"> N</span><span class="pun">&gt;</span><span class="pln"> </span><span class="kwd">const</span><span class="pun">&amp;</span><span class="pln">
rhs </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> result_type </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">array</span><span class="pun">&lt;</span><span class="typ">Out</span><span class="pun">,</span><span class="pln"> N</span><span class="pun">&gt;;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> index_over_N </span><span class="pun">=</span><span class="pln"> indexer</span><span class="pun">&lt;</span><span class="pln">N</span><span class="pun">&gt;();</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> index_over_N</span><span class="pun">([&amp;](</span><span class="kwd">auto</span><span class="pun">...</span><span class="pln">is</span><span class="pun">)-&gt;</span><span class="pln">result_type </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">{{</span><span class="pln">
</span><span class="pun">(</span><span class="pln">lhs</span><span class="pun">[</span><span class="pln">is</span><span class="pun">]</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> rhs</span><span class="pun">[</span><span class="pln">is</span><span class="pun">])...</span><span class="pln">
</span><span class="pun">}};</span><span class="pln">    
</span><span class="pun">});</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<a data-ss1617022517="1" href="coliru.stacked-crooked.com/a/c071a0662834c838" rel="">هذا مثال حيّ</a> على ذلك.
</p>

<p>
	يمكن توسيع هذه الشيفرة لتعمل على الصفوف (tuples) أو الأزواج أو المصفوفات الشبيهة بـ C، أو حتى الحاويات متغيّرة الطول. كذلك تستطيع استخدام عامل نوعي عنصري (element-wise operator type) والحصول منه على <code>‎lhs *element_wise&lt;'+'&gt;* rhs‎</code>. أيضًا من الممكن استخدام عامِلا الضرب <code>‎*dot*‎</code> و <code>‎*cross*‎</code>.
</p>

<p>
	يمكن توسيع استخدام <code>‎*‎</code> ليدعم مُحدّدات (delimiters) أخرى مثل <code>‎+‎</code>، وتُحدّد أسبقيةُ المُحدّد أسبقيةَ العامِل المسمَّى، وذلك مفيد عند استخدام معادلات الفيزياء في C++‎ إذ لن تحتاج إلّا إلى الحد الأدنى من أقواس <code>‎()‎</code> .
</p>

<p>
	نستطيع دعم عوامل <code>‎-&gt;*then*‎</code> بتغيير طفيف على المكتبة أعلاه، وكذلك توسيع <code>‎std::function‎</code> قبل المعيار الذي يتم تحديثه، أو كتابة <code>‎-&gt;*bind*‎</code> أُحاديّ، بل يمكننا الحصول على عامل مُسمّى إذ نمرِّر العامل <code>‎Op‎</code> إلى دالّة الاستدعاء النهائية، مما يسمح بما يلي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6826_29" style="">
<span class="pln">named_operator </span><span class="pun">&lt;</span><span class="pln"> </span><span class="str">'*'</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> append </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[](</span><span class="kwd">auto</span><span class="pln"> lhs</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> rhs</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">using</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">begin</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">using</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">end</span><span class="pun">;</span><span class="pln">
    lhs</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="pln">end</span><span class="pun">(</span><span class="pln">lhs</span><span class="pun">),</span><span class="pln"> begin</span><span class="pun">(</span><span class="pln">rhs</span><span class="pun">),</span><span class="pln"> end</span><span class="pun">(</span><span class="pln">rhs</span><span class="pun">));</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">move</span><span class="pun">(</span><span class="pln">lhs</span><span class="pun">);</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	مما ينتج عنه إنشاء عامل مسمّى ومضيف للحاويات في C++‎ 17.
</p>

<h2>
	العوامل الأحادية (Unary Operators)
</h2>

<p>
	العاملان الأحاديان التاليان يمكن زيادة تحميلهما:
</p>

<ul>
<li>
		<code>‎‎</code>++foo و foo++<code>‎‎</code>
	</li>
	<li>
		<code>--foo</code> و <code>foo--</code> ويكون التحميل مُتماثل بالنسبة لكلا النوعين (<code>‎++‎</code> و <code>‎--‎</code>)، ولزيادة التحميل خارج الصنف (<code>‎class‎</code>) أو البنية (<code>‎struct‎</code>):
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6826_31" style="">
<span class="com">// ++foo العامل المسبق</span><span class="pln">
T </span><span class="pun">&amp;</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">++(</span><span class="pln">T </span><span class="pun">&amp;</span><span class="pln"> lhs</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// إجراء عملية الجمع</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> lhs</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يجب أن يُستخدم العامل المسبق <code>++foo</code> -يُستخدم وسيط <code>int</code> لفصل المُسبِق <code>pre</code> عن اللاحق <code>postfix</code>- بواسطة العامل المسبق <code>foo++</code>، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6826_33" style="">
<span class="pln">T </span><span class="kwd">operator</span><span class="pun">++(</span><span class="pln">T </span><span class="pun">&amp;</span><span class="pln"> lhs</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    T t</span><span class="pun">(</span><span class="pln">lhs</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">++</span><span class="pln">lhs</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> t</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	التحميل الزائد داخل الصنف (<code>‎class‎</code>) أو البنية (<code>‎struct‎</code>):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6826_35" style="">
<span class="com">// ++foo العامل المسبق</span><span class="pln">
T </span><span class="pun">&amp;</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">++()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// إجراء عملية الجمع</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="kwd">this</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	كما فعلنا قبل قليل، يجب أن يُستخدم <code>++foo</code> -يُستخدم وسيط <code>int</code> لفصل المُسبِق <code>pre</code> عن اللاحق <code>postfix</code>- بواسطة <code>foo++</code>، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6826_37" style="">
<span class="pln">T </span><span class="kwd">operator</span><span class="pun">++(</span><span class="typ">int</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    T t</span><span class="pun">(</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">++(</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> t</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<strong>ملاحظة</strong>: يعيد العامل المسبق مرجعًا إلى نفسه حتى يمكنك متابعة العمليات عليه، ويكون الوسيط الأول مرجعًا إذ أنّ العامل المسبق يغيّر الكائن، وهذا سبب في كونه غير ثابت <code>‎const‎</code>، إذ لم تكن لتستطيع تعديله إن كان غير ذلك.
</p>

<p>
	يُعيد العامل المُلحق (postﬁx operator) قيمة مؤقتة -القيمة السابقة-، وعليه لا يمكن أن يكون مرجعًا لأنه سيكون مرجعًا إلى قيمة مؤقتة، والتي ستكون قيمة مُهملة (garbage value) في نهاية الدالّة لأنّ المتغيرات المؤقتة تخرج عن النطاق، كذلك لا يمكن أن تكون ثابتة إذ يُفترض أن تستطيع تعديلها مباشرةً.
</p>

<p>
	واعلم أن الوسيط الأوّل هو مرجع غير ثابت للكائن المُستدعِي، لأنه لو كان ثابتًا فلن تتمكّن من تعديله، وإذا لم يكن مرجعًا، فلن يكون بمقدورك تغيير القيمة الأصلية.
</p>

<p>
	يُفضل استخدام السابقة ++ بدلاً من اللاحقة ++ في [حلقات](رابط الفصل 11) <code>‎for‎</code> بسبب عملية النسخ (copying) الضرورية في تحميلات العامل المُلحق. ورغم تكافئ الاثنتين وظيفيًا من منظور [حلقة](رابط الفصل 11) <code>‎for‎</code>، إلا أنه قد تكون هناك ميزة طفيفة في الأداء عند استخدام السابقة ++، وخاصة في الأصناف "الكبيرة" التي تحتوي الكثير من الأعضاء الواجب نسخها. انظر المثال التالي على استخدام السابقة ++ في حلقة for:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6826_39" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">list</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> string </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="typ">const_iterator</span><span class="pln"> it </span><span class="pun">=</span><span class="pln"> tokens</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">();</span><span class="pln"> it </span><span class="pun">!=</span><span class="pln"> tokens</span><span class="pun">.</span><span class="pln">end</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">++</span><span class="pln">it</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">// it++ لا تستخدم</span><span class="pln">
    </span><span class="pun">...</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	عوامل الموازنة (Comparison operators)
</h2>

<p>
	يمكنك زيادة تحميل جميع عوامل المقارنة:
</p>

<ul>
<li>
		<code>‎==‎</code> و <code>‎!=‎</code>
	</li>
	<li>
		<code>‎&gt;‎</code> و <code>‎&lt;‎</code>
	</li>
	<li>
		<code>‎&gt;=‎</code> و <code>‎&lt;=‎</code>
	</li>
</ul>
<p>
	الطريقة الموصى بها لزيادة تحميل كل هذه العوامل هي باستخدام العامليْن (<code>‎==‎</code> و <code>‎&lt;‎</code>) فقط، ثمّ استخدَامِهما لتعريف الباقي. انظر المثال التالي للتحميل خارج الصنف أو البنية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6826_41" style="">
<span class="com">// لا تستخدم إلا هذين العامليْن</span><span class="pln">
</span><span class="kwd">bool</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> T </span><span class="pun">&amp;</span><span class="pln"> lhs</span><span class="pun">,</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> T </span><span class="pun">&amp;</span><span class="pln"> rhs</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">/* Compare */</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="kwd">bool</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> T </span><span class="pun">&amp;</span><span class="pln"> lhs</span><span class="pun">,</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> T </span><span class="pun">&amp;</span><span class="pln"> rhs</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">/* Compare */</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="com">// الآن يمكنك تعريف الباقي</span><span class="pln">
</span><span class="kwd">bool</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">!=</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> T </span><span class="pun">&amp;</span><span class="pln"> lhs</span><span class="pun">,</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> T </span><span class="pun">&amp;</span><span class="pln"> rhs</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">!(</span><span class="pln">lhs </span><span class="pun">==</span><span class="pln"> rhs</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">bool</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> T </span><span class="pun">&amp;</span><span class="pln"> lhs</span><span class="pun">,</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> T </span><span class="pun">&amp;</span><span class="pln"> rhs</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> rhs </span><span class="pun">&lt;</span><span class="pln"> lhs</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">bool</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> T</span><span class="pun">&amp;</span><span class="pln"> lhs</span><span class="pun">,</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> T</span><span class="pun">&amp;</span><span class="pln"> rhs</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">!(</span><span class="pln">lhs </span><span class="pun">&gt;</span><span class="pln"> rhs</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">bool</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">&gt;=</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> T</span><span class="pun">&amp;</span><span class="pln"> lhs</span><span class="pun">,</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> T</span><span class="pun">&amp;</span><span class="pln"> rhs</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">!(</span><span class="pln">lhs </span><span class="pun">&lt;</span><span class="pln"> rhs</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	زيادة التحميل داخل الصنف أو البنية، لاحظ أن الدوال ثابتة، ذلك أنه إن لم تكن كذلك فلن تستطيع استدعاءها إن كان الكائن ثابتًا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6826_43" style="">
<span class="com">// لا تستخدم إلا هذين العاملين</span><span class="pln">
</span><span class="kwd">bool</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> T</span><span class="pun">&amp;</span><span class="pln"> rhs</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">/* Compare */</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="kwd">bool</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> T</span><span class="pun">&amp;</span><span class="pln"> rhs</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">/* Compare */</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="com">// الآن يمكنك تعريف الباقي</span><span class="pln">
</span><span class="kwd">bool</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">!=</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> T</span><span class="pun">&amp;</span><span class="pln"> rhs</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">!(</span><span class="pln"> </span><span class="pun">*</span><span class="kwd">this</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> rhs</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">bool</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> T</span><span class="pun">&amp;</span><span class="pln"> rhs</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> rhs </span><span class="pun">&lt;</span><span class="pln"> </span><span class="pun">*</span><span class="kwd">this</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">bool</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> T</span><span class="pun">&amp;</span><span class="pln"> rhs</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">!(</span><span class="pln"> </span><span class="pun">*</span><span class="kwd">this</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> rhs</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">bool</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">&gt;=</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> T</span><span class="pun">&amp;</span><span class="pln"> rhs</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">!(</span><span class="pln"> </span><span class="pun">*</span><span class="kwd">this</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> rhs</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	من الواضح أنّ العوامل ستعيد قيمة منطقية (<code>‎bool‎</code>)، أي إمّا <code>‎true‎</code> أو <code>‎false‎</code>. تأخذ جميع العوامل وسائطها كمراجع ثابتة (<code>‎const&amp;‎</code>) لأنّ الشيء الوحيد الذي تفعله هذه العوامل هو المقارنة، لذلك لا ينبغي لها تعديل الكائنات. لاحظ أن التمرير بالمرجع (<code>‎&amp;‎</code>) أسرع من التمرير بالقيمة (by value)، ويكون مرجعًا ثابتًا <code>const</code> للتأكد من أنّ العوامل لن تعدّله.
</p>

<p>
	كذلك، لاحظ أنّ العوامل داخل الأصناف والبنيات تكون ثابتة، لأن الدوالّ إن لم تكن ثابتة فلن يمكننا مقارنة الكائنات الثابتة، لأنّ المصرّف لا يعلم أنّ العوامل لا تغيّر شيئًا.
</p>

<h2>
	عامل الإسناد (Assignment Operator)
</h2>

<p>
	تكمن أهمية عامل الإسناد في أنه يتيح لك تغيير حالة المتغير، وإذا لم تزد تحميل عامل الإسناد في الصنف أو البنية فسيُنشئه المصرِّف تلقائيًا، ويُجري عامل الإسناد المُنشأ تلقائيًا عملية "الإسناد عضوًا بعضو" (memberwise assignment)، أي عن طريق استدعاء عوامل الإسناد على جميع الأعضاء، بحيث يُنسخ كائن إلى آخر، عضوًا بعضو. يجب زيادة تحميل عامل الإسناد عندما لا تكون عملية الإسناد عضوًا بعضو مناسبة للصنف أو البنية خاصتك، كأن تكون بحاجة إلى تنفيذ نسخ عميق (deep copy) لكائن ما.
</p>

<p>
	زيادة تحميل عامل الإسناد <code>‎=‎</code> سهل، لكن عليك اتباع بعض الخطوات البسيطة.
</p>

<ol>
<li>
		<strong>اختبار الإسناد الذاتي (Test for self-assignment)</strong>. هذا الاختبار مهم لسببين:
	</li>
</ol>
<ul>
<li>
		الإسناد الذاتي عملية نسخ لا داعي لها، لذلك ليس من المنطقي إجراؤها.
	</li>
	<li>
		لن تنجح الخطوة التالية في حال استخدام الإسناد الذاتي.
	</li>
</ul>
<ol>
<li>
		<strong>تنظيف البيانات القديمة</strong>. يجب استبدال البيانات الجديدة بالبيانات القديمة. ربما تفهم الآن السبب الثاني في الخطوة السابقة إذ أنه في حال حذف محتوى الكائن فستفشل عملية الإسناد الذاتي في تنفيذ عملية النسخ.
	</li>
	<li>
		<strong>نسخ جميع الأعضاء</strong>. إذا زدت تحميل عامل الإسناد في صنفك أو بنيتك فلن يُنشأ تلقائيًا بواسطة المُصرّف، لذلك سيقع على عاتقك مسؤولية نسخ جميع الأعضاء من الكائن الآخر.
	</li>
	<li>
		<strong>إعادة <code>‎*this‎</code></strong>. يُعيد العامل مرجعًا إليه لأجل السماح بالعمليات المتسلسلة (أي <code>int b = (a = 6)‎ +‎ 4;</code>).
	</li>
</ol>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6826_45" style="">
<span class="com">// يمثل نوعا ما T </span><span class="pln">
T </span><span class="pun">&amp;</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> T </span><span class="pun">&amp;</span><span class="pln"> other</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// افعل شيئا ما</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="kwd">this</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<strong>ملاحظة</strong>: يُمرّر <code>‎other‎</code> بمرجع ثابت (<code>‎const&amp;‎</code>) لأنه لا ينبغي تغيير الكائن الذي يتم تعيينه، كما أنّ التمرير بالمرجع أسرع من التمرير بالقيمة، وينبغي جعل <code>‎operator=‎</code> ثابتًا <code>const</code> للتأكد أنه لن يعدّلها عن طريق الخطأ.
</p>

<p>
	لا يمكن زيادة تحميل عامل الإسناد إلا في الأصناف والبنيات، لأنّ القيمة اليسرى لـ <code>‎=‎</code> تكون دائمًا هي الصنفَ أو البنيةَ نفسها، ولا يضمن تعريف العامل كدالّة حرّة (free function) ذلك، لهذا لا يُسمح به.
</p>

<p>
	تكون القيمة اليسرى هي الصنف أو البُنية بنفسها بشكل ضمني عند التصريح عنها في صنف أو بُنية، لذا لا توجد مشكلة في ذلك.
</p>

<h2>
	عامل استدعاء الدالّة (Function call operator)
</h2>

<p>
	يمكنك زيادة تحميل عامل استدعاء الدالّة <code>‎()‎</code>، ويجب أن تحدث زيادة التحميل داخل صنف أو بنية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6826_47" style="">
<span class="com">//R &lt;- نوع القيمة المعادة</span><span class="pln">
R </span><span class="kwd">operator</span><span class="pun">()(</span><span class="typ">Type</span><span class="pln"> name</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Type2</span><span class="pln"> name2</span><span class="pun">,</span><span class="pln"> </span><span class="pun">...)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// افعل شيئا ما</span><span class="pln">
    </span><span class="com">// إعادة قيمة</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="com">// استخدمه هكذا</span><span class="pln">
R foo </span><span class="pun">=</span><span class="pln"> object</span><span class="pun">(</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> b</span><span class="pun">,</span><span class="pln"> </span><span class="pun">...);</span></pre>

<p>
	مثلا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6826_49" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Sum</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">()(</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> a </span><span class="pun">+</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="com">// انشاء نسخة من البنية</span><span class="pln">
</span><span class="typ">Sum</span><span class="pln"> sum</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> result </span><span class="pun">=</span><span class="pln"> sum</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span><span class="pln"> </span><span class="com">//  2</span></pre>

<h2>
	عامل NOT الثنائي (Bitwise NOT operator)
</h2>

<p>
	زيادة تحميل عامل NOT الثنائي (<code>‎~‎</code>) بسيط إلى حد ما. انظر المثال التالي لزيادة التحميل خارج الصنف أو البنية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6826_51" style="">
<span class="pln">T </span><span class="kwd">operator</span><span class="pun">~(</span><span class="pln">T lhs</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// نفذ العملية</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> lhs</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	التحميل الزائد داخل الصنف أو البنية <code>‎class‎</code> / <code>‎struct‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6826_53" style="">
<span class="pln">T </span><span class="kwd">operator</span><span class="pun">~()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    T t</span><span class="pun">(</span><span class="pln"> </span><span class="pun">*</span><span class="kwd">this</span><span class="pun">);</span><span class="pln">
    </span><span class="com">// نفذ العملية</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> t</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<strong>ملاحظة</strong>: يعيد عامل <code>‎operator~‎</code> بالقيمة (by value) لأنّ عليه أن يُعيد قيمة جديدة (القيمة المُعدّلة) وليس مرجعًا إلى القيمة -سيكون مرجعًا إلى الكائن المؤقّت الذي ستصبح قيمته مُهملة [محذوفة] بمجرد تنفيذ العامل-، كما أنها لا ينبغي أن تكون ثابتة لأنّ شيفرة الاستدعاء يجب أن تكون قادرة على تعديله بعد ذلك (أي يجب أن تكون العبارة ‎<code>int a = ~a+ 1;‎</code>‎ ممكنة).
</p>

<p>
	يجب عليك إنشاء كائن مؤقت داخل الصنف أو البنية، إذ لا يمكنك تعديل <code>‎this‎</code>، لأنه سيؤدي إلى تعديل الكائن الأصلي، وهو ما لا ينبغي أن يحدث.
</p>

<h2>
	عوامل الإزاحة البِتيّة للدخل/الخرج (Bit shift operators for I/O)
</h2>

<p>
	يشيع استخدام العامليْن <code>‎&lt;&lt;‎</code> و <code>‎&gt;&gt;‎</code> كعوامل للكتابة والقراءة، على الترتيب.
</p>

<ul>
<li>
		<code>std::ostream</code> تزيد تحميل <code>‎&lt;&lt;‎</code> لكتابة المتغيرات في [المجرى](رابط الفصل 13) الأساسي (على سبيل المثال: <code>std::cout</code>)
	</li>
	<li>
		<code>std::istream</code> تزيد تحميل <code>‎&gt;&gt;‎</code> للقراءة من [المجرى](رابط الفصل 13) الأساسي إلى متغير (على سبيل المثال: <code>std::cin</code>)
	</li>
</ul>
<p>
	ويتماثل أسلوبهما في حال أردت زيادة تحميلهما "بشكل طبيعي" خارج الصنف أو البنية، باستثناء أنّ الوسائط ليست من نفس النوع:
</p>

<ul>
<li>
		نوع القيمة المُعادة هو [المجرى](رابط الفصل 13) الذي تريد زيادة التحميل منه - overload from - (على سبيل المثال، <code>‎std::ostream‎</code>)، والذي يُمرّر بالمرجع (by reference) للسماح بالعمليات المتسلسلة (التسلسل: <code>‎std::cout &lt;&lt; a &lt;&lt; b;‎</code>). مثال: <code>‎std::ostream&amp;‎</code>
	</li>
	<li>
		<code>‎lhs‎</code> سيكون من نفس نوع القيمة المعادة.
	</li>
	<li>
		<code>‎rhs‎</code> تمثّل النوع الذي تريد السماح بالتحميل منه (على سبيل المثال <code>‎T‎</code>)، والذي يُمرَّر بمرجع ثابت بدلاً من تمريره بالقيمة لأسباب تتعلّق بالأداء (لا ينبغي تغيير <code>‎rhs‎</code> على أيّ حال). مثال: <code>‎const Vector&amp;‎</code>. انظر المثال التالي حيث نزيد تحميل <code>&gt;&gt;std::ostream operator</code> للسماح بالخرج من المتجه:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6826_55" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">ostream</span><span class="pun">&amp;</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">&lt;&lt;(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">ostream</span><span class="pun">&amp;</span><span class="pln"> lhs</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Vector</span><span class="pun">&amp;</span><span class="pln"> rhs</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    lhs </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"x: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> rhs</span><span class="pun">.</span><span class="pln">x </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" y: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> rhs</span><span class="pun">.</span><span class="pln">y </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" z: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> rhs</span><span class="pun">.</span><span class="pln">z </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> lhs</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="typ">Vector</span><span class="pln"> v </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="lit">1</span><span class="pun">,</span><span class="pln">
    </span><span class="lit">2</span><span class="pun">,</span><span class="pln">
    </span><span class="lit">3</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="com">// الآن يمكنك فعل ما يلي</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> v</span><span class="pun">;</span></pre>

<p>
	هذا الدرس جزء من <a data-ss1617022517="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة مقالات عن C++‎</a>.
</p>

<p>
	ترجمة -بتصرّف- للفصل Chapter 36: Operator Overloading من كتاب <a data-ss1617022517="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">935</guid><pubDate>Wed, 15 Jul 2020 18:04:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x62A;&#x62D;&#x645;&#x64A;&#x644; &#x627;&#x644;&#x632;&#x627;&#x626;&#x62F; Overloading: &#x62A;&#x62D;&#x644;&#x64A;&#x644;&#x647; &#x648;&#x62A;&#x637;&#x628;&#x64A;&#x642;&#x647; &#x639;&#x644;&#x649; &#x627;&#x644;&#x62F;&#x648;&#x627;&#x644; &#x641;&#x64A; Cpp</title><link>https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AA%D8%AD%D9%85%D9%8A%D9%84-%D8%A7%D9%84%D8%B2%D8%A7%D8%A6%D8%AF-overloading-%D8%AA%D8%AD%D9%84%D9%8A%D9%84%D9%87-%D9%88%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D9%87-%D8%B9%D9%84%D9%89-%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-%D9%81%D9%8A-cpp-r934/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_06/22.jpg.e15e56b77fea233d76f9b75b84479334.jpg" /></p>

<h2>
	تصنيف كلفة تمرير وسيط إلى معامل
</h2>

<p>
	يقسم تحليل التحميل الزائد تكلفة تمرير وسيط (argument) إلى مُعامل (parameter) إلى 4 تصنيفات مختلفة، تُسمّى "تسلسلات" (sequences)، وقد يتضمن كل تسلسل صفرًا أو واحدًا أو عدّة تحويلات.
</p>

<ul>
<li>
		تسلسل التحويل القياسي Standard conversion sequence
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_7" style="">
<span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">);</span><span class="pln">
f</span><span class="pun">(</span><span class="lit">42</span><span class="pun">);</span></pre>

<ul>
<li>
		تسلسل التحويل المُعرّف من قبل المستخدم User defined conversion sequence
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_9" style="">
<span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string s</span><span class="pun">);</span><span class="pln">
f</span><span class="pun">(</span><span class="str">"hello"</span><span class="pun">);</span></pre>

<ul>
<li>
		تسلسل تحويل علامة الحذف Ellipsis conversion sequence:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_11" style="">
<span class="kwd">void</span><span class="pln"> f</span><span class="pun">(...);</span><span class="pln">
f</span><span class="pun">(</span><span class="lit">42</span><span class="pun">);</span></pre>

<ul>
<li>
		تسلسل قائمة التهيئة:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_13" style="">
<span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v</span><span class="pun">);</span><span class="pln">
f</span><span class="pun">({</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">});</span></pre>

<p>
	المبدأ العام هو أنّ تسلسلات التحويل القياسية هي الأقل كلفة، يليها تسلسل التحويل المُعرَّف من المستخدم، يليها تسلسل تحويل علامة الحذف.
</p>

<p>
	أما تسلسل قائمة التهيئة فهي حالة خاصة، إذ أنّها ليست تحويلًا -قائمة المهيئ ليست تعبيرًا ذا نوع- تُحسب كُلفتها عن طريق تعريفها على أنّها تكافئ إحدى تسلسلات التحويل الثلاثة الأخرى، وذلك اعتمادًا على نوع المُعامل وشكل قائمة المهيئ.
</p>

<h2>
	الترقيات والتحويلات الحسابية Arithmetic promotions and conversions
</h2>

<p>
	يُعدّ تحويل نوع عددي صحيح إلى نوع مُرقّى (promoted type) مقابل له أفضل من تحويله إلى نوع عددِي صحيح آخر.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_15" style="">
<span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="kwd">short</span><span class="pln"> x</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">signed</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> c </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span><span class="pln">
f</span><span class="pun">(</span><span class="pln">c</span><span class="pun">);</span><span class="pln">    </span><span class="com">// short  أفضل من التحويل إلى int الترقية إلى</span><span class="pln">
</span><span class="kwd">short</span><span class="pln"> s </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span><span class="pln">
f</span><span class="pun">(</span><span class="pln">s</span><span class="pun">);</span><span class="pln">    </span><span class="com">// int التطابق التام أفضل من الترقية إلى</span></pre>

<p>
	كذلك ترقية <code>‎float‎</code> إلى <code>‎double‎</code> أفضل من تحويله إلى نوع عددِي عشري آخر.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_17" style="">
<span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="kwd">double</span><span class="pln"> x</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="kwd">long</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> x</span><span class="pun">);</span><span class="pln">
f</span><span class="pun">(</span><span class="lit">3.14</span><span class="pln"> f</span><span class="pun">);</span><span class="pln">    </span><span class="com">// calls f(double); long double أفضل من التحويل إلى double الترقية إلى</span></pre>

<p>
	تتكافأ التحويلات الحسابية الأخرى، بخلاف الترقيات.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_19" style="">
<span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="typ">float</span><span class="pln"> x</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="kwd">long</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> x</span><span class="pun">);</span><span class="pln">
f</span><span class="pun">(</span><span class="lit">3.14</span><span class="pun">);</span><span class="pln">    </span><span class="com">// غامض</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> g</span><span class="pun">(</span><span class="kwd">long</span><span class="pln"> x</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> g</span><span class="pun">(</span><span class="kwd">long</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> x</span><span class="pun">);</span><span class="pln">
g</span><span class="pun">(</span><span class="lit">42</span><span class="pun">);</span><span class="pln">    </span><span class="com">// غامض</span><span class="pln">
g</span><span class="pun">(</span><span class="lit">3.14</span><span class="pun">);</span><span class="pln">    </span><span class="com">// غامض</span></pre>

<p>
	لذلك، من أجل ضمان رفع أيّ لبس عند استدعاء دالة <code>‎f‎</code> سواء مع وسائط عددية صحيحة أو عشرية من أيّ نوع قياسي، فستحتاج لكتابة ثمانية تحميلات زائدة، بحيث يحدث تطابق تام مع التحميل الزائد أو يُختار التحميل الزائد ذو نوع الوسيط المُرقّى (promoted argument type)، مهما كان نوع الوسيط.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_21" style="">
<span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="kwd">unsigned</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> x</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="kwd">long</span><span class="pln"> x</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="kwd">unsigned</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> x</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="kwd">long</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> x</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="kwd">unsigned</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> x</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="kwd">double</span><span class="pln"> x</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="kwd">long</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> x</span><span class="pun">);</span></pre>

<h2>
	التحميل الزائد على مرجع إعادة توجيه Forwarding Reference
</h2>

<p>
	يجب أن تكون حذرًا عند توفير تحميل زائد لمرجع إعادة توجيه (forwarding reference) لأنّه قد يكون تامَّ التطابق:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_23" style="">
<span class="kwd">struct</span><span class="pln"> A </span><span class="pun">{</span><span class="pln">
A</span><span class="pun">()</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">default</span><span class="pun">;</span><span class="pln"> </span><span class="com">// #1</span><span class="pln">
A</span><span class="pun">(</span><span class="pln">A </span><span class="kwd">const</span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">default</span><span class="pun">;</span><span class="pln"> </span><span class="com">// #2</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
A</span><span class="pun">(</span><span class="pln">T</span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// #3</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	والقصد هنا هو أنّ <code>‎A‎</code> قابلة للنسخ، وأنّ لدينا منشئًا آخر يمكنه أن يهيّئ عضوًا آخر. انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_25" style="">
<span class="pln">A a</span><span class="pun">;</span><span class="pln">    </span><span class="com">// #1 استدعاء</span><span class="pln">
A b</span><span class="pun">(</span><span class="pln">a</span><span class="pun">);</span><span class="pln">    </span><span class="com">// #3! استدعاء</span></pre>

<p>
	هناك تطابُقان صالحان لاستدعاء الإنشاء:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_27" style="">
<span class="pln">A</span><span class="pun">(</span><span class="pln">A </span><span class="kwd">const</span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">);</span><span class="pln"> </span><span class="com">// #2</span><span class="pln">
A</span><span class="pun">(</span><span class="pln">A</span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">);</span><span class="pln">           </span><span class="com">// #3, مع T = A&amp;</span></pre>

<p>
	كلاهما مُطابِقان بشكل تام، لكن <code>‎#3‎</code> تأخذ مرجعًا إلى كائن تأهيله أقل من <code>‎#2‎</code>، لذا فهو أكثر امتثالًا لتسلسل التحويل القياسي، وأكثر تطابقًا، والحل هنا هو تقييد هذه المنشآت دائمًا (على سبيل المثال باستخدام قاعدة SFINAE):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_29" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">,</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">enable_if_t</span><span class="pun">&lt;!</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_convertible</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="typ">decay_t</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;*,</span><span class="pln"> A</span><span class="pun">*&gt;::</span><span class="pln">value</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> A</span><span class="pun">(</span><span class="pln">T</span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="pun">);</span></pre>

<p>
	وما نريده هنا هو استبعاد أيّ نوع <code>‎A‎</code> أو صنف مُشتقّ علنًا (publicly) من <code>‎A‎</code> من نظرنا، ونتيجة لذلك تصبح صيغة هذا المنشئ غير صحيحة في المثال المُوضّح سابقًا (وعليه يُزال من مجموعة التحميل الزائد). لذا سيُستدعى مُنشئ النسخ، وهو الذي أردنا.
</p>

<h2>
	التطابق التام
</h2>

<p>
	يفضَّل التحميل الزائد الذي لا يحتاج إلى تحويل أنواع المعاملات أو الذي يحتاج فقط إلى التحويلات بين الأنواع التي تُعدُّ مُتطابقة بشكل تام، على التحميل الزائد الذي يتطّلب تحويلات أخرى قبل إجراء الاستدعاء.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_31" style="">
<span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="kwd">double</span><span class="pln"> x</span><span class="pun">);</span><span class="pln">
f</span><span class="pun">(</span><span class="lit">42</span><span class="pun">);</span><span class="pln">    </span><span class="com">// f(int) استدعاء</span></pre>

<p>
	عندما يرتبط وسيط بمرجع من نفس النوع، فإنّ المطابقة لن تتطّلب تحويلًا حتى لو كان المرجع ذا تأهيل ثباتي أعلى. انظر المثال التالي حيث يكون نوع الوسيط في <code>(f(x</code> هو <code>int</code>، وهو تطابق تام مع <code>&amp;int</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_33" style="">
<span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="typ">int</span><span class="pun">&amp;</span><span class="pln"> x</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="kwd">double</span><span class="pln"> x</span><span class="pun">);</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span><span class="pln">
f</span><span class="pun">(</span><span class="pln">x</span><span class="pun">);</span><span class="pln">   
</span><span class="kwd">void</span><span class="pln"> g</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pun">&amp;</span><span class="pln"> x</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> g</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">);</span><span class="pln">
g</span><span class="pun">(</span><span class="pln">x</span><span class="pun">);</span><span class="pln">    </span><span class="com">// غامض، كلا التحميلين الزائدين يعطيان تطابقا تاما</span></pre>

<p>
	يعد النوعان "مصفوفة تحتوي عناصر من النوع <code>‎T‎</code>" و "مؤشّر إلى <code>‎T‎</code>" متطابقين بشكل تام لغرض تحليل التحميل الزائد، كما يُعدُّ نوع الدالّة <code>‎T‎</code> مطابقًا تمامًا لنوع مؤشّر الدالّة <code>‎T*‎</code>، رغم أنّ كليهما يتطّلبان إجراء تحويلات .
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_35" style="">
<span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="typ">int</span><span class="pun">*</span><span class="pln"> p</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="kwd">void</span><span class="pun">*</span><span class="pln"> p</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> g</span><span class="pun">(</span><span class="typ">int</span><span class="pun">*</span><span class="pln"> p</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> g</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> </span><span class="pun">(&amp;</span><span class="pln">p</span><span class="pun">)[</span><span class="lit">100</span><span class="pun">]);</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">[</span><span class="lit">100</span><span class="pun">];</span><span class="pln">
f</span><span class="pun">(</span><span class="pln">a</span><span class="pun">);</span><span class="pln">    </span><span class="com">// f(int*); تطابق تام، مع تحويل من مصفوفة إلى مؤشّر</span><span class="pln">
g</span><span class="pun">(</span><span class="pln">a</span><span class="pun">);</span><span class="pln">    </span><span class="com">// غامض، كلا التحويلين الزائدين يعطيان تطابقا تاما</span></pre>

<h2>
	التحميل الزائد للثباتية constness والتغير volatility
</h2>

<p>
	يُعدّ تمرير وسيط مؤشّر (pointer argument) إلى مُعامل <code>‎T*‎</code> -إن أمكن- أفضل من تمريره إلى مُعامل <code>‎const T*‎</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_37" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Derived</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="typ">Base</span><span class="pun">*</span><span class="pln"> pb</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Base</span><span class="pun">*</span><span class="pln"> pb</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Derived</span><span class="pun">*</span><span class="pln"> pd</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="kwd">bool</span><span class="pln"> b</span><span class="pun">);</span><span class="pln">
</span><span class="typ">Base</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
f</span><span class="pun">(&amp;</span><span class="pln">b</span><span class="pun">);</span><span class="pln">  
</span><span class="typ">Derived</span><span class="pln"> d</span><span class="pun">;</span><span class="pln">
f</span><span class="pun">(&amp;</span><span class="pln">d</span><span class="pun">);</span><span class="pln">    </span></pre>

<p>
	تفسير الشيفرة السابقة:
</p>

<ul>
<li>
		في <code>(f(&amp;b</code>: تٌفضَّل <code>(*f(base</code> على <code>(*f(const base</code>.
	</li>
	<li>
		في <code>(f(&amp;d</code>: تٌفضَّل <code>(*f(const Derived</code> على <code>(*f(base</code>، رغم أن دور الثباتية ينحصر في كسر التعادل (tie-breaker).
	</li>
</ul>
<p>
	وبالمثل، يُعدّ تمرير وسيط إلى مُعامل <code>‎T&amp;‎</code> أفضل من تمريره إلى مُعامل <code>‎const T&amp;‎</code>، حتى لو كان لكليهما نفس التطابق (match rank).
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_39" style="">
<span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="typ">int</span><span class="pun">&amp;</span><span class="pln"> r</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pun">&amp;</span><span class="pln"> r</span><span class="pun">);</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
f</span><span class="pun">(</span><span class="pln">x</span><span class="pun">);</span><span class="pln">    </span><span class="com">// أفضل f(int&amp;) التحميلان مطابقان، لكنّ</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> y </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span><span class="pln">
f</span><span class="pun">(</span><span class="pln">y</span><span class="pun">);</span><span class="pln">    </span><span class="com">// هي المرشح الصالح f(const int&amp;) </span></pre>

<p>
	تنطبق هذه القاعدة أيضًا على الدوال التابعة المُؤهّلة ثباتيًا (const-qualiﬁed member functions)، التي تحتاج إلى السماح بالوصول المتغيّر (mutable access) إلى الكائنات غير الثابتة، والوصول الثابت (immutable access) إلى الكائنات الثابتة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_41" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">IntVector</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="com">// ...</span><span class="pln">
       </span><span class="typ">int</span><span class="pun">*</span><span class="pln"> data</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> m_data</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
       </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pun">*</span><span class="pln"> data</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> m_data</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
        </span><span class="com">// ...</span><span class="pln">
        </span><span class="typ">int</span><span class="pun">*</span><span class="pln"> m_data</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">IntVector</span><span class="pln"> v1</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pun">*</span><span class="pln"> data1 </span><span class="pun">=</span><span class="pln"> v1</span><span class="pun">.</span><span class="pln">data</span><span class="pun">();</span><span class="pln"> 
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">IntVector</span><span class="pln"> v2</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pun">*</span><span class="pln"> data2 </span><span class="pun">=</span><span class="pln"> v2</span><span class="pun">.</span><span class="pln">data</span><span class="pun">();</span><span class="pln">   </span></pre>

<p>
	تفسير الشيفرة السابقة:
</p>

<ul>
<li>
		<code>()Vector::data</code> أفضل من <code>Vector::data() const</code>، ويمكن استخدام <code>data1</code> لتعديل المتجه.
	</li>
	<li>
		<code>Vector::data() const</code> هي المرشح الصالح الوحيد، ولايمكن استخدام <code>data2</code> لتعديل المتجه.
	</li>
</ul>
<p>
	كذلك فإن التحميل الزائد غير المتغيّر (non-volatile overload) أفضل من التحميل الزائد المتغيّر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_43" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">AtomicInt</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="com">// ...</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> load</span><span class="pun">();</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> load</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">volatile</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
        </span><span class="com">// ...</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">AtomicInt</span><span class="pln"> a1</span><span class="pun">;</span><span class="pln">
a1</span><span class="pun">.</span><span class="pln">load</span><span class="pun">();</span><span class="pln">    </span><span class="com">// يُفضَّل التحميل الزائد غير المتغير، لايوجد آثار جانبية</span><span class="pln">
</span><span class="kwd">volatile</span><span class="pln"> </span><span class="typ">AtomicInt</span><span class="pln"> a2</span><span class="pun">;</span><span class="pln">
a2</span><span class="pun">.</span><span class="pln">load</span><span class="pun">();</span><span class="pln">    </span><span class="com">// التحويل الزائد المتغير هو الوحيد المرشّح، مع وجود آثار جانبية</span><span class="pln">
</span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">volatile</span><span class="pln"> </span><span class="typ">AtomicInt</span><span class="pln"> </span><span class="pun">&amp;&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">a1</span><span class="pun">).</span><span class="pln">load</span><span class="pun">();</span><span class="pln">   </span></pre>

<h2>
	البحث عن الاسماء والتحقق من الوصول
</h2>

<p>
	يحدث تحليل التحميل الزائد بعد البحث عن الاسم، هذا يعني أنّ تحليل التحميل الزائد قد لا يختار الدالّة الأكثر تطابقا في حال عدم العثور على اسمها. انظر المثال التالي حيث نستدعي <code>S::f</code> لأن <code>f</code> غير مرئية هنا، رغم أنها ستكون أكثر تطابقًا.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_45" style="">
<span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> S
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="kwd">double</span><span class="pln"> x</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> g</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        f</span><span class="pun">(</span><span class="lit">42</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">  
</span><span class="pun">};</span></pre>

<p>
	يحدث تحليل التحميل الزائد قبل التحقّق من الوصول، وقد تُختار دالّة غير مُتاحة للوصول من قبل تحليل التحميل الزائد بدلًا من دالة أخرى أقلّ تطابقًا ولو كانت متاحة للوصول.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_47" style="">
<span class="kwd">class</span><span class="pln"> C
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="kwd">double</span><span class="pln"> x</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">);</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
C</span><span class="pun">::</span><span class="pln">f</span><span class="pun">(</span><span class="lit">42</span><span class="pun">);</span></pre>

<p>
	في الشيفرة السابقة، تعطي <code>(C::f(42</code> خطأً، لأنها تستدعي <code>(private C::f(int</code> رغم أن (public C::f(double` صالحة.
</p>

<p>
	وبالمثل، لا يتحقّق تحليل التحميل الزائد ممّا إذا كانت صيغة <code>‎explicit‎</code> صحيحة في الاستدعاء الناتج:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_49" style="">
<span class="kwd">struct</span><span class="pln"> X
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">explicit</span><span class="pln"> X</span><span class="pun">(</span><span class="typ">int</span><span class="pun">);</span><span class="pln">
    X</span><span class="pun">(</span><span class="kwd">char</span><span class="pun">);</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">(</span><span class="pln">X</span><span class="pun">);</span><span class="pln">
foo</span><span class="pun">({</span><span class="pln"> </span><span class="lit">4</span><span class="pln"> </span><span class="pun">});</span><span class="pln">    </span><span class="com">// أكثر تطابقا، لكن التعبير سيء الصياغة، لأنّ المنشئ صريح X(int) </span></pre>

<h2>
	التحميل الزائد داخل التسلسل الهرمي للصنف
</h2>

<p>
	الأمثلة التالية سوف تستخدم هذا التسلسل الهرمي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_51" style="">
<span class="kwd">struct</span><span class="pln"> A
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> m</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> B</span><span class="pun">:</span><span class="pln"> A </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> C</span><span class="pun">:</span><span class="pln"> B </span><span class="pun">{};</span></pre>

<p>
	يُفضل التحويل من نوع صنف مشتق (derived class type) إلى نوع صنف أساسي (base class type) في التحويلات المُعرَّفة من قبل المستخدم، ينطبق هذا عند التمرير بالقيمة (by value) أو بالمرجع (by reference)، وكذلك عند تحويل مؤشّر يشير إلى صنف مشتق إلى مؤشّر آخر يشير إلى صنف أساسي.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_53" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Unrelated</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="typ">Unrelated</span><span class="pun">(</span><span class="pln">B b</span><span class="pun">);</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="pln">A a</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="typ">Unrelated</span><span class="pln"> u</span><span class="pun">);</span><span class="pln">
B b</span><span class="pun">;</span><span class="pln">
f</span><span class="pun">(</span><span class="pln">b</span><span class="pun">);</span><span class="pln">  </span><span class="com">// f(A) استدعاء</span></pre>

<p>
	يُعدّ تحويل المؤشّر من صنف مشتق إلى صنف أساسي أفضل من تحويله إلى <code>‎void*‎</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_55" style="">
<span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="pln">A</span><span class="pun">*</span><span class="pln"> p</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="kwd">void</span><span class="pun">*</span><span class="pln"> p</span><span class="pun">);</span><span class="pln">
B b</span><span class="pun">;</span><span class="pln">
f</span><span class="pun">(&amp;</span><span class="pln">b</span><span class="pun">);</span><span class="pln">    </span><span class="com">// f(A*) استدعاء</span></pre>

<p>
	إذا كانت هناك عدّة تحميلات زائدة داخل نفس التسلسل الوراثي، فستكون الأولوية للتحميل الزائد الخاص بالصنف الأساسي الأكثر اشتقاقا (most derived base class). هذا المبدأ مماثل للإرسال الوهمي (virtual dispatch)، إذ يُختار التنفيذ "الأكثر تخصّصًا"، لكن يحدث تحليل التحميل الزائد دائمًا في وقت التصريف، ولن يُنزّل (down-cast) ضمنيًا أبدًا.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_57" style="">
<span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> A</span><span class="pun">&amp;</span><span class="pln"> a</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> B</span><span class="pun">&amp;</span><span class="pln"> b</span><span class="pun">);</span><span class="pln">
C c</span><span class="pun">;</span><span class="pln">
f</span><span class="pun">(</span><span class="pln">c</span><span class="pun">);</span><span class="pln">    </span><span class="com">// f(const B&amp;) استدعاء</span><span class="pln">
B b</span><span class="pun">;</span><span class="pln">
A</span><span class="pun">&amp;</span><span class="pln"> r </span><span class="pun">=</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
f</span><span class="pun">(</span><span class="pln">r</span><span class="pun">);</span><span class="pln">    </span><span class="com">// f(const A&amp;) استدعاء</span><span class="pln">
    </span><span class="com">// غير صالح f(const B&amp;) التحميل الزائد لـ  </span></pre>

<p>
	بالنسبة للمؤشّرات العضوية (pointers to members)، تُطبّق قاعدة مماثلة ولكن في الاتجاه المعاكس، إذ يُفضَّل الصنف المشتق الأقل اشتقاقا (least derived derived class).
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_59" style="">
<span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> B</span><span class="pun">::*</span><span class="pln">p</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> C</span><span class="pun">::*</span><span class="pln">p</span><span class="pun">);</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> A</span><span class="pun">::*</span><span class="pln">p </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">A</span><span class="pun">::</span><span class="pln">m</span><span class="pun">;</span><span class="pln">
f</span><span class="pun">(</span><span class="pln">p</span><span class="pun">);</span><span class="pln">   </span><span class="com">// f(int B::*) استدعاء</span></pre>

<h2>
	خطوات تحليل التحميل الزائد
</h2>

<p>
	خطوات تحليل التحميل الزائد هي:
</p>

<ol>
<li>
		<strong>البحث عن الدوالّ المرشّحة عبر البحث بالاسم</strong>. ستُجري الاستدعاءات غير المُؤهّلة كلّا من البحث العادي غير المُؤهّل - regular unqualiﬁed lookup - وكذلك البحث القائم على الوسيط - argument-dependent lookup - (إن أمكن).
	</li>
	<li>
		<strong>غربلة مجموعة الدوالّ المرشّحة لاستخلاص مجموعة من الدوالّ القابلة للتطبيق.</strong> الدوالّ القابلة للتطبيق هي الدوال التي يوجد تسلسل تحويل ضمني بين الوسائط المُمرّرة إليها والمعاملات التي تقبلها. في المثال التالي، تكون الدالتان 1 و2 صالحتين رغم حذفنا للدالة 2، والدالة 3 غير صالحة لعدم تطابق قائمة الوسائط، أما 4 فغير صالحة لأننا لا نستطيع ربط عنصر مؤقت بمرجع يساري غير ثابت.
	</li>
</ol>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_61" style="">
<span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="kwd">char</span><span class="pun">);</span><span class="pln">    </span><span class="com">// (1)</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="typ">int</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">delete</span><span class="pun">;</span><span class="pln">    </span><span class="com">// (2)</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">();</span><span class="pln">    </span><span class="com">// (3)</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="typ">int</span><span class="pun">&amp;);</span><span class="pln">    </span><span class="com">// (4)</span><span class="pln">
f</span><span class="pun">(</span><span class="lit">4</span><span class="pun">);</span><span class="pln">   </span></pre>

<ol start="3">
<li>
		<strong>اختيار أفضل دالّة مرشحة قابلة للتطبيق.</strong> تكون دالّة قابلة للتطبيق <code>‎F1‎</code> أفضل من دالّة أخرى أخرى قابلة للتطبيق <code>‎F2‎</code> إذا لم يكن تسلسل التحويل الضمني لكل وسيط في <code>‎F1‎</code> أسوأ من تسلسل التحويل الضمني المقابل في <code>‎F2‎</code>، 

		<ul>
<li>
				وبالنسبذة لوسيط ما، فإنّ تسلسل التحويل الضمني لذلك الوسيط في <code>‎F1‎</code> أفضل من تسلسل تحويل ذلك الوسيط في <code>‎F2‎</code>،
			</li>
		</ul>
</li>
</ol>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_63" style="">
<span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="typ">int</span><span class="pun">);</span><span class="pln">    </span><span class="com">// (1)</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="kwd">char</span><span class="pun">);</span><span class="pln">    </span><span class="com">// (2)</span><span class="pln">
f</span><span class="pun">(</span><span class="lit">4</span><span class="pun">);</span><span class="pln">    </span><span class="com">// استدعاء 1 لأنّ تسلسل التحويل فيها أفضل</span></pre>

<p>
	 
</p>

<ul style="margin-right: 40px;">
<li>
		أو في التحويلات المُعرَّفة من قبل المستخدم، فإنّ تسلسل التحويل القياسي (standard conversion sequence) من القيمة المُعادة من <code>‎F1‎</code> إلى النوع المقصود أفضل منه لدى نوع القيمة المُعادة من <code>‎F2‎</code>،
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_65" style="">
<span class="kwd">struct</span><span class="pln"> A
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">operator</span><span class="pln"> </span><span class="typ">int</span><span class="pun">();</span><span class="pln">
    </span><span class="kwd">operator</span><span class="pln"> </span><span class="kwd">double</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

a</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> a</span><span class="pun">;</span><span class="pln">  
</span><span class="typ">float</span><span class="pln"> f </span><span class="pun">=</span><span class="pln"> a</span><span class="pun">;</span><span class="pln">    </span><span class="com">// غامض</span></pre>

<p>
	تفسير <code>int i = a</code> في الشيفرة السابقة: يفضَّل <code>()a.operator int</code> على <code>()a.operator double</code>
</p>

<ul style="margin-right: 40px;">
<li>
		أو يكون‏ لـ <code>‎F1‎</code> نفس نوع المرجع في ارتباط مرجعي مباشر (direct reference binding)، على خلاف <code>‎F2‎</code>،
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_67" style="">
<span class="kwd">struct</span><span class="pln"> A
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">operator</span><span class="pln"> X</span><span class="pun">&amp;();</span><span class="pln">    </span><span class="com">// #1</span><span class="pln">
    </span><span class="kwd">operator</span><span class="pln"> X</span><span class="pun">&amp;&amp;();</span><span class="pln">   </span><span class="com">// #2</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
A a</span><span class="pun">;</span><span class="pln">
X</span><span class="pun">&amp;</span><span class="pln"> lx </span><span class="pun">=</span><span class="pln"> a</span><span class="pun">;</span><span class="pln">    </span><span class="com">// #1 استدعاء</span><span class="pln">
X</span><span class="pun">&amp;&amp;</span><span class="pln"> rx </span><span class="pun">=</span><span class="pln"> a</span><span class="pun">;</span><span class="pln">    </span><span class="com">// #2 استدعاء</span></pre>

<p>
	 
</p>

<ul style="margin-right: 40px;">
<li>
		<code>أو ‎F1‎</code> ليست تخصيصًا لقالب دالة، على خلاف <code>‎F2‎</code>،
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_69" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="pln">T</span><span class="pun">);</span><span class="pln">    </span><span class="com">// #1</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="typ">int</span><span class="pun">);</span><span class="pln">    </span><span class="com">// #2</span><span class="pln">
f</span><span class="pun">(</span><span class="lit">42</span><span class="pun">);</span><span class="pln">    </span><span class="com">// #2 استدعاء</span></pre>

<p>
	 
</p>

<ul style="margin-right: 40px;">
<li>
		<code>أو ‎F1‎</code> و <code>‎F2‎</code> كلاهما تخصيصان لقالب الدالّة، بيْد أنّ <code>‎F1‎</code> أكثر تخصيصًا من <code>‎F2‎</code>.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_71" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="pln">T</span><span class="pun">);</span><span class="pln">    </span><span class="com">// #1</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="pln">T</span><span class="pun">*);</span><span class="pln">    </span><span class="com">// #2</span><span class="pln">
</span><span class="typ">int</span><span class="pun">*</span><span class="pln"> p</span><span class="pun">;</span><span class="pln">
f</span><span class="pun">(</span><span class="pln">p</span><span class="pun">);</span><span class="pln">    </span><span class="com">// #2 استدعاء</span></pre>

<p>
	الترتيب هنا مهم، فالتحقّق من تسلسل التحويل قبل القالب أفضل مقارنة بعدم التحقق من القالب (non-template check)، إذ يؤدّي هذا إلى خطأ شائع في التحميل الزائد لمراجع إعادة التوجيه (forwarding reference):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_73" style="">
<span class="kwd">struct</span><span class="pln"> A
</span><span class="pun">{</span><span class="pln">
    A</span><span class="pun">(</span><span class="pln">A </span><span class="kwd">const</span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">);</span><span class="pln">    </span><span class="com">// #1</span><span class="pln">

    </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
        A</span><span class="pun">(</span><span class="pln">T</span><span class="pun">&amp;&amp;);</span><span class="pln">    </span><span class="com">//  #2 ليست مقيدة</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
A a</span><span class="pun">;</span><span class="pln">
A b</span><span class="pun">(</span><span class="pln">a</span><span class="pun">);</span><span class="pln">    </span><span class="com">// #2 استدعاء</span></pre>

<p>
	تفسير الشيفرة السابقة: الحالة 1 ليست قالبًا، والحالة 2 تحلَّل إلى <code>(&amp;A(A</code> التي تكون مرجعًا أقل تأهيلًا مقارنة بحالة 1، وذلك يجعلها الخيار الأنسب لتسلسل التحويل الضمني.
</p>

<p>
	إذا لم يكن هناك مرشّح قابل للتطبيق أفضل من غيره، فسيُعدُّ الاستدعاء غامضًا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_75" style="">
<span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="kwd">double</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

</span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="typ">float</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

f</span><span class="pun">(</span><span class="lit">42</span><span class="pun">);</span><span class="pln">    </span><span class="com">// خطأ: غامض</span></pre>

<h2>
	التحميل الزائد للدوال (Function Overloading)
</h2>

<h3>
	ما هو التحميل الزائد للدوال؟
</h3>

<p>
	التحميل الزائد للدوالّ هو أن يُصرَّح عن عدة دوّال تحمل نفس الاسم بالضبط ولها نفس النطاق، وتختلف فقط في بصمتها (signature)، أي في الوسائط التي تقبلها.
</p>

<p>
	لنفترض أنّك تريد كتابة سلسلة من الدوالّ المتخصّصة في الطباعة بشكل عام، بدءًا بالسّلاسل النصية <code>std::string</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_77" style="">
<span class="kwd">void</span><span class="pln"> print</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&amp;</span><span class="pln"> str</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"This is a string: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> str </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	سيعمل هذا بكفاءة، لنفترض الآن أنّك تريد دالّة تقبل عددًا صحيحًا (<code>‎int‎</code>) وتطبعه. يمكنك كتابة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_79" style="">
<span class="kwd">void</span><span class="pln"> print_int</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> num</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"This is an int:  "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> num </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ولكن بما أن الدالتان تقبلان معاملات مختلفة، فيمكنك ببساطة كتابة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_81" style="">
<span class="kwd">void</span><span class="pln"> print</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> num</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"This is an int: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> num </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	صار لدينا الآن دالتان، كلتاهما تحمل الاسم <code>‎print‎</code> ولكن مع بصْمتين مختلفين، وتقبل إحداهما سلسلة نصية، والأخرى تقبل عددًا صحيحًا (<code>‎int‎</code>). يمكنك الآن استدعَاؤهما على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_83" style="">
<span class="pln">print</span><span class="pun">(</span><span class="str">"Hello world!"</span><span class="pun">);</span><span class="pln"> </span><span class="com">//  "This is a string: Hello world!"</span><span class="pln">
print</span><span class="pun">(</span><span class="lit">1337</span><span class="pun">);</span><span class="pln"> </span><span class="com">//  "This is an int: 1337"</span></pre>

<p>
	بدلًا من:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_85" style="">
<span class="pln">print</span><span class="pun">(</span><span class="str">"Hello world!"</span><span class="pun">);</span><span class="pln">
print_int</span><span class="pun">(</span><span class="lit">1337</span><span class="pun">);</span></pre>

<p>
	عندما تكون لديك عدة دوالّ زائدة التحميل (overloaded)، سيستنتج المُصرّف أيًّا من تلك الدوالّ يجب عليه استدعاؤها عبر تحليل المعاملات المُمرّرة. كذلك يجب الحذر عند تحميل الدوالّ. انظر المثال التالي مع تحويلات النوع الضمنية (implicit type conversions):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_87" style="">
<span class="kwd">void</span><span class="pln"> print</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> num</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"This is an int: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> num </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> print</span><span class="pun">(</span><span class="kwd">double</span><span class="pln"> num</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"This is a double: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> num </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	كما ترى فليس من الواضح أيُّ تحميلٍ زائد للدالّة <code>‎print‎</code> سيُستدعى عند كتابة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_89" style="">
<span class="pln">print</span><span class="pun">(</span><span class="lit">5</span><span class="pun">);</span></pre>

<p>
	وقد تحتاج إلى إعطاء المُصرّف بعض التلميحات، مثل:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_91" style="">
<span class="pln">print</span><span class="pun">(</span><span class="kwd">static_cast</span><span class="str">&lt;double&gt;</span><span class="pun">(</span><span class="lit">5</span><span class="pun">));</span><span class="pln">
print</span><span class="pun">(</span><span class="kwd">static_cast</span><span class="str">&lt;int&gt;</span><span class="pun">(</span><span class="lit">5</span><span class="pun">));</span><span class="pln">
print</span><span class="pun">(</span><span class="lit">5.0</span><span class="pun">);</span></pre>

<p>
	يجب توخّي الحذر أيضًا عند كتابة تحميلات زائدة تقبل معامِلات اختيارية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_93" style="">
<span class="com">// انتبه! شيفرة خاطئة</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> print</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> num1</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> num2 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="com">// هي 0 num2 القيمة الافتراضية لـ</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"These are ints: &lt;&lt; num1 &lt;&lt; "</span><span class="pln">
    and </span><span class="str">"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> num2 </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> print</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> num</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"This is an int: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> num </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	سيعجز المُصرّف عن معرفة إن كان الاستدعاء <code>‎print(17)‎</code> مخصّصًا للدالّة الأولى أو الثانية، وذلك بسبب المعامل الثاني الاختياري، لهذا لن تُصرّف هذه الشيفرة.
</p>

<h3>
	نوع القيمة المعادة في الدوالّ زائدة التحميل
</h3>

<p>
	لاحظ أنك لا تستطيع زيادة التحميل على دالّة بناءً على نوع قيمتها المعادة. مثلا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_95" style="">
<span class="com">// شيفرة خاطئة</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">string getValue</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="str">"hello"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> getValue</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> getValue</span><span class="pun">();</span></pre>

<p>
	سيؤدي هذا إلى حدوث خطأ في التصريف نظرًا لأنّ المصرّف سيعجز عن تحديد نسخة <code>‎getValue‎</code> التي يجب استدعاؤها، رغم اختلاف نوع القيمة المعادة في التصريحين.
</p>

<h3>
	زيادة تحميل الدوال التابعة المؤهلة
</h3>

<p>
	يمكن زيادة تحميل الدوال التي داخل الأصناف عند الوصول إليها عبر مراجع مؤهَّلة (cv-qualified reference) لذلك الصنف، ويُستخدم هذا غالبًا لزيادة تحميل الثوابت (<code>‎const‎</code>)، ولكن يمكن استخدامها أيضًا لزيادة تحميل القيم ذات التأهيل <code>‎volatile‎</code> و <code>‎const ‎volatile‎</code> أيضًا، ذلك لأنّ جميع الدوال التابعة غير الساكنة تأخذ <code>this</code> كمعامِل خفي، ذلك المعامِل تُطبَّقُ عليه المؤهّلات الثباتية (cv- qualiﬁers).
</p>

<p>
	هذا ضروري لأنه لا يمكن استدعاء تابع إلا إذا كان تأهيله مكافئًا على الأقل لتأهيل النسخة التي استُدعِي عليها، وصحيح أنّ النسخة غير ثابتة تستطيع استدعاء كل من الأعضاء الثابتة وغير الثابتة، إلا أنه لا يمكن لنسخة ثابتة أن تستدعي إلا الأعضاء الثابتة، وهذا يسمح لدالّة بأن يكون لها سلوكيات مختلفة بحسب مؤهّلات النُّسخة التي استُدعِيت عليها، ويسمح للمبرمج بمنع الدوالّ بالنسبة لمؤهِّل معيّن من خلال عدم توفير إصدار من تلك الدالّة لذلك المؤهل.
</p>

<p>
	يمكن لصنف ذي تابع <code>‎print‎</code> أن يُزاد تحميله ثباتيًا (const overloaded) على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_97" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Integer</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
</span><span class="typ">Integer</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i_</span><span class="pun">):</span><span class="pln"> i</span><span class="pun">{</span><span class="pln">i_</span><span class="pun">}{}</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> print</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"int: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> i </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">void</span><span class="pln"> print</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"const int: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> i </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">protected</span><span class="pun">:</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="typ">Integer</span><span class="pln"> i</span><span class="pun">{</span><span class="lit">5</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Integer</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">ic </span><span class="pun">=</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">

i</span><span class="pun">.</span><span class="pln">print</span><span class="pun">();</span><span class="pln"> </span><span class="com">// يطبع "int: 5"</span><span class="pln">
ic</span><span class="pun">.</span><span class="pln">print</span><span class="pun">();</span><span class="pln"> </span><span class="com">// يطبع "const int: 5"</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	هذا مبدأ أساسي لصحة الثباتية (const)، إذ يُسمح باستدعاء الدوال التابعة على نُسخ <code>const</code> من خلال جعلها هي ثابتة، وهذا يتيح للدوالّ أن تأخذ النسخ كمؤشرات/مراجع ثابتة إذا لم تكن بحاجة إلى تعديلها، ويسمح هذا للشيفرة بتحديد ما إذا كانت الحالة ستُعدّل عن طريق أخذ معامِلات غير مُعدّلة كمعامِلات ذات تأهيل ثابت <code>const</code> ومعاملات مُعدّلة بدون تأهيل، مما يجعل الشيفرة أكثر أمانًا وأسهل في القراءة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_99" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">ConstCorrect</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">void</span><span class="pln"> good_func</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"I care not whether the instance is const."</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> bad_func</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"I can only be called on non-const, non-volatile instances."</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> i_change_no_state</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">ConstCorrect</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> cc</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"I can take either a const or a non-const ConstCorrect."</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    cc</span><span class="pun">.</span><span class="pln">good_func</span><span class="pun">();</span><span class="pln"> </span><span class="com">// جيد، يمكن استدعاؤها من النسخ الثابتة أو غير الثابتة</span><span class="pln">
    cc</span><span class="pun">.</span><span class="pln">bad_func</span><span class="pun">();</span><span class="pln"> </span><span class="com">// خطأ، لا يمكن استدعاؤها إلا من النسخ غير الثابتة</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> const_incorrect_func</span><span class="pun">(</span><span class="typ">ConstCorrect</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> cc</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    cc</span><span class="pun">.</span><span class="pln">good_func</span><span class="pun">();</span><span class="pln"> </span><span class="com">// جيد، يمكن استدعاؤها من النسخ الثابتة أو غير الثابتة</span><span class="pln">
    cc</span><span class="pun">.</span><span class="pln">bad_func</span><span class="pun">();</span><span class="pln"> </span><span class="com">// جيد، لا يمكن استدعاؤها إلا من النسخ غير الثابتة</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	أحد الاستخدامات الشائعة لهذا هو إعلان توابع الوصول (accessors) كثوابت، وتوابع التغيير (mutators) على أنها غير ثابتة، ولا يمكن تعديل عضو من الصنف داخل تابع ثابت. أما إذا كان هناك عضو تحتاج إلى تعديله، كأن تريد قفل <code>std::mutex</code> مثلًا فيمكنك إعلانه كـ <code>‎mutable‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_101" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Integer</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">Integer</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i_</span><span class="pun">):</span><span class="pln"> i </span><span class="pun">{</span><span class="pln">
            i_
        </span><span class="pun">}</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> get</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">lock_guard </span><span class="pun">&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">mutex </span><span class="pun">&gt;</span><span class="pln"> lock </span><span class="pun">{</span><span class="pln">
            mut
        </span><span class="pun">};</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">set</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i_</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">lock_guard </span><span class="pun">&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">mutex </span><span class="pun">&gt;</span><span class="pln"> lock </span><span class="pun">{</span><span class="pln">
            mut
        </span><span class="pun">};</span><span class="pln">
        i </span><span class="pun">=</span><span class="pln"> i_</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">mutable</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">mutex mut</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span></pre>

<h3>
	زيادة تحميل قوالب الدوال (Function Template Overloading)
</h3>

<p>
	يمكن زيادة تحميل قوالب الدوالّ وفق نفس القواعد التي نزيد بها تحميل الدوالّ العادية، أي يجب أن يكون للدوالّ المُحمّلة نفس الاسم، ولكن مع أنواع معاملات مختلفة، وتكون زيادة التحميل صالحة إذا كان:
</p>

<ul>
<li>
		نوع القيمة المعادة مختلفًا، أو …
	</li>
	<li>
		إذا كانت قائمة معاملات القالب مختلفة، باستثناء أسماء المعاملات والوسائط الافتراضية (فهُما ليسا جزءًا من التوقيع).
	</li>
</ul>
<p>
	تبدو مقارنة نوعا معامِلات بالنسبة لدالة عادية عمليةً سهلة على المُصرّف لأنه يملك كل المعلومات اللازمة، ولكن ربما لا تكون الأنواع داخل القالب قد حُدّدت بعد، لذا فإن القاعدة التي تحكم على مدى تطابق نوعي معامِلات تقريبية هنا، وتقضي بأن الأنواع والقيم المستقلة (non depependend) يجب أن تطابق تهجِئة الأنواع والعبارات التابعة (dependent)، أي يجب أن يتوافقًا مع قاعدة التعريف الواحد [ODR]،مع استثناء أن معامِلات القالب يمكن إعادة تسميتها. لكن إذا كانت التهجئة مختلفة، واختلفت قيمتان داخل النوعين لكنهما يستنسخان دائمًا إلى نفس القيم، فتكون زيادة التحميل غير صالحة (invalid)، لكن لن يكون التشخيص مطلوبًا من المصرِّف.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_103" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="pln">T</span><span class="pun">*)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="pln">T</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span></pre>

<p>
	هذا تحميل صالح (valid)، لأنّ "T" و "T *" لهما تهجئتان مختلفتان، لكنّ زيادة التحميل التالية غير صالحة، كما أنّ التشخيص غير مطلوب.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8851_105" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="pln">T </span><span class="pun">(*</span><span class="pln">x</span><span class="pun">)[</span><span class="kwd">sizeof</span><span class="pun">(</span><span class="pln">T</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="pln">T</span><span class="pun">)])</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="pln">T </span><span class="pun">(*</span><span class="pln">x</span><span class="pun">)[</span><span class="lit">2</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="pln">T</span><span class="pun">)])</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">}</span></pre>

<p>
	هذا الدرس جزء من <a data-ss1617022515="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة دروس عن C++‎</a>.
</p>

<p>
	ترجمة -بتصرّف- للفصول:
</p>

<ul>
<li>
		Chapter 35: Function Overloading
	</li>
	<li>
		Chapter 37: Function Template Overloading
	</li>
	<li>
		Chapter 105: Overload resolution
	</li>
</ul>
<p>
	من كتاب <a data-ss1617022515="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">934</guid><pubDate>Sun, 12 Jul 2020 18:07:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x623;&#x635;&#x646;&#x627;&#x641; Classes &#x648;&#x627;&#x644;&#x628;&#x646;&#x64A;&#x627;&#x62A; Structures &#x641;&#x64A; Cpp</title><link>https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%A3%D8%B5%D9%86%D8%A7%D9%81-classes-%D9%88%D8%A7%D9%84%D8%A8%D9%86%D9%8A%D8%A7%D8%AA-structures-%D9%81%D9%8A-cpp-r933/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_06/21.jpg.4011d25cfe89975a82b34449c787535c.jpg" /></p>

<h2>
	أساسيات الأصناف
</h2>

<p>
	الصنف (class) هو نوع يعرّفه المستخدم، ويُسبق بالكلمة المفتاحية <code>‎class‎</code> أو <code>‎struct‎</code> أو <code>‎union‎</code>، ويشير المصطلح "class" بشكل عام إلى الأصناف غير الاتحاديّة (non-union classes).
</p>

<p>
	والصنف مؤلّف من أعضاء يمكن أن تكون أيًا مما يلي:
</p>

<ul>
<li>
		متغيرات أعضاء، وتسمى كذلك متغيِّرات عضوية أو حقولًا (member variables)،
	</li>
	<li>
		توابع، وتسمى كذلك دوالًا تابعة أو دوالًا أعضاءً (member functions)،
	</li>
	<li>
		أنواع عضوية أو أنواع تعريفية (typedefs أو member types)
	</li>
	<li>
		قوالب عضوية أو قوالب أعضاء (member templates) من أيّ نوع: متغير، دالّة، صنف أو قالب.
	</li>
</ul>
<p>
	الكلمتان المفتاحيّتان <code>‎class‎</code> و <code>‎struct‎</code> واللّتان تُسمّيان مفاتيح الأصناف (class keys) متشابهتان إلى حدّ كبير، باستثناء أنّ محدد الوصول الافتراضي للأعضاء والأصناف الأساسية (bases) تكون خاصّة (private) في الأصناف التي صُرِّح عنها باستخدام المفتاح <code>‎class‎</code>، وعامّة (public) بالنسبة للأصناف التي صُرِّح عنها باستخدام أحد المفتاحين <code>‎struct‎</code> أو <code>‎union‎</code>. على سبيل المثال، المُقتطفان التاليان متطابقان:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_7" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Vector</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> y</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> z</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="com">// تكافئ</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Vector</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> y</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> z</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	بعد التصريح عن صنف، يُضاف نوع جديد إلى برنامجك، ومن الممكن استنساخ كائنات من هذا الصنف على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_9" style="">
<span class="typ">Vector</span><span class="pln"> my_vector</span><span class="pun">;</span></pre>

<p>
	ويمكن الوصول إلى أعضاء الصّنف باستخدام الصياغة النقطيّة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_11" style="">
<span class="pln">my_vector</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln">
my_vector</span><span class="pun">.</span><span class="pln">y </span><span class="pun">=</span><span class="pln"> my_vector</span><span class="pun">.</span><span class="pln">x </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln"> </span><span class="com">// my_vector.y = 11;</span><span class="pln">
my_vector</span><span class="pun">.</span><span class="pln">z </span><span class="pun">=</span><span class="pln"> my_vector</span><span class="pun">.</span><span class="pln">y </span><span class="pun">-</span><span class="pln"> </span><span class="lit">4</span><span class="pun">;</span><span class="pln"> </span><span class="com">// my:vector.z = 7;</span></pre>

<h2>
	الأصناف والبِنيات النهائية
</h2>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	يُمكن حظر اشتقاق صنف بواسطة الكلمة المفتاحية <code>‎final‎</code>، وفق الصياغة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_13" style="">
<span class="kwd">class</span><span class="pln"> A final </span><span class="pun">{</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	ستؤدّي أيُّ محاولة لاشتقاقه إلى خطأ تصريفي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_15" style="">
<span class="com">// Compilation error: cannot derive from final class</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> B </span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> A </span><span class="pun">{};</span></pre>

<p>
	يمكن أن تظهر الأصناف النهائية في أيّ مكان في هرميّة الأصناف (class hierarchy):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_17" style="">
<span class="kwd">class</span><span class="pln"> A </span><span class="pun">{};</span><span class="pln">
</span><span class="com">// OK.</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> B final</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> A </span><span class="pun">{};</span><span class="pln">
</span><span class="com">// Compilation error: cannot derive from final class B.</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> C</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> B </span><span class="pun">{};</span></pre>

<h2>
	محددات الوصول (Access speciﬁers)
</h2>

<table>
<thead><tr>
<th>
				الكلمة المفتاحية
			</th>
			<th>
				الوصف
			</th>
		</tr></thead>
<tbody>
<tr>
<td>
				<code>public</code>
			</td>
			<td>
				الجميع لديهم صلاحية الوصول
			</td>
		</tr>
<tr>
<td>
				<code>protected</code>
			</td>
			<td>
				الصنف والأصناف المشتقة منه وأصدقاء الصنف هم من لهم صلاحية الوصول
			</td>
		</tr>
<tr>
<td>
				<code>private</code>
			</td>
			<td>
				الصنف وأصدقاء الصنف فقط لديهم حق الوصول
			</td>
		</tr>
</tbody>
</table>
<style type="text/css">
table {
    width: 100%;
}

thead {
    vertical-align: middle;
    text-align: center;
}

td, th {
    border: 1px solid #dddddd;
    text-align: right;
    padding: 8px;
    text-align: inherit;

}
tr:nth-child(even) {
    background-color: #dddddd;
}</style>
<p>
	إذا عُرِّف النوع باستخدام الكلمة المفتاحية <code>‎class‎</code>، سيكون مُحدِّد الوصول الافتراضي هو <code>‎private‎</code>، ولكن إذا عُرِّف باستخدام <code>‎struct‎</code>، فإنّ محدِّد الوصول الافتراضي الخاص به سيكون <code>‎public‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_19" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">MyStruct</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">MyClass</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">MyStruct</span><span class="pln"> s</span><span class="pun">;</span><span class="pln">
s</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">9</span><span class="pun">;</span><span class="pln"> </span><span class="com">// عام x خلل في الصياغة، لأنّ</span><span class="pln">
</span><span class="typ">MyClass</span><span class="pln"> c</span><span class="pun">;</span><span class="pln">
c</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">9</span><span class="pun">;</span><span class="pln"> </span><span class="com">// خاصّ x خلل في الصياغة، لأنّ</span></pre>

<p>
	غالبًا ما تُستخدم مُحدِّدات الوصول لتقييد إمكانية الوصول إلى الحقول والتوابع الداخلية، إذ تجبر تلك المحدِّدات المُبرمج على استخدام واجهة برمجية محدّدة، فمثلًا لفرض استخدام الجالِبات (توابع الجلب - getters) والمُعيِّنات (توابع التعيين - setters) بدلاً من الرجوع مباشرة إلى المتغيرات:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_21" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">MyClass</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln"> </span><span class="com">/* Methods: */</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> x</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> noexcept </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> m_x</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> setX</span><span class="pun">(</span><span class="typ">int</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> x</span><span class="pun">)</span><span class="pln"> noexcept </span><span class="pun">{</span><span class="pln">
        m_x </span><span class="pun">=</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln"> </span><span class="com">/* Fields: */</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> m_x</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	يُعدُّ استخدام الكلمة المفتاحيّة <code>‎protected‎</code> مفيدًا لقصر حق الوصول إلى بعض الوظائف على الأصناف المشتقّة، فمثلًا في الشيفرة التالية، يكون الوصول إلى التابع <code>‎calculateValue()‎</code> مقصورًا على الأصناف المشتقّة من الصنف <code>‎Plus2Base‎</code>. انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_23" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Plus2Base</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> value</span><span class="pun">()</span><span class="pln"> noexcept </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> calculateValue</span><span class="pun">()</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pun">:</span><span class="pln"> </span><span class="com">/* Methods: */</span><span class="pln">
        </span><span class="kwd">virtual</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> calculateValue</span><span class="pun">()</span><span class="pln"> noexcept </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">FortyTwo</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Plus2Base</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pun">:</span><span class="pln"> </span><span class="com">/* Methods: */</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> calculateValue</span><span class="pun">()</span><span class="pln"> noexcept final override </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">40</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	لاحظ أنّه يمكن استخدام الكلمة المفتاحية <code>‎friend‎</code> لمنح تراخيص استثنائية إلى بعض الدوالّ أو الأنواع من أجل الوصول إلى الأعضاء المحمييّن والخواص. كذلك يمكن استخدام الكلمات المفتاحية <code>‎public‎</code> و <code>‎protected‎</code> و <code>‎private‎</code> لمنح أو تقييد حقّ الوصول إلى الكائنات الفرعية للصنف الأساسي.
</p>

<h2>
	الوراثة (Inheritance)
</h2>

<p>
	يمكن للأصناف والبُنى أن تكون بينها علاقات وراثة، فإذا ورث صنف أو بنية <code>‎B‎</code> من صنف أو بنية <code>‎A‎</code>، فإنّ هذا يعني أنّ <code>‎B‎</code> هو أب لـ <code>‎A‎</code>. ونقول أنّ <code>‎B‎</code> هو صنف أو بنية مشتقة من <code>‎A‎</code>، وأنّ <code>‎A‎</code> هو الصنف أو البنية الأساسية (base class/struct)، أو نقول اختصارًا "أساس".
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_25" style="">
<span class="kwd">struct</span><span class="pln"> A </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> p1</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pun">:</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> p2</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> p3</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="com">// A يرث من  B اجعل</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> B</span><span class="pun">:</span><span class="pln"> A </span><span class="pun">{};</span></pre>

<p>
	هناك ثلاثة أشكال من الوراثة:
</p>

<ul>
<li>
		<code>‎public‎</code>
	</li>
	<li>
		<code>‎private‎</code>
	</li>
	<li>
		<code>‎protected‎</code>
	</li>
</ul>
<p>
	لاحظ أنّ الوراثة الافتراضية تماثل الرؤية الافتراضية للأعضاء: أي أنها تكون عامّة (<code>‎public‎</code>) في حال استخدام الكلمة المفتاحية <code>‎struct‎</code>، أو خاصّة (<code>‎private‎</code>) في حال استخدام الكلمة المفتاحية <code>‎class‎</code>.
</p>

<p>
	من الممكن اشتقاق صنف من بِنية (أو العكس). ويُتحكَّم في الوراثة الافتراضية هنا بواسطة الصنف الابن/الفرعي (child)، وعليه فإنّ بنيةً مشتقة من صنف ستكون وراثتها الافتراضية عامّة (public)، وصنفٌ (<code>‎class‎</code>) مشتق من بنية (<code>‎struct‎</code>) ستكون وراثته الافتراضية خاصة (private).
</p>

<p>
	<strong>الوراثة العامة (<code>‎public‎</code>):</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_27" style="">
<span class="kwd">struct</span><span class="pln"> B</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> A </span><span class="com">// `struct B : A` أو</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        p1 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> </span><span class="com">// B عام في p1 </span><span class="pln">
        p2 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> </span><span class="com">// B محمي  p2 </span><span class="pln">
        p3 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> </span><span class="com">// B خاص في p3 صيغة غير صحيحة، لأن</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
B b</span><span class="pun">;</span><span class="pln">
b</span><span class="pun">.</span><span class="pln">p1 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln"> </span><span class="com">// عام p1 </span><span class="pln">
b</span><span class="pun">.</span><span class="pln">p2 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln"> </span><span class="com">// محمي p2 خطأ</span><span class="pln">
b</span><span class="pun">.</span><span class="pln">p3 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln"> </span><span class="com">// غير قابل للوصول p2 خطأ لأن</span></pre>

<p>
	<strong>الوراثة الخاصة (<code>‎private‎</code>):</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_29" style="">
<span class="kwd">struct</span><span class="pln"> B</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">private</span><span class="pln"> A </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        p1 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> </span><span class="com">// B خاص في  p1 </span><span class="pln">
        p2 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> </span><span class="com">// B خاص في p2 </span><span class="pln">
        p3 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> </span><span class="com">// A خاص في p3 خطأ،لأنّ</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
B b</span><span class="pun">;</span><span class="pln">
b</span><span class="pun">.</span><span class="pln">p1 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln"> </span><span class="com">// خاص p3 خطأ،لأنّ</span><span class="pln">
b</span><span class="pun">.</span><span class="pln">p2 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln"> </span><span class="com">// خاص p2 خطأ،لأنّ</span><span class="pln">
b</span><span class="pun">.</span><span class="pln">p3 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln"> </span><span class="com">// غير قابل للوصول p3 خطأ، لأنّ</span></pre>

<p>
	<strong>الوراثة المحميّة (<code>‎protected‎</code>):</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_31" style="">
<span class="kwd">struct</span><span class="pln"> B</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">protected</span><span class="pln"> A </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        p1 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> </span><span class="com">// B محمي في  p1 </span><span class="pln">
        p2 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> </span><span class="com">// B محمي في  p2 </span><span class="pln">
        p3 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> </span><span class="com">// A خاص في p2 خطأ، لأنّ </span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
B b</span><span class="pun">;</span><span class="pln">
b</span><span class="pun">.</span><span class="pln">p1 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln"> </span><span class="com">// محمي  p1 خطأ، لأن</span><span class="pln">
b</span><span class="pun">.</span><span class="pln">p2 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln"> </span><span class="com">// محمي  p2 خطأ لأنّ</span><span class="pln">
b</span><span class="pun">.</span><span class="pln">p3 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln"> </span><span class="com">// غير قابل للوصول p3 خطأ لأنّ</span></pre>

<p>
	لاحظ أنه على الرغم من أنّ الوراثة المحميّة <code>‎protected‎</code> مسموح بها إلا أنّ استخدامها ناد، فمن أمثلة استخدامها في التخصيص الجزئي لصنف أساسي (يشار إليه عادةً باسم "التعددية الشكلية المحكومة".
</p>

<p>
	كان يُنظَر في بدايات البرمجة الكائنية (<abbr title="Object-Oriented Programming | البرمجة كائنية التوجه">OOP</abbr>) إلى الوراثة (العامة) كعلاقة انتماء ("IS-A")، وهذا يعني أنّ الوراثة العامة لا تكون صحيحة إلا إذا كانت نُسخ الصنف المشتق أيضًا نُسخًا من الصنف الأساسي، وقد استُبدِلَ بهذا المبدأ مبدأ آخر، وهو <a data-ss1617022514="1" href="https://en.wikipedia.org/wiki/Liskov_substitution_principle" rel="external nofollow">مبدأ Liskov للتعويض</a>:
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		يجب ألا تُستخدم الوراثة العامة إلا عندما يكون من الممكن استبدال نُسخة من الصنف المشتق بنُسخة من الصنف الأساسي في جميع الظروف (ويبقى ذلك منطقيًّا).
	</p>
</blockquote>

<p>
	يقال عادة إنّ الوراثة الخاصة (Private inheritance) تجسّد علاقة مختلفة تمامًا، إذ يُعبَّر عنها عادة بالصيغة "منفَّذة وفق" (تُدعى أحيانًا علاقة "HAS-A"). على سبيل المثال، يمكن أن يرث صنف <code>‎Stack‎</code> بشكل خاص (privately) من صنف <code>‎Vector‎</code>، وتشبه الوراثة الخاصة علاقة التجميع (aggregation) أكثر من شبهها بعلاقة الوراثة العامة.
</p>

<p>
	ولا تكادُ تُستخدم الوراثة المحمية (Protected inheritance) على الإطلاق، ولا يوجد اتفاق عام على نوع العلاقة التي تجسّدها.
</p>

<h2>
	الصداقة (Friendship)
</h2>

<p>
	تُستخدم الكلمة المفتاحية <code>‎friend‎</code> لإعطاء الأصناف والدوالّ الأخرى حق الوصول إلى أعضاء الصنف الخواص والمحميّين، حتى لو كانت مُعرّفة خارج نطاق الصنف.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_35" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Animal</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">double</span><span class="pln"> weight</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">double</span><span class="pln"> height</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">friend</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> printWeight</span><span class="pun">(</span><span class="typ">Animal</span><span class="pln"> animal</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">friend</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">AnimalPrinter</span><span class="pun">;</span><span class="pln">
    </span><span class="com">//  &lt;&lt; من الاستخدامات الشائعة للدوالّ الصديقة هو زيادة تحميل المعامل </span><span class="pln">
    </span><span class="kwd">friend</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">ostream </span><span class="pun">&amp;</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">ostream </span><span class="pun">&amp;</span><span class="pln"> os</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Animal</span><span class="pln"> animal</span><span class="pun">);</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> printWeight</span><span class="pun">(</span><span class="typ">Animal</span><span class="pln"> animal</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> animal</span><span class="pun">.</span><span class="pln">weight </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">AnimalPrinter</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">void</span><span class="pln"> print</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Animal</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> animal</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="com">// يُسمح بالدخول إلى الأعضاء الخاصة الآن</span><span class="pln">
            std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> animal</span><span class="pun">.</span><span class="pln">weight </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> animal</span><span class="pun">.</span><span class="pln">height </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">ostream</span><span class="pun">&amp;</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">&lt;&lt;(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">ostream</span><span class="pun">&amp;</span><span class="pln"> os</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Animal</span><span class="pln"> animal</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    os </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Animal height: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> animal</span><span class="pun">.</span><span class="pln">height </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> os</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Animal</span><span class="pln"> animal </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="lit">10</span><span class="pun">,</span><span class="pln">
        </span><span class="lit">5</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
    printWeight</span><span class="pun">(</span><span class="pln">animal</span><span class="pun">);</span><span class="pln">
    </span><span class="typ">AnimalPrinter</span><span class="pln"> aPrinter</span><span class="pun">;</span><span class="pln">
    aPrinter</span><span class="pun">.</span><span class="pln">print</span><span class="pun">(</span><span class="pln">animal</span><span class="pun">);</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> animal</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	الناتج:
</p>

<pre class="ipsCode">
10
10, 5
Animal height: 5
</pre>

<h2>
	الوراثة الوهمية (Virtual Inheritance)
</h2>

<p>
	يمكنك استخدام الكلمة المفتاحية <code>‎virtual‎</code> وفق الصياغة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_37" style="">
<span class="kwd">struct</span><span class="pln"> A</span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> B</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">virtual</span><span class="pln"> A</span><span class="pun">{};</span></pre>

<p>
	إذا كان لصنف <code>‎B‎</code> صنفٌ أساسيّ وهمي هو <code>‎A‎</code>، فهذا يعني أنّ <code>‎A‎</code> سوف يكون في أكثر صنف مشتق، وعليه فإنّ الصنف الأكثر اشتقاقًا (most derived class) سيكون مسؤولًا عن تهيئة ذلك الصنف الأساسي الوهمي (virtual base):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_39" style="">
<span class="kwd">struct</span><span class="pln"> A </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> member</span><span class="pun">;</span><span class="pln">
    A</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> param</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        member </span><span class="pun">=</span><span class="pln"> param</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">struct</span><span class="pln"> B</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">virtual</span><span class="pln"> A </span><span class="pun">{</span><span class="pln">
    B</span><span class="pun">():</span><span class="pln"> A</span><span class="pun">(</span><span class="lit">5</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">struct</span><span class="pln"> C</span><span class="pun">:</span><span class="pln"> B </span><span class="pun">{</span><span class="pln">
    C</span><span class="pun">():</span><span class="pln"> </span><span class="com">/*A(88)*/</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    C object</span><span class="pun">;</span><span class="pln"> </span><span class="com">// `A` لم يهيّئ الصنف الأساسي الوهمي C خطأ، لأنّ</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	إذا ألغينا تعليق <code>/* A (88)‎ */</code>، فلن يحدث خطأ، لأنّ <code>‎C‎</code> سيكون قد هيّأ أساسه الوهمي (أو صنفه الأب) <code>‎A‎</code>. كذلك، لاحظ أنه عند إنشاء <code>‎object‎</code>، فإنّ الصنف الأكثر اشتقاقا (most derived class) هو <code>‎C‎</code>، وعليه فإنّ <code>‎C‎</code> هو المسؤول عن إنشاء (استدعاء مُنشئ) <code>‎A‎</code>، ومن ثم فإنّ قيمة <code>‎A::member‎</code> ستكون <code>‎88‎</code>، وليس <code>‎5‎</code> (كما سيكون الأمر لو أنشأنا كائنًا من النوع <code>‎B‎</code>).
</p>

<p>
	هذا مفيد لحل <a data-ss1617022514="1" href="https://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problem" rel="external nofollow">مشكلة الماسّة</a>:
</p>

<pre class="ipsCode">
   A                                        A      A
 /     \                                       |      |
B    C                                      B   C
 \    /                                         \    /
   D                                            D
الوراثة الوهمية        vs               الوراثة العادية
</pre>

<p>
	يرث كلٌّ من <code>‎B‎</code> و <code>‎C‎</code> من <code>‎A‎</code>، ويرث <code>‎D‎</code> من <code>‎B‎</code> و <code>‎C‎</code>، لذا فهناك نُسختان من A في D! قد ينتج عن هذا بعض الغموض عند محاولة الوصول إلى عضو من <code>‎A‎</code> عبر <code>‎D‎</code>، ذلك أنّه ليس للمُصرّف أي طريقة لتَخمين الصنف الذي تريد الوصول من خلاله إلى العضو (أهو الصنف الذي يرثه <code>‎B‎</code>، أو الصنف الذي ورثه <code>‎C‎</code>؟) .
</p>

<p>
	تحل الوراثة الوهميّة (Virtual inheritance) هذه المشكلة على النحو التالي: نظرًا لأنّ الأصناف الأساسية الوهميّة تقبع في الكائنات الأكثر اشتقاقًا (most derived object)، فستكون هناك نُسخة واحدة فقط من <code>‎A‎</code> في <code>‎D‎</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_41" style="">
<span class="kwd">struct</span><span class="pln"> A </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">struct</span><span class="pln"> B</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> </span><span class="com">/*virtual*/</span><span class="pln"> A </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> C</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> </span><span class="com">/*virtual*/</span><span class="pln"> A </span><span class="pun">{};</span><span class="pln">

</span><span class="kwd">struct</span><span class="pln"> D</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> B</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> C </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> bar</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        foo</span><span class="pun">();</span><span class="pln">     </span><span class="com">// نستدعي؟ foo خطأ، فأي </span><span class="pln">
</span><span class="com">// B::foo() أم C::foo() هل </span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	إزالة التعليقات سيُجلِّي هذا الغموض.
</p>

<h2>
	الوراثة الخاصة: تقييد واجهة الصنف الأساسي
</h2>

<p>
	الوراثة الخاصة مفيدة لتقييد الواجهة العامة للصنف:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_43" style="">
<span class="kwd">class</span><span class="pln"> A </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> move</span><span class="pun">();</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> turn</span><span class="pun">();</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> B</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">private</span><span class="pln"> A </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">using</span><span class="pln"> A</span><span class="pun">::</span><span class="pln">turn</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

B b</span><span class="pun">;</span><span class="pln">
b</span><span class="pun">.</span><span class="pln">move</span><span class="pun">();</span><span class="pln"> </span><span class="com">// خطأ في التصريف</span><span class="pln">
b</span><span class="pun">.</span><span class="pln">turn</span><span class="pun">();</span><span class="pln"> </span><span class="com">// OK</span></pre>

<p>
	يمنع هذا المنظور الوصول إلى التوابع العامة لـ <code>A</code> عبر مؤشّرٍ أو مرجع يشير إلى <code>A</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_45" style="">
<span class="pln">B b</span><span class="pun">;</span><span class="pln">
A</span><span class="pun">&amp;</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="pln">A</span><span class="pun">&amp;&gt;(</span><span class="pln">b</span><span class="pun">);</span><span class="pln"> </span><span class="com">// خطأ في التصريف</span></pre>

<p>
	في حالة الوراثة العامة، سيوفّر مثل هذا التحويل إمكانية الوصول إلى جميع التوابع العامة للصنف <code>A</code>، رغم وجود طرق بديلة لمنع ذلك من داخل الصنف المشتق <code>B</code>، مثل الإخفاء:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_47" style="">
<span class="kwd">class</span><span class="pln"> B</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> A </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> move</span><span class="pun">();</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	أو استخدام الكلمة المفتاحية <code>private</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_49" style="">
<span class="kwd">class</span><span class="pln"> B</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> A </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln"> 
</span><span class="kwd">using</span><span class="pln"> A</span><span class="pun">::</span><span class="pln">move</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	وفي كلا الحالتين، سيكون من الممكن القيام بما يلي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_51" style="">
<span class="pln">B b</span><span class="pun">;</span><span class="pln">
A</span><span class="pun">&amp;</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="pln">A</span><span class="pun">&amp;&gt;(</span><span class="pln">b</span><span class="pun">);</span><span class="pln">    </span><span class="com">// جائز في الوراثة العامة</span><span class="pln">
a</span><span class="pun">.</span><span class="pln">move</span><span class="pun">();</span><span class="pln">                </span><span class="com">// OK</span></pre>

<h2>
	الوصول إلى أعضاء الصنف
</h2>

<p>
	للوصول إلى متغيرات الأعضاء أو الدوالّ العضوية لكائن من صنف ما، فإننا نستخدم العامل <code>‎.‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_53" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">SomeStruct</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> a</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="typ">SomeStruct</span><span class="pln">
var</span><span class="pun">;</span><span class="pln">
</span><span class="com">// var في a الدخول إلى الحقل</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln">
    var</span><span class="pun">.</span><span class="pln">a </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="com">// var في b تعيين الحقل</span><span class="pln">
var</span><span class="pun">.</span><span class="pln">b </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
</span><span class="com">// استدعاء تابع</span><span class="pln">
var</span><span class="pun">.</span><span class="pln">foo</span><span class="pun">();</span></pre>

<p>
	يُستخدم العامل <code>‎-&gt;‎</code> عادة عند محاولة الوصول إلى أعضاء الصنف عبر مؤشّر. كخيار بديل، يمكن تحصيل النُسخة واستخدام العامل <code>‎.‎</code>، لكنّ هذا أقل شيوعًا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_55" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">SomeStruct</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> a</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">SomeStruct</span><span class="pln"> var</span><span class="pun">;</span><span class="pln">
</span><span class="typ">SomeStruct</span><span class="pln"> </span><span class="pun">*</span><span class="pln">p </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">var</span><span class="pun">;</span><span class="pln">
</span><span class="com">// عبر مؤشّر a الوصول إلى المتغير العضو</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> p </span><span class="pun">-&gt;</span><span class="pln"> a </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">(*</span><span class="pln">p</span><span class="pun">).</span><span class="pln">a </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="com">// عبر مؤشّر b تعيين متغير العضو</span><span class="pln">
p </span><span class="pun">-&gt;</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
</span><span class="pun">(*</span><span class="pln">p</span><span class="pun">).</span><span class="pln">b </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
</span><span class="com">// استدعاء دالة تابعة عبر مؤشّر</span><span class="pln">
p </span><span class="pun">-&gt;</span><span class="pln"> foo</span><span class="pun">();</span><span class="pln">
</span><span class="pun">(*</span><span class="pln">p</span><span class="pun">).</span><span class="pln">foo</span><span class="pun">();</span></pre>

<p>
	للوصول إلى أعضاء الصنف الساكنة (static class members)، فإنّنا نستخدم العامل <code>‎::‎</code>، ولكن مع اسم الصنف وليس نسخته، وكخيار بديل، يمكن الوصول إلى الأعضاء الساكنة من نُسخة أو مُؤشّر--إلى-نُسخة باستخدام العامل <code>‎.‎</code> أو <code>‎-&gt;‎</code> على الترتيب، وبنفس الصياغة المُستخدمة للوصول إلى الأعضاء غير الساكنة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_57" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">SomeStruct</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> a</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> c</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> bar</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> </span><span class="typ">SomeStruct</span><span class="pun">::</span><span class="pln">c</span><span class="pun">;</span><span class="pln">
</span><span class="typ">SomeStruct</span><span class="pln"> var</span><span class="pun">;</span><span class="pln">
</span><span class="typ">SomeStruct</span><span class="pun">*</span><span class="pln"> p </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">var</span><span class="pun">;</span><span class="pln">
</span><span class="com">// SomeStruct في البنية c تعيين الحقل الساكن</span><span class="pln">
</span><span class="typ">SomeStruct</span><span class="pun">::</span><span class="pln">c </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln">
</span><span class="com">// p و var عبر SomeStruct في البنية c تعيين متغير العضو الساكن</span><span class="pln">
var</span><span class="pun">.</span><span class="pln">a </span><span class="pun">=</span><span class="pln"> var</span><span class="pun">.</span><span class="pln">c</span><span class="pun">;</span><span class="pln">
var</span><span class="pun">.</span><span class="pln">b </span><span class="pun">=</span><span class="pln"> p</span><span class="pun">-&gt;</span><span class="pln">c</span><span class="pun">;</span><span class="pln">
</span><span class="com">// استدعاء دالة تابعة ساكنة</span><span class="pln">
</span><span class="typ">SomeStruct</span><span class="pun">::</span><span class="pln">bar</span><span class="pun">();</span><span class="pln">
var</span><span class="pun">.</span><span class="pln">bar</span><span class="pun">();</span><span class="pln">
p</span><span class="pun">-&gt;</span><span class="pln">bar</span><span class="pun">();</span></pre>

<p>
	<strong>تفصيل</strong> العامل <code>‎-&gt;‎</code> ضروريّ لأنّ عامل الوصول العضوي <code>‎.‎</code> له الأسبقية على عامل التحصيل <code>‎*‎</code>، وقد يتوقع المرء أنّ <code>‎*p.a‎</code> سيحصل‏‏ <code>‎p‎</code> (لينتج عنه مرجع إلى الكائن المشار إليه من قِبل <code>‎p‎</code>) ثم يصل إلى العضو <code>‎a‎</code>. ولكن في الواقع، فإنّه يحاول الوصول إلى العضو <code>‎a‎</code> من <code>‎p‎</code> قبل أن يحصله، أي أن <code>‎*p.a‎</code> تكافئ <code>‎*(p.a)‎</code>.
</p>

<p>
	في المثال أعلاه، قد ينتج عن هذا خطأ في التصريف لسببين: أولاً، <code>‎p‎</code> مؤشّر وليس له عضو <code>‎a‎</code>. ثانياً، <code>‎a‎</code> عدد صحيح، وبالتالي لا يمكن تحصيله.
</p>

<p>
	أحد الحلول الممكنة -رغم عدم شيوعه- لهذه المشكلة هو التحكّم بشكل صريح (explicitly) في الأسبقية عبر الأقواس: <code>‎(*p).a‎</code>. وهناك حل أكثر شيوعًا، وهو استخدام العامل <code>‎-&gt;‎</code>، وهو حل مختصر لتحصيل المؤشّر ثم الوصول إليه. بمعنى آخر <code>‎(*p).a‎</code> تكافئ <code>‎p-&gt;a‎</code>.
</p>

<p>
	العامل <code>‎::‎</code> هو عامل النطاق (scope operator)، ويُستخدم بنفس طريقة الوصول إلى عضو في فضاء الاسم (namespace). ذلك أنّ الأعضاء الساكنة في الصنف تعدٌّ في نطاق ذلك الصنف، لكنها لا تُعدُّ أعضاءً في نُسخ ذلك الصنف. يُسمح أيضًا باستخدام <code>‎.‎</code> و <code>‎-&gt;‎</code> المعتادتان مع الأعضاء الساكنة، على الرغم من أنهما ليستا عضوتين في النُسخ لأسباب تاريخية، وهذا مفيد لكتابةِ الشيفرات العامة في القوالب لأنّ المُستدعِي لا يعنيه إن كان التابع ساكنًا أو غير ساكن.
</p>

<h2>
	أنواع الأعضاء، والأسماء البديلة / الكُنى
</h2>

<p>
	يمكن لصنف <code>‎class‎</code> أو بنية <code>‎struct‎</code> تعريف الكُنى/الأسماء البديلة (aliases) لنوع عضوي (member type)، وهي أسماء بديلة للنّوع توجد داخل الصنف نفسه وتُعامل كأعضاء منه.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_59" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">IHaveATypedef</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">typedef</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="typ">MyTypedef</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">IHaveATemplateTypedef</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln">
        </span><span class="kwd">using</span><span class="pln"> </span><span class="typ">MyTemplateTypedef</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	يمكن الوصول إلى هذه التعريفات النوعية (typedefs)، مثل الأعضاء الساكنة، باستخدام عامل النطاق <code>‎::‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_61" style="">
<span class="typ">IHaveATypedef</span><span class="pun">::</span><span class="typ">MyTypedef</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln"> </span><span class="com">// عدد صحيح i </span><span class="pln">
</span><span class="typ">IHaveATemplateTypedef</span><span class="pun">::</span><span class="typ">MyTemplateTypedef</span><span class="str">&lt;int&gt;</span><span class="pln"> v</span><span class="pun">;</span><span class="pln"> </span><span class="com">// std::vector&lt;int&gt; من النوع v </span></pre>

<p>
	يُسمح لكُنى الأنواع العضوية -كما هو الحال مع أسماء النوع البديلة (type aliases) العادية- أن تشير إلى أيّ نوع سبق تعريفه أو تكنِيته (aliased) من قبل، لكن ليس بعد تعريفه. وبالمثل، يمكن أن يشير التعريف النوعي (typedef) الموجود خارج الصنف إلى أيّ تعريف نوعي يمكن الوصول إليه داخل الصنف، بشرط أن يأتي بعد تعريف الصنف.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_63" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">IHaveATypedef</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">typedef</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="typ">MyTypedef</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">IHaveATemplateTypedef</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln">
        </span><span class="kwd">using</span><span class="pln"> </span><span class="typ">MyTemplateTypedef</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Helper</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        T get</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="lit">42</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">IHaveTypedefs</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">//    typedef MyTypedef NonLinearTypedef; // سيحدث خطأ في حال إلغاء التعليق</span><span class="pln">
    </span><span class="kwd">typedef</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="typ">MyTypedef</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">typedef</span><span class="pln"> </span><span class="typ">Helper</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">MyTypedef</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="typ">MyTypedefHelper</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">IHaveTypedefs</span><span class="pun">::</span><span class="typ">MyTypedef</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">        </span><span class="com">// x_i is an int.</span><span class="pln">
</span><span class="typ">IHaveTypedefs</span><span class="pun">::</span><span class="typ">MyTypedefHelper</span><span class="pln"> hi</span><span class="pun">;</span><span class="pln">    </span><span class="com">// x_hi is a Helper&lt;int&gt;.</span><span class="pln">
</span><span class="kwd">typedef</span><span class="pln"> </span><span class="typ">IHaveTypedefs</span><span class="pun">::</span><span class="typ">MyTypedef</span><span class="pln"> </span><span class="typ">TypedefBeFree</span><span class="pun">;</span><span class="pln">
</span><span class="typ">TypedefBeFree</span><span class="pln"> ii</span><span class="pun">;</span><span class="pln">                </span><span class="com">// ii is an int.</span></pre>

<p>
	يمكن التصريح عن أسماء النوع العضوي البديلة عبر مستوى وصول (access level)، وستحترم معدَّل الوصول المناسب:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_65" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">TypedefAccessLevels</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">typedef</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="typ">PrvInt</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">typedef</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="typ">ProInt</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">typedef</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="typ">PubInt</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="typ">TypedefAccessLevels</span><span class="pun">::</span><span class="typ">PrvInt</span><span class="pln"> prv_i</span><span class="pun">;</span><span class="pln"> </span><span class="com">// خاص TypedefAccessLevels::PrvInt خطأ، لأن</span><span class="pln">
</span><span class="typ">TypedefAccessLevels</span><span class="pun">::</span><span class="typ">ProInt</span><span class="pln"> pro_i</span><span class="pun">;</span><span class="pln"> </span><span class="com">// محمي TypedefAccessLevels::ProInt خطأ، لأن</span><span class="pln">
</span><span class="typ">TypedefAccessLevels</span><span class="pun">::</span><span class="typ">PubInt</span><span class="pln"> pub_i</span><span class="pun">;</span><span class="pln"> </span><span class="com">// حسنا</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Derived</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">TypedefAccessLevels</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">PrvInt</span><span class="pln"> prv_i</span><span class="pun">;</span><span class="pln"> </span><span class="com">// خاص TypedefAccessLevels::PrvInt خطأ، لأنّ</span><span class="pln">
    </span><span class="typ">ProInt</span><span class="pln"> pro_i</span><span class="pun">;</span><span class="pln"> </span><span class="com">// حسنا</span><span class="pln">
    </span><span class="typ">PubInt</span><span class="pln"> pub_i</span><span class="pun">;</span><span class="pln"> </span><span class="com">// حسنا</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	يساعد هذا على توفير قدر من التجريد، مما يسمح لمصمّم الصنف بتغيير عمله الداخلي دون تعطيل الشّيفرات التي تعتمد عليه.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_67" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Something</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">friend</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">SomeComplexType</span><span class="pun">;</span><span class="pln">

   </span><span class="kwd">short</span><span class="pln"> s</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// ...</span><span class="pln">

    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">typedef</span><span class="pln"> </span><span class="typ">SomeComplexType</span><span class="pln"> </span><span class="typ">MyHelper</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">MyHelper</span><span class="pln"> get_helper</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">MyHelper</span><span class="pun">(</span><span class="lit">8</span><span class="pun">,</span><span class="pln"> s</span><span class="pun">,</span><span class="pln"> </span><span class="lit">19.5</span><span class="pun">,</span><span class="pln"> </span><span class="str">"shoe"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="com">// ...</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="com">// ...</span><span class="pln">

</span><span class="typ">Something</span><span class="pln"> s</span><span class="pun">;</span><span class="pln">
</span><span class="typ">Something</span><span class="pun">::</span><span class="typ">MyHelper</span><span class="pln"> hlp </span><span class="pun">=</span><span class="pln"> s</span><span class="pun">.</span><span class="pln">get_helper</span><span class="pun">();</span></pre>

<p>
	في هذه الحالة، إذا تغير الصنف المساعد من <code>‎SomeComplexType‎</code> إلى نوع آخر فلن تحتاج إلّا إلى تعديل تصريح <code>‎typedef‎</code> و <code>‎friend‎</code> طالما يوفّر الصنف المساعد نفس الوظيفة، كما أنّ أيّ شيفرة تستخدمه كـ <code>‎Something::MyHelper‎</code> بدلاً من تحديده باسمه لن تحتاج إلى أيّ تعديلات. وهكذا نقلّل مقدار الشيفرة التي يجب تعديلها عند تغييرالتنفيذ إذ لن نحتاج إلى تغيير اسم النوع إلا في مكان واحد.
</p>

<p>
	يمكنك أيضًا دمج هذا مع <code>‎decltype‎</code>، إذا رغبت في ذلك.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_69" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">SomethingElse</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">AnotherComplexType</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">bool</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">SomeThirdClass</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> helper</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">typedef</span><span class="pln"> </span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">helper</span><span class="pun">)</span><span class="pln"> </span><span class="typ">MyHelper</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">InternalVariable</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">MyHelper</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> ivh</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// ...</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">MyHelper</span><span class="pun">&amp;</span><span class="pln"> get_helper</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> helper</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
    </span><span class="com">// ...</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	في هذه الحالة، سيؤدي تغيير تقديم <code>‎SomethingElse::helper‎</code> إلى تغيير التعريف النوعي (typedef) تلقائيًا بفضل <code>‎decltype‎</code>. هذا يقلّل من عدد التعديلات اللازمة عندما نريد تغيير الصنف المساعد <code>‎helper‎</code>، كما يقلّل من الأخطاء البشرية.
</p>

<p>
	إذا لم يكن اسم النوع يُستخدَم إلّا مرّة واحدة أو مرتين داخليًا، ولم يكن يُستخدَم أبدًا في الخارج على سبيل المثال، فليست هناك حاجة لتوفير كُنية له. أمّا إذا كان يُستخدم مئات أو آلاف المرّات داخل المشروع أو كان له اسم طويل، فقد يكون من المفيد توفيره كتعريف نوعي (typedef) بدلًا من استخدامه باسمه الأساسي. يجب عليك أن تدرس الأمر قبل اختيار الطريقة التي تريد العمل بها.
</p>

<p>
	يمكن أيضًا استخدام هذا مع أصناف القوالب لتوفير حقّ الوصول إلى معاملات القالب من خارج الصنف.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_71" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">SomeClass</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// ...</span><span class="pln">

       </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">typedef</span><span class="pln"> T </span><span class="typ">MyParam</span><span class="pun">;</span><span class="pln">
         </span><span class="typ">MyParam</span><span class="pln"> getParam</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="lit">42</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">

</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">::</span><span class="typ">MyParam</span><span class="pln"> some_func</span><span class="pun">(</span><span class="pln">T </span><span class="pun">&amp;</span><span class="pln"> t</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> t</span><span class="pun">.</span><span class="pln">getParam</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

</span><span class="typ">SomeClass</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> si</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> some_func</span><span class="pun">(</span><span class="pln">si</span><span class="pun">);</span></pre>

<p>
	يَشيع استخدام هذا مع الحاويات التي عادة ما توفر نوع العنصر الخاص بها (والأنواع المساعِدة الأخرى) كأسماء بديلة لنوع عضوي (member type aliases). وتوفّر معظم الحاويات الموجودة في المكتبة القياسية للغة C++‎ الأنواع المساعدة الاثنتي عشر التالية، إضافة إلى أنواع خاصة أخرى.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_73" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">SomeContainer</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// ...</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
</span><span class="com">// توفير نفس الأنواع المساعدة للحاويات القياسية</span><span class="pln">
</span><span class="kwd">typedef</span><span class="pln"> T                         value_type</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">typedef</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">allocator</span><span class="str">&lt;value_type&gt;</span><span class="pln">         allocator_type</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">typedef</span><span class="pln"> value_type</span><span class="pun">&amp;</span><span class="pln">                 reference</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">typedef</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> value_type</span><span class="pun">&amp;</span><span class="pln">             const_reference</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">typedef</span><span class="pln"> value_type</span><span class="pun">*</span><span class="pln">                 pointer</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">typedef</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> value_type</span><span class="pun">*</span><span class="pln">                 const_pointer</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">typedef</span><span class="pln"> </span><span class="typ">MyIterator</span><span class="str">&lt;value_type&gt;</span><span class="pln">             </span><span class="typ">iterator</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">typedef</span><span class="pln"> </span><span class="typ">MyConstIterator</span><span class="str">&lt;value_type&gt;</span><span class="pln">         </span><span class="typ">const_iterator</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">typedef</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">reverse_iterator</span><span class="str">&lt;iterator&gt;</span><span class="pln">         reverse_iterator</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">typedef</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">reverse_iterator</span><span class="str">&lt;const_iterator&gt;</span><span class="pln">     const_reverse_iterator</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">typedef</span><span class="pln"> </span><span class="typ">size_t</span><span class="pln">                     size_type</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">typedef</span><span class="pln"> </span><span class="typ">ptrdiff_t</span><span class="pln">                     difference_type</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	كان توفير "قالب <code>‎typedef‎</code>" شائعًا قبل الإصدار C++‎ 11، وقد أصبحت هذه الطريقة أقل شيوعًا مع إضافة ميزة كُنَى القوالب، لكنّها ما تزال مفيدة في بعض المواقف، وتُدمج مع كُنى القوالب في مواقف أخرى، قد يكون هذا مفيدًا جدًا في الحصول على مكوِّنات فردية من نوع معقّد، مثل مؤشّر دالّة ما. كذلك يكثر استخدام الاسم <code>‎type‎</code> للاسم البديل للنوع. انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_75" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">TemplateTypedef</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">typedef</span><span class="pln"> T type</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="typ">TemplateTypedef</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="pln">type i</span><span class="pun">;</span><span class="pln">        </span><span class="com">// هو رقم صحيح i.</span></pre>

<p>
	يُستخدم هذا غالبًا مع الأنواع التي لها عدّة معاملات قوالب، لتوفير اسم بديل يُعرّف معاملًا واحدًا أو أكثر.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_77" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> </span><span class="typ">size_t</span><span class="pln"> SZ</span><span class="pun">,</span><span class="pln"> </span><span class="typ">size_t</span><span class="pln"> D </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Array</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">/* ... */</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> </span><span class="typ">size_t</span><span class="pln"> SZ </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">OneDArray</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">typedef</span><span class="pln"> </span><span class="typ">Array</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> SZ</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> type</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> </span><span class="typ">size_t</span><span class="pln"> SZ </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">TwoDArray</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">typedef</span><span class="pln"> </span><span class="typ">Array</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> SZ</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> type</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">MonoDisplayLine</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">typedef</span><span class="pln"> </span><span class="typ">Array</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> </span><span class="lit">80</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> type</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
</span><span class="typ">OneDArray</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="pln">type arr1i</span><span class="pun">;</span><span class="pln">        </span><span class="com">// Array&lt;int, 3, 1&gt; مصفوفة من النوع arr1i </span><span class="pln">
</span><span class="typ">TwoDArray</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">short</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="pln">type arr2s</span><span class="pun">;</span><span class="pln">    </span><span class="com">// Array&lt;short, 5, 2&gt; مصفوفة من النوع arr2s </span><span class="pln">
</span><span class="typ">MonoDisplayLine</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="pln">type arr3c</span><span class="pun">;</span><span class="pln">    </span><span class="com">// Array&lt;char, 80, 1&gt; مصفوفة من النوع arr3c</span></pre>

<h2>
	الأصناف والبِنيات المُتشعِّبة (Nested Classes/Structures)
</h2>

<p>
	يمكن أن يحتوي صنف <code>‎class‎</code> أو بنية <code>‎struct‎</code> على تعريف صنف أو بنية أخرى داخله، وسيُسمى "صنفًا متشعبًا" (nested class)، بينما يُشار إلى الصنف الذي يحتوي التعريف "بالصنف المُحيط" (enclosing class)، ويعدُّ الصنف المتشعِّب عضوًا في الصنف المُحيط لكنه منفصل عنه.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_79" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Outer</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Inner</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	يمكن الوصول إلى الأصناف المتشعِّبة من خارج الصنف المُحيط باستخدام عامل النطاق، أمّا من داخل الصنف المُحيط، فيمكن استخدام الأصناف المتشعِّبة بدون مؤهلات:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_81" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Outer</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Inner</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
    </span><span class="typ">Inner</span><span class="pln"> in </span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="com">// ...</span><span class="pln">
</span><span class="typ">Outer</span><span class="pln"> o</span><span class="pun">;</span><span class="pln">
</span><span class="typ">Outer</span><span class="pun">::</span><span class="typ">Inner</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> o</span><span class="pun">.</span><span class="pln">in</span><span class="pun">;</span></pre>

<p>
	وكما هو الحال مع الأصناف والبنيات غير المُتشعِّبة، يمكن تعريف التوابع والمتغيّرات الساكنة إما داخل الصنف المتشعِّب، أو في فضاء الاسم (namespace) المُحيط، لكن لا يمكن تعريفها داخل الصنف المُحيط لأنه يُعتبر صنفًا مختلفًا عن الصنف المتشعِّب.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_83" style="">
<span class="com">// خطأ</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Outer</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Inner</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">void</span><span class="pln"> do_something</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">

    </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Inner</span><span class="pun">::</span><span class="pln">do_something</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="com">// ممتاز</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Outer</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Inner</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">void</span><span class="pln"> do_something</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Outer</span><span class="pun">::</span><span class="typ">Inner</span><span class="pun">::</span><span class="pln">do_something</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span></pre>

<p>
	بالمثل، وكما هو الحال مع الأصناف غير المتشعِّبة، يمكن التصريح مُسبقًا (forward declared) عن الأصناف المتشعِّبة ثم تعريفها لاحقًا، شريطة أن تُعرّف قبل استخدامها.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_85" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Outer</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Inner1</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Inner2</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Inner1</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">

    </span><span class="typ">Inner1</span><span class="pln"> in1</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">Inner2</span><span class="pun">*</span><span class="pln"> in2p</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">Outer</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">~</span><span class="typ">Outer</span><span class="pun">();</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Outer</span><span class="pun">::</span><span class="typ">Inner2</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">

</span><span class="typ">Outer</span><span class="pun">::</span><span class="typ">Outer</span><span class="pun">():</span><span class="pln"> in1</span><span class="pun">(</span><span class="typ">Inner1</span><span class="pun">()),</span><span class="pln"> in2p</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Inner2</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="typ">Outer</span><span class="pun">::~</span><span class="typ">Outer</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">in2p</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">delete</span><span class="pln"> in2p</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<strong>الإصدار &lt;C++‎ 11</strong>
</p>

<p>
	لم يكن للأصناف المتشعِّبة قبل الإصدار C++‎ 11 حق الوصول إلّا إلى أسماء الأنواع (type names) والأعضاء الساكنة (<code>‎static‎</code>) والعدّادات (enumerators) من الصنف المُحيط، ولم تكن الأعضاء الأخرى المعرَّفة في الصنف المحيط متاحة.
</p>

<p>
	<strong><strong>الإصدار ≥ C++‎ 11</strong> </strong>
</p>

<p>
	وبدءًا من الإصدار C++‎ 11، تُعامل الأصناف المتشعِّبة وأعضاؤها كما لو كانت صديقة (<code>‎friend‎</code>) للصنف المُحيط، وصار بإمكانها الوصول إلى جميع أعضائه وفقًا لقواعد الوصول المعتادة، وإذا كان أعضاء الصنف المتشعِّب يحتاجون إلى تقييم عضو ساكن أو أكثر من الصنف المُحيط، فيجب أن تُمرّر نُسخة إليها:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_87" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Outer</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Inner</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> get_sizeof_x</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="pln">x</span><span class="pun">);</span><span class="pln"> </span><span class="com">// غير مُقيّم، لذلك هناك حاجة إلى نسخة x </span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> get_x</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> x</span><span class="pun">;</span><span class="pln"> </span><span class="com">// لا يمكن الوصول إلى الأعضاء غير الساكنين بدون نسخة</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> get_x</span><span class="pun">(</span><span class="typ">Outer</span><span class="pun">&amp;</span><span class="pln"> o</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> o</span><span class="pun">.</span><span class="pln">x</span><span class="pun">;</span><span class="pln"> </span><span class="com">// الوصول إلى الأعضاء الخاصة Inner بإمكان  Outer كعضو من </span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	بالمقابل، لا يُعامَل الصنف المُحيط كصديق للصنف المتشعِّب، وعليه لا يمكنه الوصول إلى أعضائه دون الحصول على إذن صريح.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_89" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Outer</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Inner</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// friend class Outer;</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
    </span><span class="typ">Inner</span><span class="pln"> in </span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> get_x</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> in</span><span class="pun">.</span><span class="pln">x</span><span class="pun">;</span><span class="pln"> </span><span class="com">// Error: int Outer::Inner::x is private.</span><span class="pln">
            </span><span class="com">// لإصلاح المشكلة "friend" الغ تعليق</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	لا يُعدّ أصدقاء الصنف المتشعِّب تلقائيًا أصدقاءً للصنف المحيط؛ فالصداقة مع الصنف المحيط ينبغي التصريح عنها بشكل منفصل. بالمقابل، بما أن الصنف المُحيط لا يُعدُّ صديقًا للصنف المتشعِّب تلقائيًا ، فلن يكون أصدقاء الصنف المُحيط أصدقاءً للصنف المتشعِّب.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_91" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Outer</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
   </span><span class="kwd">friend</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> barge_out</span><span class="pun">(</span><span class="typ">Outer</span><span class="pun">&amp;</span><span class="pln"> out</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Inner</span><span class="pun">&amp;</span><span class="pln"> in</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Inner</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">friend</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> barge_in</span><span class="pun">(</span><span class="typ">Outer</span><span class="pun">&amp;</span><span class="pln"> out</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Inner</span><span class="pun">&amp;</span><span class="pln"> in</span><span class="pun">);</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> o</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> barge_in</span><span class="pun">(</span><span class="typ">Outer</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> out</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Outer</span><span class="pun">::</span><span class="typ">Inner</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> in </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> in </span><span class="pun">.</span><span class="pln">i</span><span class="pun">;</span><span class="pln"> </span><span class="com">// جيد</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> o </span><span class="pun">=</span><span class="pln"> out</span><span class="pun">.</span><span class="pln">o</span><span class="pun">;</span><span class="pln"> </span><span class="com">// خاص int Outer::o خطأ: لأن</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> barge_in</span><span class="pun">(</span><span class="typ">Outer</span><span class="pun">&amp;</span><span class="pln"> out</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Outer</span><span class="pun">::</span><span class="typ">Inner</span><span class="pun">&amp;</span><span class="pln"> in</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> in </span><span class="pun">.</span><span class="pln">i</span><span class="pun">;</span><span class="pln"> </span><span class="com">// خاص int Outer::Inner::i خطأ: لأن</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> o </span><span class="pun">=</span><span class="pln"> out</span><span class="pun">.</span><span class="pln">o</span><span class="pun">;</span><span class="pln"> </span><span class="com">// جيد</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	كما هو الحال مع جميع أعضاء الصنف الآخرين، لا يمكن تسمية الأصناف المتشعِّبة من خارج الصنف إلا إذا كانت عامّة (public). لكن يُسمح لك بالوصول إليها بغض النظر عن مُعدِّل الوصول طالما أنك لا تُسمّيها صراحة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_93" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Outer</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Inner</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">void</span><span class="pln"> func</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"I have no private taboo.\n"</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">Inner</span><span class="pln"> make_Inner</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">Inner</span><span class="pun">();</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="com">// ...</span><span class="pln">
</span><span class="typ">Outer</span><span class="pun">::</span><span class="typ">Inner</span><span class="pln"> oi</span><span class="pun">;</span><span class="pln"> </span><span class="com">// خاص Outer::Inner خطأ: لأن</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> oi </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Outer</span><span class="pun">::</span><span class="pln">make_Inner</span><span class="pun">();</span><span class="pln"> </span><span class="com">// جيد</span><span class="pln">
oi</span><span class="pun">.</span><span class="pln">func</span><span class="pun">();</span><span class="pln"> </span><span class="com">// جيد</span><span class="pln">
</span><span class="typ">Outer</span><span class="pun">::</span><span class="pln">make_Inner</span><span class="pun">().</span><span class="pln">func</span><span class="pun">();</span><span class="pln"> </span><span class="com">// جيد</span></pre>

<p>
	يمكنك أيضًا إنشاء كُنية نوع للصنف المتشعِّب، وإذا كانت كُنية النوع موجودة في الصنف المحيط فيمكن أن يكون للنوع المتشعِّب وكُنية النوع مُحدِّدا وصول مختلفّين. وإذا كانت كُنية النوع موجودة خارج الصنف المُحيط، فإن ذلك يتطلب إمّا أن يكون الصنف المتشعِّب عامًّا (public)، أو نوع التعريف (<code>‎typedef‎</code>)، أيهما.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_95" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Outer</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Inner_</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">typedef</span><span class="pln"> </span><span class="typ">Inner_</span><span class="pln"> </span><span class="typ">Inner</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">typedef</span><span class="pln"> </span><span class="typ">Outer</span><span class="pun">::</span><span class="typ">Inner</span><span class="pln"> </span><span class="typ">ImOut</span><span class="pun">;</span><span class="pln"> </span><span class="com">// جيد</span><span class="pln">
</span><span class="kwd">typedef</span><span class="pln"> </span><span class="typ">Outer</span><span class="pun">::</span><span class="typ">Inner_</span><span class="pln"> </span><span class="typ">ImBad</span><span class="pun">;</span><span class="pln"> </span><span class="com">// خطأ</span><span class="pln">
</span><span class="com">// ...</span><span class="pln">
</span><span class="typ">Outer</span><span class="pun">::</span><span class="typ">Inner</span><span class="pln"> oi</span><span class="pun">;</span><span class="pln"> </span><span class="com">// جيد</span><span class="pln">
</span><span class="typ">Outer</span><span class="pun">::</span><span class="typ">Inner_</span><span class="pln"> oi</span><span class="pun">;</span><span class="pln"> </span><span class="com">// خطأ</span><span class="pln">
</span><span class="typ">ImOut</span><span class="pln"> oi</span><span class="pun">;</span><span class="pln"> </span><span class="com">// جيد</span></pre>

<p>
	كما هو الحال مع الأصناف الأخرى، يمكن الاشتقاق من الأصناف المتشعِّبة، ويمكنها أن تشتق من أصناف أخرى.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_97" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Outer</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Inner</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Derived</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Outer</span><span class="pun">::</span><span class="typ">Inner</span><span class="pln"> </span><span class="pun">{};</span></pre>

<p>
	هذا مفيد في الحالات التي يكون هناك صنف مشتقّ من الصنف المُحيط، إذ يسمح ذلك للمُبرمج بتحديث الصنف المتشعِّب عند الضرورة، ويمكن دمج ذلك مع تعريف نوعيٍّ (typedef) لتوفير اسم ثابت لكل صنف متشعِّب من الصنف المُحيط:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_99" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">BaseOuter</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">BaseInner_</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">virtual</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> do_something</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
        </span><span class="kwd">virtual</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> do_something_else</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    b_in</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">typedef</span><span class="pln"> </span><span class="typ">BaseInner_</span><span class="pln"> </span><span class="typ">Inner</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">virtual</span><span class="pln"> </span><span class="pun">~</span><span class="typ">BaseOuter</span><span class="pun">()</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">virtual</span><span class="pln"> </span><span class="typ">Inner</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> getInner</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> b_in</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> </span><span class="typ">BaseOuter</span><span class="pun">::</span><span class="typ">BaseInner_</span><span class="pun">::</span><span class="pln">do_something_else</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="com">// ---</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">DerivedOuter</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">BaseOuter</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// BaseOuter::BaseInner_ is private لاحظ استخدام النوع التعريفي المؤهل</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">DerivedInner_</span><span class="pun">:</span><span class="pln"> </span><span class="typ">BaseOuter</span><span class="pun">::</span><span class="typ">Inner</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">void</span><span class="pln"> do_something</span><span class="pun">()</span><span class="pln"> override </span><span class="pun">{}</span><span class="pln">
        </span><span class="kwd">void</span><span class="pln"> do_something_else</span><span class="pun">()</span><span class="pln"> override</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    d_in</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">typedef</span><span class="pln"> </span><span class="typ">DerivedInner_</span><span class="pln"> </span><span class="typ">Inner</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">BaseOuter</span><span class="pun">::</span><span class="typ">Inner</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> getInner</span><span class="pun">()</span><span class="pln"> override </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> d_in</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> </span><span class="typ">DerivedOuter</span><span class="pun">::</span><span class="typ">DerivedInner_</span><span class="pun">::</span><span class="pln">do_something_else</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="com">// ...</span><span class="pln">
</span><span class="com">// BaseOuter::BaseInner_::do_something(); استدعاء</span><span class="pln">
</span><span class="typ">BaseOuter</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">BaseOuter</span><span class="pun">;</span><span class="pln">
</span><span class="typ">BaseOuter</span><span class="pun">::</span><span class="typ">Inner</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> bin </span><span class="pun">=</span><span class="pln"> b </span><span class="pun">-&gt;</span><span class="pln"> getInner</span><span class="pun">();</span><span class="pln">
bin</span><span class="pun">.</span><span class="pln">do_something</span><span class="pun">();</span><span class="pln">
b </span><span class="pun">-&gt;</span><span class="pln"> getInner</span><span class="pun">().</span><span class="pln">do_something</span><span class="pun">();</span><span class="pln">
</span><span class="com">// DerivedOuter::DerivedInner_::do_something(); استدعاء</span><span class="pln">
</span><span class="typ">BaseOuter</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> d </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">DerivedOuter</span><span class="pun">;</span><span class="pln">
</span><span class="typ">BaseOuter</span><span class="pun">::</span><span class="typ">Inner</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> din </span><span class="pun">=</span><span class="pln"> d </span><span class="pun">-&gt;</span><span class="pln"> getInner</span><span class="pun">();</span><span class="pln">
din</span><span class="pun">.</span><span class="pln">do_something</span><span class="pun">();</span><span class="pln">
d </span><span class="pun">-&gt;</span><span class="pln"> getInner</span><span class="pun">().</span><span class="pln">do_something</span><span class="pun">();</span></pre>

<p>
	في الحالة أعلاه، يقدّم كل من الصِّنفين <code>‎BaseOuter‎</code> و <code>‎DerivedOuter‎</code> النوع العُضوي <code>‎Inner‎</code> كـ <code>‎BaseInner_‎</code> و <code>‎DerivedInner_‎</code> على الترتيب، ويسمح هذا بااشتقاق الأنواع المتشعِّبة دون تعطيل واجهة الصِّنف المُحيط، كما يسمح باستخدام النوع المتشعِّب بأشكال متعددة.
</p>

<h2>
	البِنيات والأصناف غير المُسمّاة (Unnamed struct/class)
</h2>

<p>
	يُسمح باستخدام البِنيات غير المُسمّاة (نوع ليس له اسم):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_101" style="">
<span class="kwd">void</span><span class="pln"> foo</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> </span><span class="com">/* No name */</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">float</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
        </span><span class="typ">float</span><span class="pln"> y</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    point</span><span class="pun">;</span><span class="pln">

    point</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	أو
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_103" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Circle</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> </span><span class="com">/* بلا اسم */</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">float</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
        </span><span class="typ">float</span><span class="pln"> y</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    center</span><span class="pun">;</span><span class="pln"> </span><span class="com">// لكن مع أعضاء لها اسم</span><span class="pln">
    </span><span class="typ">float</span><span class="pln"> radius</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	يمكن أن نكتب الآن:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_105" style="">
<span class="typ">Circle</span><span class="pln"> circle</span><span class="pun">;</span><span class="pln">
circle</span><span class="pun">.</span><span class="pln">center</span><span class="pun">.</span><span class="pln">x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42.f</span><span class="pun">;</span></pre>

<p>
	لكن لا يُسمح بالبنيات المجهولة - anonymous struct - (نوع غير مسمّى وكائن غير مسمّى)
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_107" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">InvalidCircle</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> </span><span class="com">/* بلا اسم */</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">float</span><span class="pln"> centerX</span><span class="pun">;</span><span class="pln">
        </span><span class="typ">float</span><span class="pln"> centerY</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">};</span><span class="pln"> </span><span class="com">// لا أعضاء كذلك</span><span class="pln">
    </span><span class="typ">float</span><span class="pln"> radius</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	<strong>ملاحظة</strong>: تسمح بعض المُصرِّفات بالبُنى المجهولة كملحقات.
</p>

<p>
	<strong>الإصدار ≥ C++‎ 11 </strong>
</p>

<ul>
<li>
		يمكن النظر إلى تعبيرات لامدا كبنية خاصة غير مُسمّاة.
	</li>
	<li>
		تسمح <code>‎decltype‎</code> بالحصول على نوع بنية غير مسمّاة:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_109" style="">
<span class="kwd">decltype</span><span class="pun">(</span><span class="pln">circle</span><span class="pun">.</span><span class="pln">point</span><span class="pun">)</span><span class="pln"> otherPoint</span><span class="pun">;</span></pre>

<ul>
<li>
		يمكن أن تكون نُسخ البنيات غير المسمّاة معاملات لتابع قالب (template method):
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_113" style="">
<span class="kwd">void</span><span class="pln"> print_square_coordinates</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">struct</span><span class="pln"> </span><span class="pun">{</span><span class="typ">float</span><span class="pln"> x</span><span class="pun">;</span><span class="pln"> </span><span class="typ">float</span><span class="pln"> y</span><span class="pun">;}</span><span class="pln"> points</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="pun">{-</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="pun">-</span><span class="lit">1</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{-</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="pun">-</span><span class="lit">1</span><span class="pun">},</span><span class="pln"> </span><span class="pun">{</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="com">// template &lt;class T, std::size_t N&gt; std::begin(T (&amp;)[N]) بالنسبة لمجال يعتمد على</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">auto</span><span class="pun">&amp;</span><span class="pln"> point </span><span class="pun">:</span><span class="pln"> points</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"{"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> point</span><span class="pun">.</span><span class="pln">x </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> point</span><span class="pun">.</span><span class="pln">y </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"}\n"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">points</span><span class="pun">[</span><span class="lit">0</span><span class="pun">])</span><span class="pln"> topRightCorner</span><span class="pun">{</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> it </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">find</span><span class="pun">(</span><span class="pln">points</span><span class="pun">,</span><span class="pln"> points </span><span class="pun">+</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln"> topRightCorner</span><span class="pun">);</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"top right corner is the "</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">distance</span><span class="pun">(</span><span class="pln">points</span><span class="pun">,</span><span class="pln"> it</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"th\n"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	أعضاء الصنف الساكنة
</h2>

<p>
	يُسمح للصنف أن يكون له أعضاء ساكنة (<code>‎static‎</code>) قد تكون متغيرات أو دوالًا، وتعدُّ هذه الأعضاء في نطاق الصنف لكنها لا تُعامل كأعضاء عاديّة، إذ أنها تتميّز بمدة تخزين ثابتة (تستمرّ في الوجود من بداية البرنامج وحتى نهايته)، ولا ترتبط بنُسخة معيّنة من الصنف، ولا يوجد منها سوى نسخة واحدة للصنف بأكمله.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_115" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Example</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">static</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> num_instances</span><span class="pun">;</span><span class="pln">    </span><span class="com">// حقل ساكن</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">                </span><span class="com">// حقل غير ساكن</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
</span><span class="kwd">static</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string static_str</span><span class="pun">;</span><span class="pln">    </span><span class="com">// حقل ساكن</span><span class="pln">
</span><span class="kwd">static</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> static_func</span><span class="pun">();</span><span class="pln">    </span><span class="com">// تابع ساكن</span><span class="pln">

</span><span class="com">// يجوز للتوابع غير الساكنة تعديل الحقول الساكنة</span><span class="pln">
    </span><span class="typ">Example</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="pun">++</span><span class="pln">num_instances</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> set_str</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&amp;</span><span class="pln"> str</span><span class="pun">);</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> </span><span class="typ">Example</span><span class="pun">::</span><span class="pln">num_instances</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">string </span><span class="typ">Example</span><span class="pun">::</span><span class="pln">static_str </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Hello."</span><span class="pun">;</span><span class="pln">

</span><span class="com">// ...</span><span class="pln">

</span><span class="typ">Example</span><span class="pln"> one</span><span class="pun">,</span><span class="pln"> two</span><span class="pun">,</span><span class="pln"> three
</span><span class="com">// الخاصة به، مثل ما يلي “i” كل مثال لديه :</span><span class="pln">
</span><span class="com">//  (&amp;one.i != &amp;two.i)</span><span class="pln">
</span><span class="com">//  (&amp;one.i != &amp;three.i)</span><span class="pln">
</span><span class="com">//  (&amp;two.i != &amp;three.i).</span><span class="pln">
</span><span class="com">// انظر ما يلي ، “num_instances” تتشارك الأمثلة الثلاثة:</span><span class="pln">
</span><span class="com">//  (&amp;one.num_instances == &amp;two.num_instances)</span><span class="pln">
</span><span class="com">//  (&amp;one.num_instances == &amp;three.num_instances)</span><span class="pln">
</span><span class="com">//  (&amp;two.num_instances == &amp;three.num_instances)</span></pre>

<p>
	لا تُعدُّ الحقول الساكنة مُعرَّفة داخل الصنف ولكنّها تُعدّ مُصرّحة فقط، وعليه سيكون تعريفها خارج تعريف الصنف. يُسمح للمبرمج بتهيئة المتغيّرات الساكنة في التعريف لكنه غير ملزَم بهذا، وعند تعريف المتغيرات العضوية تُحذف الكلمة المفتاحية <code>‎static‎</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_117" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Example</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> num_instances</span><span class="pun">;</span><span class="pln">            </span><span class="com">// تصريح</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">static</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string static_str</span><span class="pun">;</span><span class="pln">            </span><span class="com">// تصريح</span><span class="pln">
    </span><span class="com">// ...</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> </span><span class="typ">Example</span><span class="pun">::</span><span class="pln">num_instances</span><span class="pun">;</span><span class="pln">            </span><span class="com">// تعريف مُهيّأ صفريًا.</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">string </span><span class="typ">Example</span><span class="pun">::</span><span class="pln">static_str </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Hello."</span><span class="pun">;</span><span class="pln">        </span><span class="com">// تعريف  </span></pre>

<p>
	لهذا السبب، يمكن أن تكون المتغيرات الساكنة أنواعًا غير مكتملة (بخلاف <code>‎void‎</code>)، طالما عُرِّفت لاحقًا كنوع كامل.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_119" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">ForwardDeclared</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">ExIncomplete</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">ForwardDeclared</span><span class="pln"> fd</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">ExIncomplete</span><span class="pln"> i_contain_myself</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> an_array</span><span class="pun">[];</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">ForwardDeclared</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">

</span><span class="typ">ForwardDeclared</span><span class="pln">    </span><span class="typ">ExIncomplete</span><span class="pun">::</span><span class="pln">fd</span><span class="pun">;</span><span class="pln">
</span><span class="typ">ExIncomplete</span><span class="pln">    </span><span class="typ">ExIncomplete</span><span class="pun">::</span><span class="pln">i_contain_myself</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln">            </span><span class="typ">ExIncomplete</span><span class="pun">::</span><span class="pln">an_array</span><span class="pun">[</span><span class="lit">5</span><span class="pun">];</span></pre>

<p>
	يمكن تعريف الدوال التابعة الساكنة داخل أو خارج تعريف الصنف كما هو حال الدوال التابعة العادية، وكما هو الحال مع المتغيرات العضوية الساكنة، تُحذَف الكلمة المفتاحية <code>‎static‎</code> في حال تعريف العضو الساكن خارج تعريف الصنف.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_121" style="">
<span class="com">// بالنسبة للمثال أعلاه، إما</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Example</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// ...</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> static_func</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> num_instances</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="com">// ...</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> set_str</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">&amp;</span><span class="pln"> str</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        static_str </span><span class="pun">=</span><span class="pln"> str</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="com">// أو</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Example</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">/* ... */</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> </span><span class="typ">Example</span><span class="pun">::</span><span class="pln">static_func</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> num_instances</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Example</span><span class="pun">::</span><span class="pln">set_str</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">&amp;</span><span class="pln"> str</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    static_str </span><span class="pun">=</span><span class="pln"> str</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	في حال التصريح عن حقل على أنه ثابت (<code>‎const‎</code>) وليس متغيّرًا (<code>‎volatile‎</code>)، وكان من نوع عددي صحيح (integral) أو تِعدادي (enumeration)، فيمكن تهيئته عند التصريح عنه داخل تعريف الصنف.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_123" style="">
<span class="kwd">enum</span><span class="pln"> E </span><span class="pun">{</span><span class="pln"> VAL </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pln"> </span><span class="pun">};</span><span class="pln">

</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">ExConst</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> ci </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln">            </span><span class="com">// جيد.</span><span class="pln">
</span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> E ce </span><span class="pun">=</span><span class="pln"> VAL</span><span class="pun">;</span><span class="pln">            </span><span class="com">// جيد.</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> cd </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln">            </span><span class="com">// خطأ.</span><span class="pln">
</span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">volatile</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> cvi </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln">        </span><span class="com">// خطأ.</span><span class="pln">

</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> good_cd</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">volatile</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> good_cvi</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> </span><span class="typ">ExConst</span><span class="pun">::</span><span class="pln">good_cd </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln">        </span><span class="com">// جيد.</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">volatile</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="typ">ExConst</span><span class="pun">::</span><span class="pln">good_cvi </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln">        </span><span class="com">// جيد.</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 11 </strong>
</p>

<p>
	بدءًا من الإصدار C++‎ 11، يمكن تعريف المتغيرات العضوية الساكنة من الأنواع <code>‎LiteralType‎</code> (أنواع يمكن إنشاؤها في وقت التصريف وفقًا لقواعد التعبيرات الثابتة <code>‎constexpr‎</code>) كتعبيرات ثابتة؛ لكن يجب أن تُهيّأ داخل تعريف الصنف.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_125" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">ExConstexpr</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">constexpr</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> ci </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln">                    </span><span class="com">// جيد.</span><span class="pln">
</span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">constexpr</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> cd </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln">                </span><span class="com">// جيد.</span><span class="pln">
</span><span class="kwd">constexpr</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> carr</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">};</span><span class="pln">            </span><span class="com">// جيد.</span><span class="pln">
</span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">constexpr</span><span class="pln"> </span><span class="typ">ConstexprConstructibleClass</span><span class="pln"> c</span><span class="pun">{};</span><span class="pln">    </span><span class="com">// جيد.</span><span class="pln">
</span><span class="kwd">constexpr</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> bad_ci</span><span class="pun">;</span><span class="pln"> </span><span class="com">// Error.</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">constexpr</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="typ">ExConstexpr</span><span class="pun">::</span><span class="pln">bad_ci </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln">                </span><span class="com">// خطأ كذلك.</span></pre>

<p>
	في حال تمّ أخذ عنوان (odr-used) لمتغير عضوي ساكن من النوع الثابت (<code>‎const‎</code>) أو <code>‎constexpr‎</code>، أو عُيَّن إلى مرجع فينبغي أن يكون له تعريف منفصل خارج تعريف الصنف، ولا يُسمح لهذا التعريف باحتواء مُهيّئ.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_127" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">ExODR</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">static</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> odr_used </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="com">// const int ExODR::odr_used;</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pun">*</span><span class="pln"> odr_user </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="typ">ExODR</span><span class="pun">::</span><span class="pln">odr_used</span><span class="pun">;</span><span class="pln"> </span><span class="com">// خطأ، ألغ تعليق السطر أعلاه لحل المشكلة</span></pre>

<p>
	يمكن الوصول إلى الأعضاء الساكنة باستخدام عامل النطاق <code>‎::‎</code> بما أنها لأنّها غير مرتبطة بنُسخة معيّنة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_130" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">string str </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Example</span><span class="pun">::</span><span class="pln">static_str</span><span class="pun">;</span></pre>

<p>
	يمكن أيضًا الوصول إليها كما لو كانت أعضاءً عادية وغير ساكنة، هذا له دلالة تاريخية ولكنه يُستخدم بشكل أقل من عامل النطاق لأنه يمنع أيّ لبس بخصوص ما إذا كان العضو ساكنًا أم لا.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_132" style="">
<span class="typ">Example</span><span class="pln"> ex</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">string rts </span><span class="pun">=</span><span class="pln"> ex</span><span class="pun">.</span><span class="pln">static_str</span><span class="pun">;</span></pre>

<p>
	يمكن لأعضاء الصنف الوصول إلى الأعضاء الساكنة دون الحاجة إلى تأهيل نطاقهم (qualifying their scope)، كما هو الحال مع أعضاء الصنف غير الساكنة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_134" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">ExTwo</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">static</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> num_instances</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> my_num</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
</span><span class="typ">ExTwo</span><span class="pun">()</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> my_num</span><span class="pun">(</span><span class="pln">num_instances</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

</span><span class="kwd">static</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> get_total_instances</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> num_instances</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> get_instance_number</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> my_num</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> </span><span class="typ">ExTwo</span><span class="pun">::</span><span class="pln">num_instances</span><span class="pun">;</span></pre>

<p>
	لا يمكن أن تكون الأعضاء الساكنة قابلة للتغيير (<code>‎mutable‎</code>)، وليست في حاجة لهذا لأنها غير مرتبطة بأيّ نُسخة، أمّا مسـالة أنّ النُسخة ثابتة أم لا فليس لها أيّ تأثير على الأعضاء الساكنة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_136" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">ExDontNeedMutable</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> immuta</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">mutable</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> muta</span><span class="pun">;</span><span class="pln">

   </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">

    </span><span class="typ">ExDontNeedMutable</span><span class="pun">():</span><span class="pln"> immuta</span><span class="pun">(-</span><span class="lit">5</span><span class="pun">),</span><span class="pln"> muta</span><span class="pun">(-</span><span class="lit">5</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> </span><span class="typ">ExDontNeedMutable</span><span class="pun">::</span><span class="pln">i</span><span class="pun">;</span><span class="pln">

</span><span class="com">// ...</span><span class="pln">

</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">ExDontNeedMutable</span><span class="pln"> dnm</span><span class="pun">;</span><span class="pln">
dnm</span><span class="pun">.</span><span class="pln">immuta </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln">    </span><span class="com">// Error: Can't modify read-only object.</span><span class="pln">
dnm</span><span class="pun">.</span><span class="pln">muta </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln">    </span><span class="com">// يمكن إعادة كتابة الحقول القابلة للتغيير من كائن ثابت</span><span class="pln">
dnm</span><span class="pun">.</span><span class="pln">i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln">        </span><span class="com">// يمكن إعادة كتابة الأعضاء الساكنة بغض النظر عن ثباتيّة النسخة</span></pre>

<p>
	تحترم الأعضاء الساكنة مُحدِّدات الوصول، تمامًا مثل الأعضاء غير الساكنة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_138" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">ExAccess</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> prv_int</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">protected</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> pro_int</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> pub_int</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> </span><span class="typ">ExAccess</span><span class="pun">::</span><span class="pln">prv_int</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> </span><span class="typ">ExAccess</span><span class="pun">::</span><span class="pln">pro_int</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> </span><span class="typ">ExAccess</span><span class="pun">::</span><span class="pln">pub_int</span><span class="pun">;</span><span class="pln">

</span><span class="com">// ...</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> x1 </span><span class="pun">=</span><span class="pln"> </span><span class="typ">ExAccess</span><span class="pun">::</span><span class="pln">prv_int</span><span class="pun">;</span><span class="pln"> </span><span class="com">// خاص int ExAccess::prv_int خطأ، لأنّ</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> x2 </span><span class="pun">=</span><span class="pln"> </span><span class="typ">ExAccess</span><span class="pun">::</span><span class="pln">pro_int</span><span class="pun">;</span><span class="pln"> </span><span class="com">// محمي int ExAccess::pro_int خطأ، لأنّ</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> x3 </span><span class="pun">=</span><span class="pln"> </span><span class="typ">ExAccess</span><span class="pun">::</span><span class="pln">pub_int</span><span class="pun">;</span><span class="pln"> </span><span class="com">// جيّد</span></pre>

<p>
	بحُكم أنّها غير مرتبطة بنُسخة معيّنة، فلا تمتلك التوابع الساكنة المؤشّرُ <code>‎this‎</code>؛ وعليه لا تستطيع الوصول إلى الحقول غير الساكنة إلا في حال تمرير نُسخة إليها.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_140" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">ExInstanceRequired</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
</span><span class="typ">ExInstanceRequired</span><span class="pun">()</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> i</span><span class="pun">(</span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

</span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> bad_mutate</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">++</span><span class="pln">i </span><span class="pun">*=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">                    </span><span class="com">// خطأ</span><span class="pln">
</span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> good_mutate</span><span class="pun">(</span><span class="typ">ExInstanceRequired</span><span class="pun">&amp;</span><span class="pln"> e</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">++</span><span class="pln">e</span><span class="pun">.</span><span class="pln">i </span><span class="pun">*=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">    </span><span class="com">// جيد</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	ونظرًا لعدم امتلاكها للمؤشّر <code>‎this‎</code>، فلا يمكن تخزين عناوينها في مؤشّرات الدوال التابعة (pointers-to-member-functions)، وتُخزّن بدلاً من ذلك في مؤشّرات الدّوال (pointers-to-functions) العادية.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_142" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">ExPointer</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> nsfunc</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> sfunc</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">typedef</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="pun">(</span><span class="typ">ExPointer</span><span class="pun">::*</span><span class="pln"> mem_f_ptr</span><span class="pun">)();</span><span class="pln">
</span><span class="kwd">typedef</span><span class="pln"> </span><span class="kwd">void</span><span class="pun">(</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> f_ptr</span><span class="pun">)();</span><span class="pln">
mem_f_ptr p_sf </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="typ">ExPointer</span><span class="pun">::</span><span class="pln">sfunc</span><span class="pun">;</span><span class="pln"> </span><span class="com">// خطأ</span><span class="pln">
f_ptr p_sf </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="typ">ExPointer</span><span class="pun">::</span><span class="pln">sfunc</span><span class="pun">;</span><span class="pln"> </span><span class="com">// جيد</span></pre>

<p>
	نظرًا لعدم امتلاكها لمؤشّر <code>‎this‎</code>، فهي لا ثابتة (<code>‎const‎</code>) ولا متغيّرة (<code>‎volatile‎</code>)، ولا يمكن أن يكون لها مؤهّلات مرجعية (ref-qualiﬁers). كما لا يمكنها أن تكون وهميّة كذلك.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_144" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">ExCVQualifiersAndVirtual</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> func</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">            </span><span class="com">// جيد</span><span class="pln">
    </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> cfunc</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">        </span><span class="com">// خطأ</span><span class="pln">
    </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> vfunc</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">volatile</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">        </span><span class="com">// خطأ</span><span class="pln">
    </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> cvfunc</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">volatile</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">    </span><span class="com">// خطأ</span><span class="pln">
    </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> rfunc</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">            </span><span class="com">//خطأ </span><span class="pln">
    </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> rvfunc</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">            </span><span class="com">// خطأ</span><span class="pln">

    </span><span class="kwd">virtual</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> vsfunc</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">        </span><span class="com">// خطأ</span><span class="pln">
    </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">virtual</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> svfunc</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">        </span><span class="com">// خطأ</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	وبما أن المتغيرات العضوية الساكنة لا ترتبط بنُسخة معينة، فيُتعَامل معها كمتغيرات عامّة استثنائيّة (special global variables)؛ فتُنشأ عند بدء تشغيل البرنامج ولا تُحذف حتى إنهائه، بغض النظر عمّا إذا كانت هناك أيّ نُسخ موجودة بالفعل من الصنف. ولا توجد إلا نسخة (copy) واحدة فقط من كل حقل ساكن (ما لم يُصرَّح بالمتغير كـ <code>‎thread_local‎</code> - الإصدار C++‎ 11 أو أحدث - وفي هذه الحالة تكون هناك نُسخة واحدة لكل خيط thread).
</p>

<p>
	والمتغيرات العضوية الساكنة لها نفس ارتباط (linkage) الصِّنف، سواء كان للصنف ارتباط خارجي أو داخلي، ولا يُسمح للأصناف المحلية (Local classes) والأصناف غير المُسمّاة (unnamed classes) أن يكون لها أعضاء ساكنة.
</p>

<h2>
	الوراثة المتعددة (Multiple Inheritance)
</h2>

<p>
	إلى جانب الوراثة الفردية (single inheritance):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_146" style="">
<span class="kwd">class</span><span class="pln"> A </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> B </span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> A </span><span class="pun">{};</span></pre>

<p>
	فهناك مفهوم الوراثة المتعددة في C++‎:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_148" style="">
<span class="kwd">class</span><span class="pln"> A </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> B </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> C </span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> A</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> B </span><span class="pun">{};</span></pre>

<p>
	سوف يرث <code>‎C‎</code> الآن من <code>‎A‎</code> و <code>‎B‎</code> في الوقت ذاته.
</p>

<p>
	ملاحظة: كن حذرًا إذ قد يؤدّي هذا إلى بعض الغموض في حال استخدام نفس الأسماء في عدّة أصناف أو بنيات موروثة.
</p>

<h3>
	الغموض في الوراثة المتعددة
</h3>

<p>
	قد تكون الوراثة المتعدّدة مفيدة في بعض الحالات ولكنها قد تخلق بعض المشاكل، فعلى سبيل المثال: لنفترض أنّ صنفين أساسيَن يحتويان على دوال بنفس الاسم، وأنّ الصنف المشتق منهما لم يُعِدْ تعريف تلك الدالة، فإن حاولت الوصول إلى تلك الدالة عبر كائن من الصنف المُشتق، فسيعرِض المُصرّف خطأً لأنه لا يستطيع تحديد الدالة التي يجب استدعاؤها. إليك مثالًا على ذلك:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_150" style="">
<span class="kwd">class</span><span class="pln"> base1 </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">void</span><span class="pln"> funtion</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">//شيفرة الدالّة }</span><span class="pln">
        </span><span class="pun">};</span><span class="pln">
    </span><span class="kwd">class</span><span class="pln"> base2 </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">void</span><span class="pln">
        function </span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">// شيفرة الدالّة }</span><span class="pln">
        </span><span class="pun">};</span><span class="pln">
        </span><span class="kwd">class</span><span class="pln"> derived</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> base1</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> base2 </span><span class="pun">{</span><span class="pln">

        </span><span class="pun">};</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            derived obj</span><span class="pun">;</span><span class="pln">

            </span><span class="com">// خطأ، لأنّ المصرف لا يستطيع أن يحدد التابع الذي يجب استدعاؤه</span><span class="pln">
            obj</span><span class="pun">.</span><span class="pln">function</span><span class="pun">()</span><span class="pln">
        </span><span class="pun">}</span></pre>

<p>
	ولكن يمكن حلّ هذه المشكلة باستخدام دالّة حلّ النطاق (scope resolution function) لتحديد الصنف الذي سيُستدعى تابعه:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_152" style="">
<span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    obj</span><span class="pun">.</span><span class="pln">base1</span><span class="pun">::</span><span class="pln"> function </span><span class="pun">();</span><span class="pln"> </span><span class="com">// base1 تُستدعى دالة الصنف</span><span class="pln">
    obj</span><span class="pun">.</span><span class="pln">base2</span><span class="pun">::</span><span class="pln"> function </span><span class="pun">();</span><span class="pln"> </span><span class="com">// base2 تُستدعى دالة الصنف</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	الدوال التابعة غير الساكنة (Non-static member functions)
</h2>

<p>
	يمكن أن يكون للصنف دوال تابعة غير ساكنة تعمل على نُسخ الصنف المستقلة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_154" style="">
<span class="kwd">class</span><span class="pln"> CL </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">void</span><span class="pln"> member_function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	تُستدعى هذه التوابع على نُسَخ الصنف، على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_156" style="">
<span class="pln">CL instance</span><span class="pun">;</span><span class="pln">
instance</span><span class="pun">.</span><span class="pln">member_function</span><span class="pun">();</span></pre>

<p>
	ويمكن تعريفها إمّا داخل أو خارج تعريف الصنف، فإذا عُرِّفت في الخارج ستُعدُّ داخل نطاق الصنف.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_158" style="">
<span class="kwd">struct</span><span class="pln"> ST </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> defined_inside</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> defined_outside</span><span class="pun">();</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> ST</span><span class="pun">::</span><span class="pln">defined_outside</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span></pre>

<p>
	ويمكن أن تُؤهّل (CV-qualiﬁed) أو تُؤهّل مرجعيًا (ref-qualiﬁed)، وينعكس ذلك على كيفية رؤيتها للنُّسخة التي استُدعيت عليها، ويعتمد الإصدار الذي سيُستدعى على المؤهّلات الثباتية للنُّسخة، فإذا لم يكن هناك إصدار له نفس المؤهِّلات الثباتيّة للنُّسخة، فسيُستدعى إصدار أكثر تأهيلًا ثباتيًا (more-cv-qualiﬁed) إذا كان متاحًا.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_160" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">CVQualifiers</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> func</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">                    </span><span class="com">// 1: غير مؤهلة ثباتيا</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> func</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">                </span><span class="com">// 2:غير ثابتة </span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> cv_only</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">volatile</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">CVQualifiers</span><span class="pln">       non_cv_instance</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">CVQualifiers</span><span class="pln">      c_instance</span><span class="pun">;</span><span class="pln">
non_cv_instance</span><span class="pun">.</span><span class="pln">func</span><span class="pun">();</span><span class="pln">            </span><span class="com">// #1 استدعاء</span><span class="pln">
c_instance</span><span class="pun">.</span><span class="pln">func</span><span class="pun">();</span><span class="pln">                </span><span class="com">// #2 استدعاء</span><span class="pln">
non_cv_instance</span><span class="pun">.</span><span class="pln">cv_only</span><span class="pun">();</span><span class="pln">        </span><span class="com">// const volatile استدعاء الإصدار </span><span class="pln">
c_instance</span><span class="pun">.</span><span class="pln">cv_only</span><span class="pun">();</span><span class="pln">            </span><span class="com">// const volatile استدعاء الإصدار</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 11 </strong>
</p>

<p>
	تحدّد الدوال التابعة المؤهّلة مرجِعيًّا (Member function ref-qualiﬁers) ما إذا كان يجوز أن يُستدعَى التابع على نُسخ يمينِيَّة (rvalue) أم لا، وتستخدم نفسَ صياغةِ التوابع المؤهّلة ثباتيًّا.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_162" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">RefQualifiers</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> func</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">            </span><span class="com">// 1: تُستدعى على  النسخ العادية</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> func</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">            </span><span class="com">// 2: تُستدعي على النسخ اليمينية</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">RefQualifiers</span><span class="pln"> rf</span><span class="pun">;</span><span class="pln">
rf</span><span class="pun">.</span><span class="pln">func</span><span class="pun">();</span><span class="pln">                </span><span class="com">// #1 استدعاء</span><span class="pln">
</span><span class="typ">RefQualifiers</span><span class="pln"> </span><span class="pun">{}.</span><span class="pln">func</span><span class="pun">();</span><span class="pln">        </span><span class="com">// #2 استدعاء</span></pre>

<p>
	يجوز دمج المؤهّلات الثباتية والمؤهّلات المرجعية إذا لزم الأمر.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_164" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">BothCVAndRef</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> func</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">        </span><span class="com">// تُستدعى على  النسخ العادية</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> func</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">            </span><span class="com">// تُستدعى على  النسخ المؤقتة</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	يمكن أيضًا أن تكون وهميّة، وهذا ضروري في التعددية الشكلية، ويسمح للأصناف المشتقة بأن يكون لها نفس واجهة الصنف الأب مع إضافة وظائفها الخاصّة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7775_166" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">virtual</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> func</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Derived</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">virtual</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> func</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">Base</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> bp </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Base</span><span class="pun">;</span><span class="pln">
</span><span class="typ">Base</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> dp </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Derived</span><span class="pun">;</span><span class="pln">
bp</span><span class="pun">.</span><span class="pln">func</span><span class="pun">();</span><span class="pln"> </span><span class="com">// Base::func() استدعاء  </span><span class="pln">
dp</span><span class="pun">.</span><span class="pln">func</span><span class="pun">();</span><span class="pln"> </span><span class="com">// Derived::func() استدعاء</span></pre>

<p>
	هذا الدرس جزء من <a data-ss1617022514="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة دروس عن C++‎</a>.
</p>

<p>
	ترجمة -وبتصرّف- للفصل Chapter 34: Classes/Structures من الكتاب <a data-ss1617022514="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">933</guid><pubDate>Fri, 10 Jul 2020 18:06:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x645;&#x624;&#x634;&#x631;&#x627;&#x62A; &#x627;&#x644;&#x630;&#x643;&#x64A;&#x629; (Smart Pointers) &#x641;&#x64A; Cpp</title><link>https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D9%85%D8%A4%D8%B4%D8%B1%D8%A7%D8%AA-%D8%A7%D9%84%D8%B0%D9%83%D9%8A%D8%A9-smart-pointers-%D9%81%D9%8A-cpp-r913/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_06/20.jpg.a2bcaffc7b30492d319801452365028e.jpg" /></p>

<h2>
	الملكية الفريدة
</h2>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	<code>‎std::unique_ptr‎</code> هو قالب صنف (class template) يُدير دورة حياة الكائنات المخزّنة ديناميكيًا، وعلى خلاف <code>std::shared_ptr</code>، فإنّ كل كائن ديناميكي يكون مملوكًا لمؤشّر حصري (<code>std::unique_ptr</code>) واحد في أيّ لحظة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6295_7" style="">
<span class="com">// أنشئ عددًا صحيحًا ديناميكيًا تساوي قيمته 20 ويكون مملوكًا من مؤشّر وحيد</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">unique_ptr</span><span class="str">&lt;int&gt;</span><span class="pln"> ptr </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">make_unique</span><span class="str">&lt;int&gt;</span><span class="pun">(</span><span class="lit">20</span><span class="pun">);</span></pre>

<p>
	ملاحظة: <code>‎std::unique_ptr‎</code> متاحٌ منذ الإصدار C++‎ 11، أما <code>‎std::make_unique‎</code> فمنذ الإصدار C++‎ 14.
</p>

<p>
	المتغيّر <code>‎ptr‎</code> يحتوي على مؤشّر إلى عدد صحيح (<code>‎int‎</code>) مخزّن ديناميكيًّا، ويُحذف الكائن المملوك عندما يخرج مؤشّر حصريّ (unique pointer) يمتلك كائنًا عن النطاق (scope)، أي أنّ المُدمِّر (destructor) الخاصّ به سيُستدعى إذا كان الكائن من نوع صنف (class type)، كما ستُحرّر ذاكرة ذلك الكائن.
</p>

<p>
	ولاستخدام <code>‎std::unique_ptr‎</code> و <code>‎std::make_unique‎</code> مع <a data-ss1617022513="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-7-%D8%A7%D9%84%D9%85%D8%B5%D9%81%D9%88%D9%81%D8%A7%D8%AA-%D9%81%D9%8A-cpp-r891/" rel="">المصفوفات</a>، استخدم الصياغة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6295_9" style="">
<span class="com">//  إنشاء مؤشّر حصري يشير إلى عدد صحيح يساوي 59 </span><span class="pln">
std</span><span class="pun">::</span><span class="pln">unique_ptr</span><span class="str">&lt;int&gt;</span><span class="pln"> ptr </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">make_unique</span><span class="str">&lt;int&gt;</span><span class="pun">(</span><span class="lit">59</span><span class="pun">);</span><span class="pln">
</span><span class="com">//  إنشاء مؤشّر حصري يشير إلى مصفوفة من 15 عددًا صحيحا </span><span class="pln">
std</span><span class="pun">::</span><span class="pln">unique_ptr</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">[]&gt;</span><span class="pln"> ptr </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">make_unique</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">[]&gt;(</span><span class="lit">15</span><span class="pun">);</span></pre>

<p>
	يمكنك الوصول إلى مؤشّر حصريّ (<code>‎std::unique_ptr‎</code>) كما تصل إلى أيّ مؤشّر خام، لأنه يزيد تحميل (overloads) تلك العوامل، كما يمكنك نقل ملكية محتويات مؤشّر ذكي إلى مؤشّر آخر باستخدام <code>‎std::move‎</code> التي ستجعل المؤشّر الذكي الأصلي يشير إلى <code>‎nullptr‎</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6295_13" style="">
<span class="com">// 1. std::unique_ptr</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">unique_ptr </span><span class="str">&lt;int&gt;</span><span class="pln"> ptr </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">make_unique </span><span class="str">&lt;int&gt;</span><span class="pln"> </span><span class="pun">();</span><span class="pln">
</span><span class="com">// 1 تغيير القيمة إلى</span><span class="pln">
</span><span class="pun">*</span><span class="pln">ptr </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
</span><span class="com">// 2. std::unique_ptr </span><span class="pln">
</span><span class="com">// سيفقد ملكية الكائن 'ptr'  فإن 'ptr2' إلى  'ptr'  بنقل </span><span class="pln">
std</span><span class="pun">::</span><span class="pln">unique_ptr </span><span class="str">&lt;int&gt;</span><span class="pln"> ptr2 </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">move</span><span class="pun">(</span><span class="pln">ptr</span><span class="pun">);</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="pun">*</span><span class="pln">ptr2</span><span class="pun">;</span><span class="pln"> </span><span class="com">// 'a' is 1</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> </span><span class="pun">*</span><span class="pln">ptr</span><span class="pun">;</span><span class="pln">  </span><span class="com">// 'nullptr' يساوي ptr</span><span class="pln">
                    </span><span class="com">// بسبب أمر النقل أعلاه</span></pre>

<p>
	تمرير <code>‎unique_ptr‎</code> إلى دالّة كمعامل:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6295_15" style="">
<span class="kwd">void</span><span class="pln"> foo</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">unique_ptr </span><span class="str">&lt;int&gt;</span><span class="pln"> ptr</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// ضع شيفرتك هنا</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">unique_ptr </span><span class="str">&lt;int&gt;</span><span class="pln"> ptr </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">make_unique </span><span class="str">&lt;int&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="lit">59</span><span class="pun">);</span><span class="pln">
foo</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">move</span><span class="pun">(</span><span class="pln">ptr</span><span class="pun">))</span></pre>

<p>
	إعادة مؤشّر <code>‎unique_ptr‎</code> من دالّة هي الطريقة المفضلة في C++‎ 11 لكتابة الدوال المُنتجة (factory functions)، إذ أنّها تعبّر بوضوح عن ملكية القيمَة المعادة، فالمُستدعي يمتلك المؤشّر <code>‎unique_ptr‎</code> الناتج وهو المسؤول عنه.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6295_17" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">unique_ptr </span><span class="str">&lt;int&gt;</span><span class="pln"> foo</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">unique_ptr </span><span class="str">&lt;int&gt;</span><span class="pln"> ptr </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">make_unique </span><span class="str">&lt;int&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="lit">59</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> ptr</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">unique_ptr </span><span class="str">&lt;int&gt;</span><span class="pln"> ptr </span><span class="pun">=</span><span class="pln"> foo</span><span class="pun">();</span></pre>

<p>
	قارن هذا بالشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6295_19" style="">
<span class="typ">int</span><span class="pun">*</span><span class="pln"> foo_cpp03</span><span class="pun">();</span><span class="pln">
</span><span class="typ">int</span><span class="pun">*</span><span class="pln"> p </span><span class="pun">=</span><span class="pln"> foo_cpp03</span><span class="pun">();</span><span class="pln"> </span><span class="com">// أم يجب علي حذفه في مرحلة ما p هل أملك </span><span class="pln">
                                 </span><span class="com">// جواب هذا السؤال غير واضح</span></pre>

<p>
	<strong>الإصدار &lt;C++‎ 14</strong>
</p>

<p>
	قُدِّم قالب الصنف <code>‎make_unique‎</code> منذ الإصدار C++‎ 14. لكن من السهل إضافته يدويًا إلى C++‎ 11:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6295_21" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pun">...</span><span class="typ">Args</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">typename</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">enable_if </span><span class="pun">&lt;</span><span class="pln"> </span><span class="pun">!</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_array </span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="pln">value</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">unique_ptr </span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="pln">type
make_unique</span><span class="pun">(</span><span class="typ">Args</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="pun">...</span><span class="pln">args</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">unique_ptr </span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> T</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">forward </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Args</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">args</span><span class="pun">)...));</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="com">// لأجل المصفوفات make_unique استخدام</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">typename</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">enable_if </span><span class="pun">&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">is_array </span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="pln">value</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">unique_ptr </span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="pln">type
make_unique</span><span class="pun">(</span><span class="typ">size_t</span><span class="pln"> n</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">unique_ptr </span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">remove_extent </span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="pln">type</span><span class="pun">[</span><span class="pln">n</span><span class="pun">]());</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 11 </strong>
</p>

<p>
	على عكس المؤشّر "الذكي" <code>‎std::auto_ptr‎</code> الغبي، فإن المؤشّر <code>‎unique_ptr‎</code> يستطيع أن يُستنسخ (instantiated) عبر تخصيص المتجه -وليس <code>std::vector</code>- إذ كانت الأمثلة السابقة للتخصيصات العددية، أما إن أردنا الحصول على مصفوفة من الأعداد الصحيحة المخزّنة ديناميكيًا، فإنك تحدد <code>‎int[]‎</code> كنوع للقالب -وليس فقط <code>‎int‎</code>-، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6295_23" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">unique_ptr</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">[]&gt;</span><span class="pln"> arr_ptr </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">make_unique</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">[]&gt;(</span><span class="lit">10</span><span class="pun">);</span></pre>

<p>
	يمكن تبسيط الشّيفرة باستخدام:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6295_26" style="">
<span class="kwd">auto</span><span class="pln"> arr_ptr </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">make_unique</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">[]&gt;(</span><span class="lit">10</span><span class="pun">);</span></pre>

<p>
	الآن، يمكنك استخدام <code>‎arr_ptr‎</code> كما لو كان مصفوفة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6295_28" style="">
<span class="pln">arr_ptr</span><span class="pun">[</span><span class="lit">2</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln"> </span></pre>

<p>
	ولا داعي للقلق بشأن إلغاء تخصيص الذاكرة (de-allocation)، فهذا الإصدار المُتخصّص في القوالب يستدعي المُنشِئاتِ (constructors) والمدمِّرات (destructors) بالشكل المناسب، وعليه فإن استخدام الإصدار المتجهي من <code>‎unique_ptr‎</code> أو المتجه <code>‎vector‎</code> نفسه تعود للتفضيل الشخصي.
</p>

<p>
	كان <code>‎std::auto_ptr‎</code> متاحًا في الإصدارات السابقة لـ C++‎ 11. وعلى عكس <code>‎unique_ptr‎</code> فإن مؤشّرات <code>‎auto_ptr‎</code> مسموح بنسخها، وسيؤدّي هذا إلى أن يفقِد المصدر <code>‎ptr‎</code> ملكية المؤشِّر لتتحوّل الملكيّة إلى الهدف.
</p>

<h2>
	الملكية المشتركة <code>std::shared_ptr</code>
</h2>

<p>
	يُعرِّف قالب الصنف <code>‎std::shared_ptr‎</code> مؤشّرًا مُشتركًا قادرًا على مشاركة ملكيّة كائن ما مع مؤشّرات مشتركة أخرى، وهذا يتعارض مع طبيعة المؤشّرات الحصرية (<code>‎std::unique_ptr‎</code>) التي تمثّل ملكية حصرية.
</p>

<p>
	ويُنفَّذ سلوك المشاركة عبر تقنية تُعرف بعدِّ المراجع (reference counting)، حيث يُخزّن عدد المؤشّرات المشتركة التي تشير إلى الكائن مع هذا الكائن نفسه، ويُدمَّر هذا الكائن تلقائيًا عندما يصل هذا العدد إلى الصفر إما بسبب تدمير النسخة الأخيرة من <code>std::shared_ptr</code> أو إعادة تعيينها. انظر المثال التالي حيث يكون <code>firstShared</code> مؤشرًا مشتركًا لنسخة جديدة من <code>Foo</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6295_30" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">shared_ptr</span><span class="pun">&lt;</span><span class="typ">Foo</span><span class="pun">&gt;</span><span class="pln"> firstShared </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">make_shared</span><span class="pun">&lt;</span><span class="typ">Foo</span><span class="pun">&gt;(</span><span class="com">/*args*/</span><span class="pun">);</span></pre>

<p>
	لإنشاء عدّة مؤشّرات ذكية تشترك في نفس الكائن، نحتاج إلى إنشاء مؤشّر مشترك آخر يأخذ اسم المؤشّر الأول المشترك، ولدينا الآن طريقتان لفعل ذلك:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6295_32" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">shared_ptr</span><span class="pun">&lt;</span><span class="typ">Foo</span><span class="pun">&gt;</span><span class="pln"> secondShared</span><span class="pun">(</span><span class="pln">firstShared</span><span class="pun">);</span><span class="pln">    </span><span class="com">// الطريقة 1: الإنشاء بالنسخ</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">shared_ptr</span><span class="pun">&lt;</span><span class="typ">Foo</span><span class="pun">&gt;</span><span class="pln"> secondShared</span><span class="pun">;</span><span class="pln">
secondShared </span><span class="pun">=</span><span class="pln"> firstShared</span><span class="pun">;</span><span class="pln">                </span><span class="com">// الطريقة 2: الإسناد</span></pre>

<p>
	كلا الطّريقتان المَذكورتان أعلاه تجعلان <code>‎secondShared‎</code> مؤشّرًا مشتركًا يتشارك ملكية نُسخة <code>‎Foo‎</code> مع <code>‎firstShared‎</code>.
</p>

<p>
	تعمل المؤشّرات الذكية مثل المؤشّرات الخام، هذا يعني أنه يمكنك استخدام <code>‎*‎</code> لتحصيلها، كما أنّ العامل العادي <code>‎-&gt;‎</code> يعمل أيضًا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6295_34" style="">
<span class="pln">secondShared</span><span class="pun">-&gt;</span><span class="pln">test</span><span class="pun">();</span><span class="pln"> </span><span class="com">// Foo::test() يستدعي</span></pre>

<p>
	أخيرًا، عندما يخرج آخر مؤشّر مشترك مُكنّى (aliased)‏‏ عن النطاق، فسيُستدعى المدمّر الخاصّ بنسخة <code>‎Foo‎</code>.
</p>

<p>
	تنبيه: قد يؤدي إنشاء مؤشّر مشترك إلى إطلاق اعتراض <code>‎bad_alloc‎</code> عند الحاجة إلى تخصيص بيانات إضافية في الملكيّة المشتركة، وفي حال تمرير مؤشّر عادي إلى المُنشئ فإنه سيَفترض أنه يمتلك الكائن الذي يشير إليه ذلك المؤشّر وسَيستدعي دالّة الحذف (deleter) في حالة إطلاق اعتراض. هذا يعني أنّ <code>shared_ptr&lt;T&gt;(new T(args))‎</code> لن تُسرِّب كائن <code>‎T‎</code> في حال فشل تخصيص ذاكرة <code>‎shared_ptr&lt;T&gt;‎</code>. أيضًا يُنصح باستخدام <code>‎make_shared&lt;T&gt;(args)‎</code> أو <code>‎allocate_shared&lt;T&gt;(alloc, args)‎</code> إذ يحسّن كفاءة تخصيص الذاكرة.
</p>

<h3>
	تخصيص ذاكرة المصفوفات باستخدام المؤشرات المشتركة
</h3>

<p>
	C++‎ 11 =&lt; الإصدار &lt; C++‎ 17
</p>

<p>
	لا توجد طريقة مباشرة لتخصيص ذاكرة <a data-ss1617022513="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-7-%D8%A7%D9%84%D9%85%D8%B5%D9%81%D9%88%D9%81%D8%A7%D8%AA-%D9%81%D9%8A-cpp-r891/" rel="">المصفوفات</a> باستخدام <code>‎make_shared&lt;&gt;‎</code>، لكن من الممكن إنشاء مصفوفات <code>‎shared_ptr&lt;&gt;‎</code> باستخدام <code>‎new‎</code> و <code>‎std::default_delete‎</code>. على سبيل المثال، لتخصِيص ذاكرة مصفوفة عُشارية مكوّنة من أعداد صحيحة، يمكننا كتابة الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6295_36" style="">
<span class="pln">shared_ptr</span><span class="str">&lt;int&gt;</span><span class="pln"> sh</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">int</span><span class="pun">[</span><span class="lit">10</span><span class="pun">],</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">default_delete</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">[]&gt;());</span></pre>

<p>
	يجب تحديد <code>‎std::default_delete‎</code> هنا للتأكّد من تنظيف الذاكرة المُخصّصة بشكل صحيح باستخدام <code>‎delete[]‎</code>. وإذا عرفنا حجم المصفوفة في وقت التصريف، يمكننا القيام بذلك بالطريقة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6295_38" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Arr</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> shared_array_maker </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> N </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> shared_array_maker </span><span class="pun">&lt;</span><span class="pln"> T</span><span class="pun">[</span><span class="pln">N</span><span class="pun">]</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">shared_ptr </span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">auto</span><span class="pln"> r </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">make_shared </span><span class="pun">&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">array </span><span class="pun">&lt;</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> N </span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="pun">();</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">r</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">{</span><span class="pln">r</span><span class="pun">.</span><span class="pln">data</span><span class="pun">(),</span><span class="pln"> r</span><span class="pun">};</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Arr</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> make_shared_array</span><span class="pun">()</span><span class="pln"> </span><span class="pun">-&gt;</span><span class="pln"> </span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">shared_array_maker </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Arr</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">{}())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> shared_array_maker </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Arr</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">{}();</span><span class="pln">
    </span><span class="pun">}</span></pre>

<p>
	سيعيد <code>‎make_shared_array&lt;int[10]&gt;‎</code> عندئذٍ المؤشّرَ المشترك <code>‎shared_ptr&lt;int&gt;‎</code> مشيرًا إلى عناصر المصفوفة الذين أنشئوا افتراضيًا.
</p>

<p>
	<strong>الإصدار ≥ C++‎ 17</strong>
</p>

<p>
	تحسَّن دعم المؤشّرات المشتركة للمصفوفات في الإصدار C++‎ 17، فلم يعد ضروريًا تحديد دالّة حذف (array-deleter) للمصفوفة بشكل صريح، وصار من الممكن تحصيل المؤشّر المشترك باستخدام عامل فهرسة المصفوفات <code>‎[]‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6295_40" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">shared_ptr</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">[]&gt;</span><span class="pln"> sh</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">int</span><span class="pun">[</span><span class="lit">10</span><span class="pun">]);</span><span class="pln">
sh</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span></pre>

<p>
	تستطيع المؤشرات المشتركة أن تشير إلى كائن فرعي من الكائن الذي تمتلكه، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6295_42" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> x</span><span class="pun">;</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">shared_ptr</span><span class="pun">&lt;</span><span class="typ">Foo</span><span class="pun">&gt;</span><span class="pln"> p1 </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">make_shared</span><span class="pun">&lt;</span><span class="typ">Foo</span><span class="pun">&gt;();</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">shared_ptr</span><span class="str">&lt;int&gt;</span><span class="pln"> p2</span><span class="pun">(</span><span class="pln">p1</span><span class="pun">,</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">p1</span><span class="pun">-&gt;</span><span class="pln">x</span><span class="pun">);</span></pre>

<p>
	يمتلك كل من <code>‎p2‎</code> و <code>‎p1‎</code> الكائن المنتمي إلى النوع <code>‎Foo‎</code> إلا أنّ <code>‎p2‎</code> يشير إلى العضو العددي الصحيح <code>‎x‎</code>، وهذا يعني أنّه في حال خرج <code>‎p1‎</code> عن النطاق أو أُعِيد تعيينه فسيظلّ الكائن <code>‎Foo‎</code> حيًّا، ممّا يضمن أنّ <code>‎p2‎</code> لن يتراجع (‏‏‎(dangle.
</p>

<p>
	ملاحظة مهمة: لا تعرِف المؤشّرات المشتركة إلا نفسَها وبقيّة المؤشّرات المشتركة الأخرى التي أنشئت باستخدام المُنشئ المكنّى (alias constructor). ولا تعرف أيّ مؤشّرات أخرى حتى المؤشّرات المشتركة التي أنشئت بالإشارة إلى نفس نُسخة <code>‎Foo‎</code>. انظر <code>()shared1.reset</code> في المثال التالي إذ سيحذف <code>foo</code> لأن <code>shared1</code> هو المؤشر المشترك الوحيد الذي يمتلكه:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6295_44" style="">
<span class="typ">Foo</span><span class="pln"> </span><span class="pun">*</span><span class="pln">foo </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Foo</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">shared_ptr </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">     </span><span class="pun">(</span><span class="pln">foo</span><span class="pun">);</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">shared_ptr </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> shared2</span><span class="pun">(</span><span class="pln">foo</span><span class="pun">);</span><span class="pln"> </span><span class="com">// لا تفعل هذا</span><span class="pln">
shared1</span><span class="pun">.</span><span class="pln">reset</span><span class="pun">();</span><span class="pln">
shared2 </span><span class="pun">-&gt;</span><span class="pln"> test</span><span class="pun">();</span><span class="pln"> </span><span class="com">// قد حُذفت shared2 الخاصة بـ foo سلوك غير محدد إذ أن.</span></pre>

<h3>
	نقل ملكية المؤشرات المشتركة
</h3>

<p>
	افتراضيًّا، تزيد المؤشّرات المشتركة <code>‎shared_ptr‎</code> عدد المراجع (reference count) لكنها لا تنقل الملكية، غير أننا نستطيع جعلها تنقل الملكية باستخدام <code>‎std::move‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6295_46" style="">
<span class="pln">shared_ptr</span><span class="str">&lt;int&gt;</span><span class="pln"> up </span><span class="pun">=</span><span class="pln"> make_shared</span><span class="str">&lt;int&gt;</span><span class="pun">();</span><span class="pln">
</span><span class="com">// نقل الملكية</span><span class="pln">
shared_ptr</span><span class="str">&lt;int&gt;</span><span class="pln"> up2 </span><span class="pun">=</span><span class="pln"> move</span><span class="pun">(</span><span class="pln">up</span><span class="pun">);</span><span class="pln">
</span><span class="com">// 1 ذي العدّاد up2 يساوي 0، وملكية المؤشّر محصورة في  up الآن، عدّاد المراجع الخاص بـ</span></pre>

<h2>
	المشاركة بملكية مؤقتة
</h2>

<p>
	يمكن أن تشير نُسخ المؤشّرات الضعيفة <code>‎std::weak_ptr‎</code> إلى الكائنات المملوكة لنُسخ المؤشّرات المشتركة <code>‎std::shared_ptr‎</code> وتصبح مالِكة مؤقتة، هذا يعني أنّ المؤشّرات الضعيفة لا تغير عدد مراجع الكائن، وعليه لا تمنع حذف الكائن إذا أُعيد إسناد كافّة مؤشّرات الكائن المشتركة أو حذفها. انظر المثال التالي إذ سنستخدم المؤشّرات الضعيفة للسماح بحذف كائن:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6295_48" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;memory&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;vector&gt;</span><span class="pln">

</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">TreeNode</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">weak_ptr </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">TreeNode</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> parent</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">shared_ptr </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">TreeNode</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> children</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// TreeNode إنشاء</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">shared_ptr </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">TreeNode</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> root</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">TreeNode</span><span class="pun">);</span><span class="pln">
    </span><span class="com">// إعطاء الأب 100 عقدة فرعية</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">size_t</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">100</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">shared_ptr </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">TreeNode</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> child</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">TreeNode</span><span class="pun">);</span><span class="pln">
        root </span><span class="pun">-&gt;</span><span class="pln"> children</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="pln">child</span><span class="pun">);</span><span class="pln">
        child </span><span class="pun">-&gt;</span><span class="pln"> parent </span><span class="pun">=</span><span class="pln"> root</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="com">// ومعه العُقَد الفرعية root  إعادة تعيين المؤشّر المشترك، وتدمير الكائن</span><span class="pln">
    root</span><span class="pun">.</span><span class="pln">reset</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تُسنّد العقدة الجذر إلى <code>‎parent‎</code> بينما تُضاف عقد فرعية (child nodes) إلى فروع العقدة الجذر، كما يصرَّح العضو <code>‎parent‎</code> كمؤشّر ضعيف بدلاً من مؤشّر مشترك حتى لا يُزاد في عدد مراجع العقدة الجذر، وسيُحذَف الجذر عند إعادة تعيين العقدة الجذر في نهاية <code>‎main()‎</code>. أيضًا، نظرًا لأنّ مراجع المؤشّر المشترك المتبقيّة التي تشير إلى العقد الفرعية قد ضُمِّنت في مجموعة الجذر <code>‎children‎</code>، لذا ستُدمَّر جميع العقد الفرعية لاحقًا.
</p>

<p>
	قد لا تُحرّر الذاكرة المخصّصة التي تخصّ المؤشّر المشترك حتى يصل العدّادان المراجعيّان <code>‎shared_ptr‎</code> و <code>‎weak_ptr‎</code> إلى الصفر.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6295_50" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;memory&gt;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">weak_ptr </span><span class="str">&lt;int&gt;</span><span class="pln"> wk</span><span class="pun">;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="com">// عبر تخصيص الذاكرة مرة واحدة std::make_shared تُحسَّن</span><span class="pln">
            </span><span class="com">// تخصّص الذاكرة مرتين std::shared_ptr&lt;int&gt;(new int(42)) </span><span class="pln">
            std</span><span class="pun">::</span><span class="pln">shared_ptr </span><span class="str">&lt;int&gt;</span><span class="pln"> sh </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">make_shared </span><span class="str">&lt;int&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="lit">42</span><span class="pun">);</span><span class="pln">
            wk </span><span class="pun">=</span><span class="pln"> sh</span><span class="pun">;</span><span class="pln">
            </span><span class="com">// ينبغي أن تكون قد حُرِّرت الآن sh ذاكرة</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="com">// ما تزال حية wk ّلكن</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="com">// (sh و wk) حُرِّرت الذاكرة الآن</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	نظرًا لأنّ المؤشّرات الضعيفة (<code>‎std::weak_ptr‎</code>) لا تُبقي الكائن الذي تشير إليه على قيد الحياة، فلا يمكن الوصول المباشر للبيانات عبر المؤشّرات الضعيفة، بيْد أنّها توفّر تابعًا <code>‎lock()‎</code>، والذي يُرجعَ مؤشّرًا مشتركًا <code>‎std::shared_ptr‎</code> إلى الكائن المشار إليه:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6295_52" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;cassert&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;memory&gt;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">weak_ptr </span><span class="str">&lt;int&gt;</span><span class="pln"> wk</span><span class="pun">;</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">shared_ptr </span><span class="str">&lt;int&gt;</span><span class="pln"> sp</span><span class="pun">;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            std</span><span class="pun">::</span><span class="pln">shared_ptr </span><span class="str">&lt;int&gt;</span><span class="pln"> sh </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">make_shared </span><span class="str">&lt;int&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="lit">42</span><span class="pun">);</span><span class="pln">
            wk </span><span class="pun">=</span><span class="pln"> sh</span><span class="pun">;</span><span class="pln">
            </span><span class="com">// wk سيؤدي إلى  إنشاء مؤشّر مشترك يشير إلى الكائن الذي يشير إليه lock استدعاء</span><span class="pln">
            sp </span><span class="pun">=</span><span class="pln"> wk</span><span class="pun">.</span><span class="pln">lock</span><span class="pun">();</span><span class="pln">
            </span><span class="com">// sp عند هذه اللحظة، على خلاف sh ستُحذف </span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        </span><span class="com">// تُبقي البيانات حية sp </span><span class="pln">
        </span><span class="com">// إن أردنا lock() ما يزال بإمكاننا استدعاء</span><span class="pln">
        </span><span class="com">// wk من أجل لحصول على مؤشّر مشترك يشير إلى نفس البيانات من</span><span class="pln">
        assert</span><span class="pun">(</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> sp </span><span class="pun">==</span><span class="pln"> </span><span class="lit">42</span><span class="pun">);</span><span class="pln">
        assert</span><span class="pun">(!</span><span class="pln">wk</span><span class="pun">.</span><span class="pln">expired</span><span class="pun">());</span><span class="pln">

        </span><span class="com">// سيمحو البيانات sp إعادة إسناد</span><span class="pln">
        </span><span class="com">// لأنه آخر مؤشّر مشترك له ملكية</span><span class="pln">
        sp</span><span class="pun">.</span><span class="pln">reset</span><span class="pun">();</span><span class="pln">

        </span><span class="com">// سيعيد مؤشّرا مشتركا فارغا wk على lock محاولة استدعاء</span><span class="pln">
        </span><span class="com">// لأن البيانات قد حُذِفت سلفا</span><span class="pln">
        sp </span><span class="pun">=</span><span class="pln"> wk</span><span class="pun">.</span><span class="pln">lock</span><span class="pun">();</span><span class="pln">
        assert</span><span class="pun">(!</span><span class="pln">sp</span><span class="pun">);</span><span class="pln">
        assert</span><span class="pun">(</span><span class="pln">wk</span><span class="pun">.</span><span class="pln">expired</span><span class="pun">());</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	استخدام دوال حذف مخصصة لتغليف واجهة C
</h2>

<p>
	تتوفّر العديد من واجهات C (مثل <a data-ss1617022513="1" href="www.libsdl.org" rel="">SDL2</a>) على دوالّ الحذف (deletion functions) الخاصّة بها. هذا يعني أنّه لا يمكنك استخدام المؤشّرات الذكية مباشرة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6295_54" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">unique_ptr</span><span class="pun">&lt;</span><span class="pln">SDL_Surface</span><span class="pun">&gt;</span><span class="pln"> a</span><span class="pun">;</span><span class="pln"> </span><span class="com">// لن يعمل، غير آمن</span></pre>

<p>
	بدلاً من ذلك، سيكون عليك أن تعرّف دالّة الحذف الخاصّة بك، تستخدم الأمثلة هنا بنية <code><a data-ss1617022513="1" href="https://wiki.libsdl.org/SDL_Surface" rel="external nofollow">‎SDL_Surface‎</a></code> التي يجب تحريرها باستخدام الدالّة <code>‎SDL_FreeSurface()‎</code>، بيْد أنّه يجب تكييفها مع العديد من واجهات C الأخرى. كذلك يجب أن تكون دالة الحذف قابلة للاستدعاء باستخدام مؤشّر وسيط (pointer argument) على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6295_57" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">unique_ptr</span><span class="pun">&lt;</span><span class="pln">SDL_Surface</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">void</span><span class="pun">(*)(</span><span class="pln">SDL_Surface</span><span class="pun">*)&gt;</span><span class="pln"> a</span><span class="pun">(</span><span class="pln">pointer</span><span class="pun">,</span><span class="pln"> SDL_FreeSurface</span><span class="pun">);</span></pre>

<p>
	سيعمل أيّ كائن آخر قابل للاستدعاء أيضًا، على سبيل المثال:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6295_59" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">SurfaceDeleter</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">()(</span><span class="pln">SDL_Surface</span><span class="pun">*</span><span class="pln"> surf</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        SDL_FreeSurface</span><span class="pun">(</span><span class="pln">surf</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">unique_ptr </span><span class="pun">&lt;</span><span class="pln"> SDL_Surface</span><span class="pun">,</span><span class="pln"> </span><span class="typ">SurfaceDeleter</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> a</span><span class="pun">(</span><span class="pln">pointer</span><span class="pun">,</span><span class="pln"> </span><span class="typ">SurfaceDeleter</span><span class="pln"> </span><span class="pun">{});</span><span class="pln"> </span><span class="com">// آمن</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">unique_ptr </span><span class="pun">&lt;</span><span class="pln"> SDL_Surface</span><span class="pun">,</span><span class="pln"> </span><span class="typ">SurfaceDeleter</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> b</span><span class="pun">(</span><span class="pln">pointer</span><span class="pun">);</span><span class="pln"> </span><span class="com">// مكافئ للشيفرة أعلاه</span></pre>

<p>
	سيوفر لك هذا إدارة آمنة واقتصادية للذاكرة بدون استخدام <code>unique_ptr</code> وكذلك ستحصل على الأمان من ناحية الاعتراضات (Exceptions).
</p>

<p>
	لاحظ أنّ دالة الحذف جزء من النوع بالنسبة للمؤشّر الحصري (<code>‎unique_ptr‎</code>)، ويستطيع التنفيذ (implementation) استخدام تحسين الأساس الفارغ (Empty base optimization) لتجنّب أي تغيير في الحجم بالنسبة لدَوالّ الحذف المخصّصة الفارغة (Empty custom deleters). لذا، رغم أنّ:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6295_61" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">unique_ptr</span><span class="pun">&lt;</span><span class="pln">SDL_Surface</span><span class="pun">,</span><span class="pln"> </span><span class="typ">SurfaceDeleter</span><span class="pun">&gt;‎</span><span class="pln">

std</span><span class="pun">::</span><span class="pln">unique_ptr</span><span class="pun">&lt;</span><span class="pln">SDL_Surface</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">void</span><span class="pun">(*)(</span><span class="pln">SDL_Surface</span><span class="pun">*)&gt;‎</span><span class="pln"> 
</span></pre>

<p>
	يحلّان المشكلة بطريقة متماثلة، فإنّ حجم النوع الأوّل يساوي حجم مؤشّر واحد، بينما يجب أن يحتفظ النوع الأخير بمؤشّرين: أي المؤشّر <code>‎SDL_Surface‎</code> * ومؤشّر الدالة! أيضًا، يُفضّل تغليف دوالّ الحذف المخصّصة الحُرّةفي نوع فارغ، ويمكن استخدام مؤشّر مشترك (<code>‎shared_ptr‎</code>) بدلاً من مؤشّر حصري (<code>‎unique_ptr‎</code>) في الحالات التي يكون فيها عدُّ المراجع مهمًا.
</p>

<p>
	تخزِّن المؤشّرات المشتركة دالّة الحذف دائمًا، مما يؤدّي إلى محوِ نوع دالّة الحذف، هذا قد يكون مفيدًا في الواجهات البرمجية (APIs). يعيب استخدام المؤشّرات المشتركة هو أنّ حجم ذاكرة تخزين دالّة الحذف ستكون أكبر، وتكلفة صيانة عدّاد المراجع ستكون أكبر كذلك.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6295_63" style="">
<span class="com">// دالة الحذف مطلوبة في وقت الإنشاء وهي جزء من النوع</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">unique_ptr</span><span class="pun">&lt;</span><span class="pln">SDL_Surface</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">void</span><span class="pun">(*)(</span><span class="pln">SDL_Surface</span><span class="pun">*)&gt;</span><span class="pln"> a</span><span class="pun">(</span><span class="pln">pointer</span><span class="pun">,</span><span class="pln"> SDL_FreeSurface</span><span class="pun">);</span><span class="pln">
</span><span class="com">// دالة الحذف مطلوبة في وقت الإنشاء ولكنها ليست جزءًا من النوع</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">shared_ptr</span><span class="pun">&lt;</span><span class="pln">SDL_Surface</span><span class="pun">&gt;</span><span class="pln"> b</span><span class="pun">(</span><span class="pln">pointer</span><span class="pun">,</span><span class="pln"> SDL_FreeSurface</span><span class="pun">);</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 17 </strong>
</p>

<p>
	تسهّل <code>‎template auto‎</code> تغليف دوال الحذف المخصّصة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6295_65" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="kwd">auto</span><span class="pln"> </span><span class="typ">DeleteFn</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">FunctionDeleter</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">()(</span><span class="pln">T</span><span class="pun">*</span><span class="pln"> ptr</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="typ">DeleteFn</span><span class="pun">(</span><span class="pln">ptr</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> </span><span class="typ">DeleteFn</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> unique_ptr_deleter </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">unique_ptr</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> </span><span class="typ">FunctionDeleter</span><span class="pun">&lt;</span><span class="typ">DeleteFn</span><span class="pun">&gt;&gt;;</span></pre>

<p>
	المثال أعلاه سُيصبح:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6295_69" style="">
<span class="pln">unique_ptr_deleter</span><span class="pun">&lt;</span><span class="pln">SDL_Surface</span><span class="pun">,</span><span class="pln"> SDL_FreeSurface</span><span class="pun">&gt;</span><span class="pln"> c</span><span class="pun">(</span><span class="pln">pointer</span><span class="pun">);</span></pre>

<p>
	الغرض من <code>‎auto‎</code> في المثال السابق هو التعامل مع جميع الدوالّ الحرّة (free functions)، سواء كانت تُعيد <code>‎void‎</code> (مثل <code>‎SDL_FreeSurface‎</code>) أم لا (مثل <code>‎fclose‎</code>).
</p>

<h2>
	الملكية الحصرية بدون دلالة النقل
</h2>

<p>
	الإصدار <c></c>++‎&gt;
</p>

<p>
	ملاحظة: أُهمِلت <code>‎std::auto_ptr‎</code> في C++‎ 11 وستُزال تمامًا في C++‎ 17، لذا لا ينبغي أن تستخدمها إلّا إن كنت مضطرًا لاستخدام C++‎ 03 أو إصدار سابق وكنت على استعداد لتوخّي الحذر الشديد، أما فيما سوى ذلك فيوصى بالانتقال إلى unique_ptr و <code>‎std::move‎</code>.
</p>

<p>
	قبل المؤشّرات الحصريّة (<code>‎std::unique_ptr‎</code>) والدلالات النقليّة (move semantics)، كان لدينا <code>‎std::auto_ptr‎</code>، والذي يوفّر ملكيّة حصريّة، غير أنّه ينقل الملكية عند النسخ. وكما هو الحال مع جميع المؤشّرات الذكية، فإن المؤشّر <code>‎std::auto_ptr‎</code> ينظف الموارد تلقائيًا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6295_71" style="">
<span class="pun">{</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">auto_ptr</span><span class="str">&lt;int&gt;</span><span class="pln"> p</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">int</span><span class="pun">(</span><span class="lit">42</span><span class="pun">));</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">*</span><span class="pln">p</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="com">// هنا، لا يوجد تسرب في الذاكرة p تُحذف</span></pre>

<p>
	لكن يسمح بمالك واحد فقط:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6295_73" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">auto_ptr</span><span class="pun">&lt;</span><span class="pln">X</span><span class="pun">&gt;</span><span class="pln"> px </span><span class="pun">=</span><span class="pln"> </span><span class="pun">...;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">auto_ptr</span><span class="pun">&lt;</span><span class="pln">X</span><span class="pun">&gt;</span><span class="pln"> py </span><span class="pun">=</span><span class="pln"> px</span><span class="pun">;</span><span class="pln">
</span><span class="com">// فارغ الآن px </span></pre>

<p>
	هذا يسمح باستخدام <code>std::auto_ptr</code> للإبقاء على المِلكِيّة صريحةً وحصريّة، لكن مع خطر خسارة الملكية بشكل غير مقصود:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6295_75" style="">
<span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">auto_ptr </span><span class="pun">&lt;</span><span class="pln"> X </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="com">// X افتراض ملكية</span><span class="pln">
    </span><span class="com">// تحذفها في نهاية النطاق.</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">auto_ptr </span><span class="pun">&lt;</span><span class="pln"> X </span><span class="pun">&gt;</span><span class="pln"> px </span><span class="pun">=</span><span class="pln"> </span><span class="pun">...;</span><span class="pln">
f</span><span class="pun">(</span><span class="pln">px</span><span class="pun">);</span><span class="pln">    </span><span class="com">// X ملكية  f تتطلب</span><span class="pln">
</span><span class="com">// فارغ الآن px</span><span class="pln">
px </span><span class="pun">-&gt;</span><span class="pln"> foo</span><span class="pun">();</span><span class="pln"> </span><span class="com">// NPE!</span><span class="pln">
</span><span class="com">// لا يحذف px.~auto_ptr() </span></pre>

<p>
	حدث نقل الملكية في مُنشئ النَّسْخ (copy constructor)، ويأخذ مُنشئ النَّسخ وعامل تعيين النَّسخ الخاصّ بالمؤشّر <code>‎auto_ptr‎</code> معامِلاته بواسطة مرجع غير ثابت (non-const) حتى يمكن تعديلها. هذا مثال على ذلك:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6295_77" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">class</span><span class="pln"> auto_ptr </span><span class="pun">{</span><span class="pln">
        T </span><span class="pun">*</span><span class="pln"> ptr</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
            auto_ptr</span><span class="pun">(</span><span class="pln">auto_ptr </span><span class="pun">&amp;</span><span class="pln"> rhs</span><span class="pun">):</span><span class="pln"> ptr</span><span class="pun">(</span><span class="pln">rhs</span><span class="pun">.</span><span class="pln">release</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
        auto_ptr </span><span class="pun">&amp;</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">auto_ptr </span><span class="pun">&amp;</span><span class="pln"> rhs</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            reset</span><span class="pun">(</span><span class="pln">rhs</span><span class="pun">.</span><span class="pln">release</span><span class="pun">());</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="kwd">this</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        T </span><span class="pun">*</span><span class="pln"> release</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            T </span><span class="pun">*</span><span class="pln"> tmp </span><span class="pun">=</span><span class="pln"> ptr</span><span class="pun">;</span><span class="pln">
            ptr </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">nullptr</span><span class="pun">;</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> tmp</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="kwd">void</span><span class="pln"> reset</span><span class="pun">(</span><span class="pln">T </span><span class="pun">*</span><span class="pln"> tmp </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">nullptr</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">ptr </span><span class="pun">!=</span><span class="pln"> tmp</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                </span><span class="kwd">delete</span><span class="pln"> ptr</span><span class="pun">;</span><span class="pln">
                ptr </span><span class="pun">=</span><span class="pln"> tmp</span><span class="pun">;</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="com">/* دوال أخرى */</span><span class="pln">
    </span><span class="pun">};</span></pre>

<p>
	هذا يكسر الدلالة النسخيّة (copy semantics) التي تتطلّب أن ينتُج عن عمليّة نسخ كائنٍ ما نسختان متكافئتان. إن كان <code>‎T‎</code> نوعًا قابلًا للنسخ، فيمكن كتابة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6295_79" style="">
<span class="pln">T a </span><span class="pun">=</span><span class="pln"> </span><span class="pun">...;</span><span class="pln">
T b</span><span class="pun">(</span><span class="pln">a</span><span class="pun">);</span><span class="pln">
assert</span><span class="pun">(</span><span class="pln">b </span><span class="pun">==</span><span class="pln"> a</span><span class="pun">);</span></pre>

<p>
	لكن ليس هذا هو الحال بالنسبة إلى <code>‎auto_ptr‎</code>، لهذا من غير الآمن وضع <code>‎auto_ptr‎</code> في الحاويات.
</p>

<h2>
	تحويل المؤشرات المشتركة
</h2>

<p>
	لا يمكن استخدام:
</p>

<ul>
<li>
		<code>‎static_cast‎</code>
	</li>
	<li>
		<code>‎const_cast‎</code>
	</li>
	<li>
		<code>‎dynamic_cast‎</code>
	</li>
	<li>
		<code>‎reinterpret_cast‎</code>
	</li>
</ul>
<p>
	مباشرةً على المؤشّرات المشتركة <code>‎std::shared_ptr‎</code> للحصول على مؤشّر يتشارك المِلكِيَّة مع المؤشّر المُمرَّر كوسيط، وإنما يجب استخدام الدوالّ:
</p>

<ul>
<li>
		<code>‎</code> <code>‎std::static_pointer_cast‎</code>
	</li>
	<li>
		<code>‎std::const_pointer_cast‎</code>
	</li>
	<li>
		<code>‎std::dynamic_pointer_cast‎</code>
	</li>
	<li>
		<code>‎std::reinterpret_pointer_cast‎</code>
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6295_81" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">virtual</span><span class="pun">~</span><span class="typ">Base</span><span class="pun">()</span><span class="pln"> noexcept </span><span class="pun">{};</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Derived</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> derivedPtr</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">make_shared </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Derived</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">());</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> basePtr</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">static_pointer_cast </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">derivedPtr</span><span class="pun">));</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> constBasePtr</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">const_pointer_cast </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Base</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">basePtr</span><span class="pun">));</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> constDerivedPtr</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">dynamic_pointer_cast </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Derived</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">constBasePtr</span><span class="pun">));</span></pre>

<p>
	لاحظ أنّ <code>‎std::reinterpret_pointer_cast‎</code> غير متاحة في C++‎ 11 و C++‎ 14، إذ لم تُقترح إلا في <a data-ss1617022513="1" href="https://isocpp.org/files/papers/N3920.html" rel="external nofollow"> N3920</a>، ولم تُعتمد في مكتبة الأساسيات (Library Fundamentals)‏‏ TS إلّا في فبراير 2014. لكن يبقى من الممكن تنفيذها على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6295_83" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">To</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">From</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">inline</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">shared_ptr </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">To</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> reinterpret_pointer_cast</span><span class="pun">(</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">shared_ptr </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">From</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> ptr</span><span class="pun">)</span><span class="pln"> noexcept </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">shared_ptr </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">To</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">ptr</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">reinterpret_cast</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">To</span><span class="pun">*</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">ptr</span><span class="pun">.</span><span class="pln">get</span><span class="pun">()));</span><span class="pln">
    </span><span class="pun">}</span></pre>

<h2>
	كتابة مؤشر ذكي: value_ptr
</h2>

<p>
	<code>‎value_ptr‎</code> هو مؤشّر ذكيّ يتصرّف كقيمة، فعند النسخ ينسخ محتوياته، وعند الإنشاء ينشئ محتوياته أيضًا. انظر:
</p>

<pre class="ipsCode" id="ips_uid_6295_85">
// std::default_delete: مثل
template &lt;class T&gt;
struct default_copier
{
    // null فارغا ويعيد القيمة  T const* ينبغي أن يعالج الناسخ نوعا
    T *operator()(T const *tin) const
    {
        if (!tin)
            return nullptr;
        return new T(*tin);
    }
    void operator()(void *dest, T const *tin) const
    {
        if (!tin)
            return;
        return new (dest) T(*tin);
    }
};

// لمعالجة القيمة الفارغة tag صنف:
struct empty_ptr_t
{
};
constexpr empty_ptr_t empty_ptr{};
// مؤشر القيمة يطبع نفسه:
template &lt;class T, class Copier = default_copier&lt;T&gt;, class Deleter = std::default_delete&lt;T&gt;,
          class Base = std::unique_ptr&lt;T, Deleter&gt;&gt;
struct value_ptr : Base, private Copier
{
    using copier_type = Copier;
    // unique_ptr من typedefs أيضًا

    using Base::Base;

    value_ptr(T const &amp;t) : Base(std::make_unique&lt;T&gt;(t)),
                            Copier()
    {
    }
    value_ptr(T &amp;&amp;t) : Base(std::make_unique&lt;T&gt;(std::move(t))),
                       Copier()
    {
    }
    // لا يكون فارغا أبدا:
    value_ptr() : Base(std::make_unique&lt;T&gt;()),
                  Copier()
    {
    }
    value_ptr(empty_ptr_t) {}

    value_ptr(Base b, Copier c = {}) : Base(std::move(b)),
                                       Copier(std::move(c))
    {
    }

    Copier const &amp;get_copier() const
    {
        return *this;
    }

    value_ptr clone() const
    {
        return {
            Base(
                get_copier()(this-&gt;get()),
                this-&gt;get_deleter()),
            get_copier()};
    }
    value_ptr(value_ptr &amp;&amp;) = default;
    value_ptr &amp;operator=(value_ptr &amp;&amp;) = default;

    value_ptr(value_ptr const &amp;o) : value_ptr(o.clone()) {}
    value_ptr &amp;operator=(value_ptr const &amp;o)
    {
        if (o &amp;&amp; *this)
        {
            // عيّن المحتوى إن كانا فارغيْن:
            **this = *o;
        }
        else
        {
            // وإلا فعيِّن قيمة منسوخة:
            *this = o.clone();
        }
        return *this;
    }
    value_ptr &amp;operator=(T const &amp;t)
    {
        if (*this)
        {
            **this = t;
        }
        else
        {
            *this = value_ptr(t);
        }
</pre>

<p>
	لا تكون قيمة المؤشّر الذكي (value_ptr) فارغة إلّا إذا أنشأته باستخدام <code>‎empty_ptr_t‎</code>، أو قمت بعملية نقل (move) منه، وهذ يكشف حقيقة أنّه حصريّ (<code>‎unique_ptr‎</code>)، لذلك سيعمل العامل <code>‎explicit operator bool() const‎</code> عليه. يعيد التابع <code>‎.get()‎</code> مرجعًا (إذ أنه لا يكاد يكون فارغًا أبدًا)، فيما يعيد التابع <code>‎.get_pointer()‎</code> مؤشّرًا. ويمكن أن يكون هذا المؤشّر الذكي مفيدًا في حال كنّا نريد دلالة قيميّة (value-semantics)، لكن لا نريد الكشف عن المحتويات خارج نطاق التنفيذ. كذلك يمكن باستخدام ناسخ <code>‎Copier‎</code> غير افتراضي أن نتعامل مع الأصناف الأساسية الوهمية (virtual base classes) التي تعرف كيفيّة إنتاج نُسخ من الصنف المشتق وتحويلها إلى أنواع قيميّة (value-types).
</p>

<h2>
	جعل المؤشرات المشتركة تشير إلى this
</h2>

<p>
	يتيح لك <code>‎enable_shared_from_this‎</code> الحصول على نُسخة صالحة من مؤشّر مشترك يشير إلى [this](رابط الفصل 32)، وسترث تابع <code>‎shared_from_this‎</code> عبر اشتقاق صنف من قالب الصنف <code>‎enable_shared_from_this‎</code>، ليعيد مؤشّرا مشتركًا يشير إلى <code>‎this‎</code>.
</p>

<p>
	لاحظ أنه لا بدّ من إنشاء الكائن كمؤشّر مشترك (<code>‎shared_ptr‎</code>):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6295_87" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;memory&gt;</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> A </span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> enable_shared_from_this</span><span class="pun">&lt;</span><span class="pln">A</span><span class="pun">&gt;</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
A </span><span class="pun">*</span><span class="pln">ap1 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> A</span><span class="pun">();</span><span class="pln">
shared_ptr</span><span class="pun">&lt;</span><span class="pln">A</span><span class="pun">&gt;</span><span class="pln"> ap2</span><span class="pun">(</span><span class="pln">ap1</span><span class="pun">);</span><span class="pln"> </span><span class="com">// تحضير مؤشّر مشتركا يشير إلى  الكائن الذي يحتويه</span><span class="pln">
</span><span class="com">// ثم الحصول على مؤشّر مشترك يشير إلى الكائن من داخل الكائن نفسه</span><span class="pln">
shared_ptr</span><span class="pun">&lt;</span><span class="pln">A</span><span class="pun">&gt;</span><span class="pln"> ap3 </span><span class="pun">=</span><span class="pln"> ap1</span><span class="pun">-&gt;</span><span class="pln">shared_from_this</span><span class="pun">();</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> c3 </span><span class="pun">=</span><span class="pln"> ap3</span><span class="pun">.</span><span class="pln">use_count</span><span class="pun">();</span><span class="pln"> </span><span class="com">// =2: يشير إلى نفس الكائن.</span></pre>

<p>
	ملاحظة: لا يمكنك استدعاء <code>‎enable_shared_from_this‎</code> داخل المُنشئ.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6295_89" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;memory&gt;</span><span class="pln">        </span><span class="com">// enable_shared_from_this</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Widget</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">enable_shared_from_this </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Widget</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> </span><span class="typ">DoSomething</span><span class="pun">()</span><span class="pln"> 
</span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">shared_ptr </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Widget</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> self </span><span class="pun">=</span><span class="pln"> shared_from_this</span><span class="pun">();</span><span class="pln">
        someEvent </span><span class="pun">-&gt;</span><span class="pln"> </span><span class="typ">Register</span><span class="pun">(</span><span class="pln">self</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
</span><span class="pun">...</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="pun">...</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> w </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">make_shared </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Widget</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">();</span><span class="pln">
    w</span><span class="pun">-&gt;</span><span class="typ">DoSomething</span><span class="pun">();</span><span class="pln">
</span><span class="pun">...</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	إذا استخدمت <code>‎shared_from_this()‎</code> على كائن غير مملوك من مؤشّر مشترك، مثل كائن تلقائي محلي (local automatic object) أو كائن عام (global object)، فإنّ السلوك لن يكون محدّدًا. لكن المصرِّف أصبح يطلق الاعتراض <code>‎std::bad_alloc‎</code> منذ الإصدار C++‎ 17.
</p>

<p>
	يكافئ استخدام <code>‎shared_from_this()‎</code> من داخل مُنشئ، استخدامه على كائن غير مملوك من مؤشّر مشترك، لأنّ الكائنات ستكون مملوكة للمؤشّر المشترك بعد عودة المُنشئ.
</p>

<p>
	هذا الدرس جزء من <a data-ss1617022513="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة دروس عن C++‎</a>.
</p>

<p>
	ترجمة -بتصرّف- للفصل Chapter 33: Smart Pointers من كتاب <a data-ss1617022513="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">913</guid><pubDate>Tue, 07 Jul 2020 18:06:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x645;&#x624;&#x634;&#x631;&#x627;&#x62A; (Pointers) &#x641;&#x64A; Cpp</title><link>https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D9%85%D8%A4%D8%B4%D8%B1%D8%A7%D8%AA-pointers-%D9%81%D9%8A-cpp-r912/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_06/19.jpg.332da889e336588cf6eb0bee6bcd91e6.jpg" /></p>

<p>
	المؤشّر هو عنوان يشير إلى موقع في الذاكرة، وتُستخدم المؤشرات عادة للسماح للدوالّ أو هياكل البيانات بالحصول على معلومات عن الذاكرة وتعديلها دون الحاجة إلى نسخ الذاكرة المشار إليها، والمؤشّرات قابلة للاستخدام سواءً مع الأنواع الأوليّة (المٌضمّنة) أو الأنواع التي يعرّفها المستخدم.
</p>

<p>
	وتستفيد المؤشّرات من عامل التحصيل <code>‎*‎</code> و العنونة <code>‎&amp;‎</code> و السهم <code>‎-&gt;‎</code>، إذ يُستخدم عاملا <code>*</code> و <code>‎‎-&gt;‎</code> للوصول إلى الذاكرة المشار إليها، فيما يُستخدم المعامل <code>‎&amp;‎</code> للحصول على عنوانٍ في الذاكرة.
</p>

<h2>
	عمليات المؤشرات
</h2>

<p>
	يوجد مُعاملان يختصان بالمؤشّرات، وهما: معامل العنونة (Address-of operator) وهو <code>&amp;</code> الذي يعيد عنوان عاملِهِ في الذاكرة، ومعامل التحصيل (Dereference) وهو <code>*</code> الذي يعيد قيمة المتغير الموجود في العنوان المحدّد بواسطة عامله.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3595_7" style="">
<span class="typ">int</span><span class="pln"> var </span><span class="pun">=</span><span class="pln"> </span><span class="lit">20</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="pln">ptr</span><span class="pun">;</span><span class="pln">
ptr </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">var</span><span class="pun">;</span><span class="pln">

cout </span><span class="pun">&lt;&lt;</span><span class="pln"> var </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">
</span><span class="com">// 20 (قيمة المتغير)</span><span class="pln">

cout </span><span class="pun">&lt;&lt;</span><span class="pln"> ptr </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">
</span><span class="com">// 0x234f119 (موقع المتغير في الذاكرة)</span><span class="pln">

cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">*</span><span class="pln">ptr </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">
</span><span class="com">// 20(ptr قيمة المتغير المخزن في مؤشر)</span></pre>

<p>
	يُستخدم رمز النجمة <code>*</code> للتصريح عن مؤشّر لمجرد التوضيح بأنه مؤشر، ولا ينبغي أن تخلط بينه وبين عامل التحصيل (dereference operator) الذي يُستخدم للحصول على القيمة الموجودة في عنوان محدّد، إذ هما شيئان مختلفان مُمثّلان بنفس الرمز.
</p>

<h2>
	أساسيات المؤشرات
</h2>

<p>
	الإصدار <c></c>++‎&gt;
</p>

<p>
	ملاحظة: في كل ما يلي، سنفترض وجود الثابت C++‎ 11) <code>‎nullptr</code>‎<code>). بالنسبة للإصدارات السابقة، بدّل </code>‎nullptr‎ <code>مكان </code>‎NULL‎، وهو الثابت الذي كان يؤدي وظيفة مشابهة.
</p>

<h3>
	إنشاء متغير المؤشر
</h3>

<p>
	يمكن إنشاء متغيّرات المؤشّرات باستخدام صيغة <code>‎*‎</code>، على سبيل المثال: <code>‎int *pointer_to_int;‎</code>. تحتوي المتغيرات من نوع المؤشّرات (<code>‎int *‎</code> مثلا) على عنوان ذاكرة يكون موقعًا تُخزَّن فيه بيانات النوع الأساسي (كـ <code>‎int *‎</code> مرة أخرى). ويتضح الفرق عند مقارنة حجم المتغير مع حجم المؤشّر الذي يشير إلى نفس النوع. انظر المثال التالي الذي نصرح فيه عن بُنية من نوع <code>big_struct</code> تحتوي على ثلاثة أعداد <code>long long int</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3595_9" style="">
<span class="kwd">typedef</span><span class="pln"> </span><span class="kwd">struct</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">long</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> foo1</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">long</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> foo2</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">long</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> foo3</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
big_struct</span><span class="pun">;</span></pre>

<p>
	والآن ننشئ متغير <code>bar</code> من نوع <code>big_struct</code>، ثم ننشئ المتغير <code>p_bar</code> من نوع <code>pointer to big_struce</code>، ونهيئه إلى المؤشر الفارغ <code>nullptr</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3595_11" style="">
<span class="pln">big_struct bar</span><span class="pun">;</span><span class="pln">
big_struct </span><span class="pun">*</span><span class="pln"> p_bar0 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">nullptr</span><span class="pun">;</span><span class="pln">
</span><span class="com">// `bar` يطبع حجم</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"sizeof(bar) = "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="pln">bar</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="com">// `p_bar` يطبع حجم</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"sizeof(p_bar0) = "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="pln">p_bar0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="com">/* الناتج
sizeof(bar) = 24
sizeof(p_bar0) = 8
*/</span></pre>

<h3>
	أخذ عنوان متغير آخر
</h3>

<p>
	يمكن إسناد قيمة مؤشّر إلى مؤشر آخر مثل المتغيرات العادية بالضبط، إلا أنّه في حال المؤشّرات فإنّ عنوان الذاكرة هو الذي يُنسخ من مؤشّر إلى آخر وليس البيانات الحقيقية التي يشير إليها المؤشّر. كذلك قد تأخذ المؤشّرات القيمة <code>‎nullptr‎</code> التي تمثّل موقعًا فارغًا في الذاكرة، وتمثل المؤشّرات التي تساوي <code>‎nullptr‎</code> موقعًا غير صالح في الذاكرة، وعليه فهي لا تشير إلى أيّ بيانات فعليّة.
</p>

<p>
	نحصل على عنوان الذاكرة الخاص بمتغيّر من نوع ما عن طريق إِسباق المتغيّر بعامل العَنْوَنة <code>‎&amp;‎</code>، وتكون القيمة المعادة من <code>‎&amp;‎</code> هي مؤشّر إلى النوع الأساسي الذي يحتوي على عنوان ذاكرة المتغير، وهي بيانات صالحة طالما لم يخرج المتغير من النطاق. انظر المثال التالي حيث ننسخ <code>p_bar0</code> إلى <code>p_bar1</code>، ثم نأخذ عنوان <code>bar</code> إلى <code>p_bar_2</code>، وعليه فإن <code>p_bar1</code> يصير فارغًا <code>nullptr</code>، و<code>p_bar2</code> صار يساوي <code>bar&amp;</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3595_13" style="">
<span class="pln">big_struct </span><span class="pun">*</span><span class="pln">p_bar1 </span><span class="pun">=</span><span class="pln"> p_bar0</span><span class="pun">;</span><span class="pln">
big_struct </span><span class="pun">*</span><span class="pln">p_bar2 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">bar</span><span class="pun">;</span></pre>

<p>
	لنجعل الآن <code>p_bar0</code> يساوي <code>&amp;bar</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3595_15" style="">
<span class="pln">p_bar0 </span><span class="pun">=</span><span class="pln"> p_bar2</span><span class="pun">;</span><span class="pln">

p_bar2 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">nullptr</span><span class="pun">;</span><span class="pln">

</span><span class="com">// p_bar0 == &amp;bar</span><span class="pln">
</span><span class="com">// p_bar1 == nullptr</span><span class="pln">
</span><span class="com">// p_bar2 == nullptr</span></pre>

<p>
	ذلك يخالف سلوك المراجع (references) كما يلي:
</p>

<ul>
<li>
		لا يؤدي إسناد مؤشّر إلى آخر إلى استبدال الذاكرة التي يشير إليها المؤشِّر المُسنَد إليه؛
	</li>
	<li>
		يمكن أن تكون المؤشّرات فارغة.
	</li>
	<li>
		عنوان العامل ينبغي أن يكون صريحًا.
	</li>
</ul>
<h3>
	الوصول إلى محتوى المؤشّر
</h3>

<p>
	يتطلب الوصول إلى العنوان استخدام العامل <code>‎&amp;‎</code>، أمّا الوصول إلى المحتوى فيتطلب استخدام عامل التحصيل <code>‎*‎</code> كسابقة (preﬁx)، عندما يُحصَّل مؤشّر فإنّه يُصبح متغيرًا من النوع الأساسي (underlying)، بل يكون مرجعًا إليه على الحقيقة، ويمكن بعدها قراءته وتعديله إن لم يكن ثابتًا (<code>‎const‎</code>). انظر المثال التالي حيث يشير <code>p_bar0</code> إلى <code>bar</code> ويطبع 5 في الخطوة 1، ثم نسند القيمة التي يشير إليها المؤشر <code>p_bar0</code> إلى <code>baz</code> في الخطوة 2، لتحتوي الأخيرة نسخة من البيانات المشار إليها من قبل <code>p_bar0</code> في الخطوة 3:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3595_17" style="">
<span class="pun">(*</span><span class="pln">p_bar0</span><span class="pun">).</span><span class="pln">foo1 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln">
</span><span class="com">// 1 الخطوة</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"bar.foo1 = "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> bar</span><span class="pun">.</span><span class="pln">foo1 </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="com">// 2 الخطوة</span><span class="pln">
big_struct baz</span><span class="pun">;</span><span class="pln">
baz </span><span class="pun">=</span><span class="pln"> </span><span class="pun">*</span><span class="pln">p_bar0</span><span class="pun">;</span><span class="pln">
</span><span class="com">// 3 الخطوة</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"baz.foo1 = "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> baz</span><span class="pun">.</span><span class="pln">foo1 </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></pre>

<p>
	يُختصر العامليْن <code>‎*‎</code> و <code>‎.‎</code> بالرمز <code>‎-&gt;‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3595_19" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"bar.foo1 = "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">(*</span><span class="pln">p_bar0</span><span class="pun">).</span><span class="pln">foo1 </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln"> </span><span class="com">// 5</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"bar.foo1 = "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln">  p_bar0</span><span class="pun">-&gt;</span><span class="pln">foo1  </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln"> </span><span class="com">// 5</span></pre>

<h3>
	تحصيل مؤشّرات غير صالحة
</h3>

<p>
	يجب أن تتأكد عند تحصيل مؤشر إلى أنّه يشير إلى بيانات صالحة، إذ قد يؤدي تحصيل مؤشّر غير صالح (أو مؤشّر فارغ) إلى حدوث خرق للذاكرة (memory access violation)، أو إلى قراءة البيانات المُهمَلة (garbage data) أو كتابتها.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3595_21" style="">
<span class="pln">big_struct </span><span class="pun">*</span><span class="pln">never_do_this</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// never_do_this هذا متغير محلي، ولا يوجد خارج</span><span class="pln">
    big_struct retval</span><span class="pun">;</span><span class="pln">
    retval</span><span class="pun">.</span><span class="pln">foo1 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">11</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// retval إعادة عنوان </span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">retval</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// تم تدميرها، وأي شيفرة تستخدم القيمة المعادة من قبل retval</span><span class="pln">
    </span><span class="com">// لها مؤشّر إلى مساحة في الذاكرة `never_do_this` </span><span class="pln">
    </span><span class="com">// تحتوي البيانات المهملة</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	في مثل هذه الحالة، يطلق المصرّفان <code>‎g++‎</code> و <code>‎clang++‎</code> التحذيرات التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3595_23" style="">
<span class="pun">(</span><span class="typ">Clang</span><span class="pun">)</span><span class="pln"> warning</span><span class="pun">:</span><span class="pln"> address of </span><span class="typ">stack</span><span class="pln"> memory associated with local variable </span><span class="str">'retval'</span><span class="pln"> returned </span><span class="pun">[-</span><span class="pln">
</span><span class="typ">Wreturn</span><span class="pun">-</span><span class="typ">stack</span><span class="pun">-</span><span class="pln">address</span><span class="pun">]</span><span class="pln">
</span><span class="pun">(</span><span class="typ">Gcc</span><span class="pun">)</span><span class="pln">   warning</span><span class="pun">:</span><span class="pln"> address of local variable </span><span class="pun">‘</span><span class="pln">retval</span><span class="pun">’</span><span class="pln"> returned </span><span class="pun">[-</span><span class="typ">Wreturn</span><span class="pun">-</span><span class="pln">local</span><span class="pun">-</span><span class="pln">addr</span><span class="pun">]</span></pre>

<p>
	وعليه يجب توخي الحذر عند تمرير المؤشّرات كوسائط إلى دوال، إذ أنّها قد تكون فارغة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3595_25" style="">
<span class="kwd">void</span><span class="pln"> naive_code</span><span class="pun">(</span><span class="pln">big_struct </span><span class="pun">*</span><span class="pln">ptr_big_struct</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// ... `ptr_big_struct` شيفرة لا تتحقق من صلاحية</span><span class="pln">
    ptr_big_struct </span><span class="pun">-&gt;</span><span class="pln"> foo1 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">12</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="com">// (ٍSegmentation) خطأ في التجزئة</span><span class="pln">
naive_code</span><span class="pun">(</span><span class="kwd">nullptr</span><span class="pun">);</span></pre>

<h2>
	حسابيات المؤشرات
</h2>

<h3>
	الزيادة والإنقَاص
</h3>

<p>
	المؤشرات قابلة للزيادة أو الإنقاص منها، وتؤدي زيادة مؤشّر إلى نقل قيمة المؤشّر إلى العنصر الذي يلي العنصر المُشار إليه حاليًا في [المصفوفة](رابط الفصل 8)، أمّا إنقاصه فينقله إلى العنصر السابق في المصفوفة. كذلك لا يجوز إجراء العمليات الحسابيّة على المؤشّرات التي تشير إلى نوع ناقص مثل <code>‎void‎</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3595_27" style="">
<span class="kwd">char</span><span class="pun">*</span><span class="pln"> str </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">[</span><span class="lit">10</span><span class="pun">];</span><span class="pln"> </span><span class="com">// str = 0x010</span><span class="pln">
</span><span class="pun">++</span><span class="pln">str</span><span class="pun">;</span><span class="pln"> </span><span class="com">// str = 0x011  in this case sizeof(char) = 1 byte</span><span class="pln">
</span><span class="typ">int</span><span class="pun">*</span><span class="pln"> arr </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">int</span><span class="pun">[</span><span class="lit">10</span><span class="pun">];</span><span class="pln"> </span><span class="com">// arr = 0x00100</span><span class="pln">
</span><span class="pun">++</span><span class="pln">arr</span><span class="pun">;</span><span class="pln"> </span><span class="com">// arr = 0x00104 if sizeof(int) = 4 bytes</span><span class="pln">
</span><span class="kwd">void</span><span class="pun">*</span><span class="pln"> ptr </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">void</span><span class="pun">*</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">[</span><span class="lit">10</span><span class="pun">];</span><span class="pln">
</span><span class="pun">++</span><span class="pln">ptr</span><span class="pun">;</span><span class="pln"> </span><span class="com">// نوع ناقص void </span></pre>

<p>
	في حال زيادة مؤشّر يشير إلى العنصر الأخير، فإنّ المؤشّر سيشير إلى العنصر الذي يلي العنصر الأخير في المصفوفة، ولا يمكن تحصيل مؤشّر كهذا لكن يمكن إنقاصه، وتؤدي زيادة مؤشّر إلى العنصر الذي يلي العنصر الأخير في المصفوفة أو إنقاص مؤشّر إلى العنصر الأول إلى سلوك غير محدّد. أيضًا، يمكن التعامل مع المؤشّرات التي تشير إلى أنواع أخرى غير المصفوفات كما لو كانت تشير إلى مصفوفات أحادية.
</p>

<h3>
	الجمع والطرح
</h3>

<p>
	يمكن إضافة قيم عددية صحيحة إلى المؤشّرات، ويكافئ ذلك زيادة قيمة المؤشّر بعدد ما خلاف 1، كما يمكن أيضًا طرح قيم عددية صحيحة من المؤشّرات أيضًا مما يؤدي إلى إنقاص قيمة المؤشّر، ويجب أن يشير المؤشر إلى نوع كامل كما هو الحال مع الزيادة والإنقَاص اللذيْن شرحناهما أعلاه.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3595_29" style="">
<span class="kwd">char</span><span class="pun">*</span><span class="pln"> str </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">[</span><span class="lit">10</span><span class="pun">];</span><span class="pln"> </span><span class="com">// str = 0x010</span><span class="pln">
str </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln"> </span><span class="com">// str = 0x010 + 2 * sizeof(char) = 0x012</span><span class="pln">
</span><span class="typ">int</span><span class="pun">*</span><span class="pln"> arr </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">int</span><span class="pun">[</span><span class="lit">10</span><span class="pun">];</span><span class="pln"> </span><span class="com">// arr = 0x100</span><span class="pln">
arr </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln"> </span><span class="com">// arr = 0x100 + 2 * sizeof(int) = 0x108, assuming sizeof(int) == 4.</span></pre>

<h3>
	الفرق بين المؤشرات
</h3>

<p>
	يمكن حساب الفرق بين مؤشِّرين يشيران إلى نفس النوع، لكن يجب أن يكون المؤشّران داخل نفس كائن المصفوفة، وإلا قد تحدث نتائج غير متوقعة. فإذا كان لدينا مؤشّران <code>‎P‎</code> و <code>‎Q‎</code> في نفس المصفوفة، وكان <code>‎P‎</code> يشير إلى العنصر رقم <code>‎i‎</code> في المصفوفة و <code>‎Q‎</code> يشير إلى العنصر رقم <code>‎j‎</code>، فإنّ <code>‎P -‎ ‎Q‎</code> سيشير إلى العنصر رقم <code>‎i - ‎j‎</code> في المصفوفة، ويكون نوع النتيجة <code>std::ptrdiff_t</code> من <code>&lt;cstddef&gt;</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3595_31" style="">
<span class="kwd">char</span><span class="pun">*</span><span class="pln"> start </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">[</span><span class="lit">10</span><span class="pun">];</span><span class="pln"> </span><span class="com">// str = 0x010</span><span class="pln">
</span><span class="kwd">char</span><span class="pun">*</span><span class="pln"> test </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">start</span><span class="pun">[</span><span class="lit">5</span><span class="pun">];</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">ptrdiff_t</span><span class="pln"> diff </span><span class="pun">=</span><span class="pln"> test </span><span class="pun">-</span><span class="pln"> start</span><span class="pun">;</span><span class="pln"> </span><span class="com">// 5 يساوي</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">ptrdiff_t</span><span class="pln"> diff </span><span class="pun">=</span><span class="pln"> start </span><span class="pun">-</span><span class="pln"> test</span><span class="pun">;</span><span class="pln"> </span><span class="com">// -5 يساوي</span></pre>

<h2>
	المؤشرات إلى الأعضاء
</h2>

<h3>
	مؤشّرات إلى الدوال التابعة الساكنة
</h3>

<p>
	تشبه الدوال التابعة الساكنة (<code>‎static‎</code>) دوالَّ C/C++‎ العادية باستثناء نطاقها، كما يلي:
</p>

<ul>
<li>
		تكون موجودة داخل الصنف (<code>‎class‎</code>)، لذا يجب أن يُرفق اسمها باسم الصنف.
	</li>
	<li>
		لديها حق الوصول للأعضاء العامّة (<code>‎public‎</code>) والمحميّة (<code>‎protected‎</code>) والخاصّة (<code>‎private‎</code>)، فإذا كان لديك حق الوصول إلى دالة تابع ساكن <code>‎static‎</code> وسميته بشكل صحيح (أي أرفقته باسم الكائن الذي ينتمي إليه)، فيمكنك الإشارة إلى تلك الدالّة كما لو كانت دالّة عادية:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3595_33" style="">
<span class="kwd">typedef</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="typ">Fn</span><span class="pun">(</span><span class="typ">int</span><span class="pun">);</span><span class="pln"> 
</span><span class="com">// هي نوع دالة تأخذ عددًا صحيحًا وتعيد عددًا صحيحا Fn </span><span class="pln">
</span><span class="com">// 'Fn' من النّوع MyFn() ّلاحظ أن</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> </span><span class="typ">MyFn</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Class</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="com">// 'Fn' من النوع Static() لاحظ أن</span><span class="pln">
        </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="typ">Static</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln"> </span><span class="com">// الصنف</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Fn</span><span class="pln"> </span><span class="pun">*</span><span class="pln">fn</span><span class="pun">;</span><span class="pln">            </span><span class="com">// Fn هو مؤشّر إلى النوع  fn </span><span class="pln">
    fn </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="typ">MyFn</span><span class="pun">;</span><span class="pln">        </span><span class="com">// أشِر إلى دالة ما</span><span class="pln">
    fn</span><span class="pun">(</span><span class="lit">3</span><span class="pun">);</span><span class="pln">            </span><span class="com">// استدعها</span><span class="pln">
    fn </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="typ">Class</span><span class="pun">::</span><span class="typ">Static</span><span class="pun">;</span><span class="pln">    </span><span class="com">// أشِر إلى دالة أخرى</span><span class="pln">
    fn</span><span class="pun">(</span><span class="lit">4</span><span class="pun">);</span><span class="pln">            </span><span class="com">// استدعها</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="com">// main()</span></pre>

<h3>
	مؤشّرات إلى الدوال التوابع
</h3>

<p>
	للوصول إلى دالة تابعة من صنف ما، يجب أن يكون لديك "مقبض" (handle) للنسخة المحدّدة، إمّا للنسخة نفسها أو مؤشّر أو مرجع إليها. وإذا كان لديك نسخة من صنف فيمكنك الإشارة إلى أعضائها باستخدام مؤشّر-إلى-عضو (pointer-to-member)، لاحظ أنّه يجب أن يكون المؤشّر من نفس النوع الذي تشير إليه تلك الأعضاء.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3595_35" style="">
<span class="kwd">typedef</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="typ">Fn</span><span class="pun">(</span><span class="typ">int</span><span class="pun">);</span><span class="pln"> </span><span class="com">// هي نوع دالة تأخذ عددًا صحيحًا وتعيد عددًا صحيحًا Fn </span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Class</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="com">// 'Fn' من النوع A() لاحظ أن</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> A</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> a</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="com">// 'Fn' من النوع B() لاحظ أن</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> B</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln"> </span><span class="com">// صنف</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Class</span><span class="pln"> c</span><span class="pun">;</span><span class="pln">            </span><span class="com">// تحتاج نسخة صنف لتجرب معها</span><span class="pln">
    </span><span class="typ">Class</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> p </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> c</span><span class="pun">;</span><span class="pln">        </span><span class="com">// تحتاج مؤشر صنف لتجرب معه</span><span class="pln">

    </span><span class="typ">Fn</span><span class="pln"> </span><span class="typ">Class</span><span class="pun">::*</span><span class="pln">fn</span><span class="pun">;</span><span class="pln">        </span><span class="com">// داخل الصنف Fn هو مؤشّر إلى النوع fn </span><span class="pln">

    fn </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="typ">Class</span><span class="pun">::</span><span class="pln">A</span><span class="pun">;</span><span class="pln">        </span><span class="com">// داخل أي صنف A يشير إلى fn </span><span class="pln">
    </span><span class="pun">(</span><span class="pln">c</span><span class="pun">.*</span><span class="pln">fn</span><span class="pun">)(</span><span class="lit">5</span><span class="pun">);</span><span class="pln">            </span><span class="com">// Fn عبر c الخاصة بـ A مرر 5 إلى دالة</span><span class="pln">
    fn </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="typ">Class</span><span class="pun">::</span><span class="pln">B</span><span class="pun">;</span><span class="pln">        </span><span class="com">// داخل أي صنف B يشير الآن إلى fn </span><span class="pln">
        </span><span class="pun">(</span><span class="pln">p </span><span class="pun">-&gt;*</span><span class="pln">fn</span><span class="pun">)(</span><span class="lit">6</span><span class="pun">);</span><span class="pln">        </span><span class="com">// Fn عبر c الخاصة بـ B مرر 6 إلى دالة</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="com">// main()</span></pre>

<p>
	على خلاف المؤشّرات التي تشير إلى متغيرات الأعضاء كما في المثال السابق، ويجب أن يكون الجمع بين نسخة الصنف والمؤشّر-إلى-العضو باستخدام الأقواس، الأمر الذي قد يبدو غريبًا كأن <code>*.</code> و <code>*&lt;-</code> لم تكونا كافيتين!
</p>

<h3>
	المؤشّرات إلى متغيرات الأعضاء
</h3>

<p>
	للوصول إلى عضو من <code>‎class‎</code>، يجب أن يكون لديك "مقبض" للنسخة المحددة، إما النسخة نفسها أو مؤشّر أو مرجع إليها. وإذا كانت لديك نسخة من الصنف <code>‎class‎</code> فتستطيع الإشارة إلى أعضائها باستخدام مؤشّر-إلى-عضو، لاحظ أنّ المؤشّر يجب أن يكون من نفس النوع الذي يشير إليه تلك الأعضاء.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3595_37" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Class</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">,</span><span class="pln"> z</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">char</span><span class="pln"> m</span><span class="pun">,</span><span class="pln"> n</span><span class="pun">,</span><span class="pln"> o</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln"> </span><span class="com">// صنف</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">        </span><span class="com">// (Global) متغير عام</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Class</span><span class="pln"> c</span><span class="pun">;</span><span class="pln">        </span><span class="com">// تحتاج نسخة صنف لتجرب معها</span><span class="pln">
    </span><span class="typ">Class</span><span class="pln"> </span><span class="pun">*</span><span class="pln">p </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">c</span><span class="pun">;</span><span class="pln">    </span><span class="com">// تحتاج مؤشر صنف لتجرب معه</span><span class="pln">

   </span><span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="pln">p_i</span><span class="pun">;</span><span class="pln">        </span><span class="com">// int مؤشّر إلى</span><span class="pln">

    p_i </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> x        </span><span class="com">// x المؤشّر يشير الآن إلى </span><span class="pln">
    p_i </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">c</span><span class="pun">.</span><span class="pln">x</span><span class="pun">;</span><span class="pln">        </span><span class="com">// c الخاص بـ  x الآن يشير إلى العنصر</span><span class="pln">

    </span><span class="typ">int</span><span class="pln"> </span><span class="typ">Class</span><span class="pun">::*</span><span class="pln">p_C_i</span><span class="pun">;</span><span class="pln">        </span><span class="com">// مؤشّر إلى عدد صحيح داخل الصنف</span><span class="pln">

    p_C_i </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="typ">Class</span><span class="pun">::</span><span class="pln">x</span><span class="pun">;</span><span class="pln">    </span><span class="com">// داخل الصنف x الإشارة إلى</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> c</span><span class="pun">.*</span><span class="pln">p_C_i</span><span class="pun">;</span><span class="pln">        </span><span class="com">// c داخل النسخة x لإيجاد  p_c_i استخدام</span><span class="pln">
    p_C_i </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="typ">Class</span><span class="pun">::</span><span class="pln">y</span><span class="pun">;</span><span class="pln">    </span><span class="com">// داخل أي صنف y يشير إلى </span><span class="pln">
    i </span><span class="pun">=</span><span class="pln"> c</span><span class="pun">.*</span><span class="pln">p_C_i         </span><span class="com">// c داخل النسخة y لإيجاد  p_c_i استخدام</span><span class="pln">

  p_C_i </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="typ">Class</span><span class="pun">::</span><span class="pln">m</span><span class="pun">;</span><span class="pln"> </span><span class="com">// خطأ</span><span class="pln">

    </span><span class="kwd">char</span><span class="pln"> </span><span class="typ">Class</span><span class="pun">::*</span><span class="pln">p_C_c </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="typ">Class</span><span class="pun">::</span><span class="pln">m</span><span class="pun">;</span><span class="pln"> </span><span class="com">// هذا أفضل</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="com">// main()</span></pre>

<p>
	تتطلّب صياغة المؤشّر العضوي بعض العناصر الإضافية:
</p>

<ul>
<li>
		لتعريف نوع المؤشّر، تحتاج إلى ذِكر النّوع الأساسي إضافة إلى حقيقة أنه داخل صنف: <code>‎int Class::*ptr;‎</code>.
	</li>
	<li>
		إذا كان لديك صنف أو مرجع وتريد استخدامه مع مؤشّر-إلى-عضو فستحتاج إلى استخدام المعامل <code>‎.*‎</code> (يشبه المعامل <code>‎.‎</code>).
	</li>
	<li>
		إذا كان لديك مؤشّر يشير إلى صنف وتريد استخدامه مع مؤشّر-إلى-عضو، فستحتاج إلى استخدام المعامل <code>‎-&gt;*‎</code> (يشبه المعامل <code>‎-&gt;‎</code>).
	</li>
</ul>
<h3>
	مؤشّرات إلى متغيرات الأعضاء الساكنة
</h3>

<p>
	متغيرات الأعضاء الساكنة تشبه متغيرات C / C++‎ العادية، باستثناء نطاقها:
</p>

<ul>
<li>
		إذ تكون موجودة داخل الصنف (<code>‎class‎</code>)، لذلك يجب أن يُرفق اسمها مع اسم الصنف؛
	</li>
	<li>
		تتمتع بحق الوصول إلى العناصر العامّة (<code>‎public‎</code>) والمحميّة (<code>‎protected‎</code>) والخاصّة (<code>‎private‎</code>). لذلك إن كان لديك حق الوصول إلى متغير عضو ساكن وأرفقته باسم الكائن الذي ينتمي إليه بالشكل الصحيح، فيمكنك الإشارة إلى ذلك المتغير مثل أيّ متغير عادي:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3595_39" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Class</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln"> </span><span class="com">// صنف</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> </span><span class="typ">Class</span><span class="pun">::</span><span class="pln">i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">    </span><span class="com">// i تعريف قيمة</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> j </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">        </span><span class="com">// متغير عام</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> k </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;</span><span class="pln"> </span><span class="com">// متغير محلي</span><span class="pln">

    </span><span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="pln">p</span><span class="pun">;</span><span class="pln">

    p </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">k</span><span class="pun">;</span><span class="pln">        </span><span class="com">// k الإشارة إلى</span><span class="pln">
    </span><span class="pun">*</span><span class="pln">p </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">        </span><span class="com">// تعديل المؤشر</span><span class="pln">
    p </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">j</span><span class="pun">;</span><span class="pln">        </span><span class="com">// j الإشارة إلى</span><span class="pln">
    </span><span class="pun">*</span><span class="pln">p </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;</span><span class="pln">        </span><span class="com">// تعديل المؤشر</span><span class="pln">
    p </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="typ">Class</span><span class="pun">::</span><span class="pln">i</span><span class="pun">;</span><span class="pln">    </span><span class="com">// Class::i الإشارة إلى</span><span class="pln">
    </span><span class="pun">*</span><span class="pln">p </span><span class="pun">=</span><span class="pln"> </span><span class="lit">4</span><span class="pun">;</span><span class="pln">        </span><span class="com">// تعديل المؤشر</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="com">// main()</span></pre>

<h2>
	مؤشر This
</h2>

<p>
	جميع الدوال التوابع غير الساكنة لها معامِل خفيّ، وهو مؤشّر يشير إلى نسخة من الصنف يُسمّى <code>‎this‎</code>، ويُدرج هذا المعامل خُفية في بداية قائمة المعاملات ويُعالَج من قِبل المُصرِّف. ويمكن الوصول إلى عضو من الصنف داخل دالة تابعة عبر <code>‎this‎</code>، مما يسمح للمُصرِّف باستخدام دالة تابعة غير ساكنة لكل النسخ، ويسمح لدالة تابعة ما باستدعاء الدوال التوابع الأخرى <a data-ss1617022512="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-16-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-%D8%A7%D9%84%D8%AA%D8%B9%D8%AF%D8%AF%D9%8A%D8%A9-%D8%A7%D9%84%D8%B4%D9%83%D9%84%D9%8A%D8%A9-polymorphism-%D9%81%D9%8A-cpp-r900/" rel="">بأشكال متعددة</a>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3595_41" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">ThisPointer</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">

    </span><span class="typ">ThisPointer</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> ii</span><span class="pun">);</span><span class="pln">

    </span><span class="kwd">virtual</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> func</span><span class="pun">();</span><span class="pln">

    </span><span class="typ">int</span><span class="pln"> get_i</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> set_i</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> ii</span><span class="pun">);</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">ThisPointer</span><span class="pun">::</span><span class="typ">ThisPointer</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> ii</span><span class="pun">):</span><span class="pln"> i</span><span class="pun">(</span><span class="pln">ii</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span></pre>

<p>
	يعيد المصرّف كتابتها على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3595_43" style="">
<span class="typ">ThisPointer</span><span class="pun">::</span><span class="typ">ThisPointer</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> ii</span><span class="pun">):</span><span class="pln"> </span><span class="kwd">this</span><span class="pln"> </span><span class="pun">-&gt;</span><span class="pln"> i</span><span class="pun">(</span><span class="pln">ii</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span></pre>

<p>
	يكون المنشئ مسؤولًا عن تحويل الذاكرة المخصصة إلى <code>this</code>، وبما أنه المسؤول عن إنشاء الكائن أيضًا فإن <code>this</code> لن تكون صالحة تمامًا إلى أن يتم إنشاء النسخة. نتابع المثال:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3595_45" style="">
<span class="com">/* virtual */</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> </span><span class="typ">ThisPointer</span><span class="pun">::</span><span class="pln">func</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">some_external_condition</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        set_i</span><span class="pun">(</span><span class="lit">182</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">218</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="com">// المصرّف يعيد كتابتها على النحو التالي</span><span class="pln">
</span><span class="com">/* virtual */</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> </span><span class="typ">ThisPointer</span><span class="pun">::</span><span class="pln">func</span><span class="pun">(</span><span class="typ">ThisPointer</span><span class="pun">*</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">some_external_condition</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">this</span><span class="pln"> </span><span class="pun">-&gt;</span><span class="pln"> set_i</span><span class="pun">(</span><span class="lit">182</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">this</span><span class="pln"> </span><span class="pun">-&gt;</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">218</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> </span><span class="typ">ThisPointer</span><span class="pun">::</span><span class="pln">get_i</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="com">// المصرّف يعيد كتابتها كـ</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> </span><span class="typ">ThisPointer</span><span class="pun">::</span><span class="pln">get_i</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">ThisPointer</span><span class="pun">*</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">this</span><span class="pln"> </span><span class="pun">-&gt;</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">void</span><span class="pln"> </span><span class="typ">ThisPointer</span><span class="pun">::</span><span class="pln">set_i</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> ii</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    i </span><span class="pun">=</span><span class="pln"> ii</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="com">// المصرّف يعيد كتابتها كـ</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> </span><span class="typ">ThisPointer</span><span class="pun">::</span><span class="pln">set_i</span><span class="pun">(</span><span class="typ">ThisPointer</span><span class="pun">*</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> ii</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">this</span><span class="pln"> </span><span class="pun">-&gt;</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> ii</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكن استخدام <code>‎this‎</code> بأمان -ضمنيًا أو بشكل صريح- داخل المنشئ للوصول إلى أيّ حقل سبقت تهيئته أو حقل في صنف أب (parent class)، لكن بالمقابل فإن الوصول -ضمنيًا أو بشكل صريح- إلى الحقول التي لم تُهيّأ بعد أو إلى أيّ حقل في الصنف المشتق، يُعد من الممارسات غير الآمنة نظرًا لأنّ الصنف المشتق لم يُهيّأ بعد، وعليه تكون حقُوله ليست لا مهيّأة ولا موجودة. كذلك ليس من الآمن استدعاء الدوال التابعة الوهميّة عبر <code>‎this‎</code> في المُنشئ، ذلك أنّ دوالّ الصنف المشتق لن تُأخذ بالحسبان نظرًا لأنّ الصنف المشتق لم يُنشأ بعد، وعليه فإنّ مُنشئه لم يُحدِّث vtable بعد.
</p>

<p>
	لاحظ أيضًا أن نوع الكائن في المُنشئ هو النوع الذي يُنشئه المُنشئ نفسه، ويبقى هذا صحيحًا حتى لو عُرِّف الكائن على أنه نوع مشتق. انظر المثال التالي حيث يكون كل من <code>‎ctd_good‎</code> و <code>‎ctd_bad‎</code> من نوع <code>‎CtorThisBase‎</code> داخل <code>‎CtorThisBase()‎</code>، ومن نوع <code>‎CtorThis‎</code> داخل <code>‎CtorThis()‎</code>، رغم أنّ نوعهما المعياري هو <code>‎CtorThisDerived‎</code>.
</p>

<p>
	ومع الاستمرار في الاشتقاق من الصنف الأساسي فإنّ النسخة تمرّ تدريجيًا عبر التسلسل الهرمي للصنف حتى تصبح نسخةً مكتملة من النوع المراد لها.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3595_47" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">CtorThisBase</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">short</span><span class="pln"> s</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">CtorThisBase</span><span class="pun">():</span><span class="pln"> s</span><span class="pun">(</span><span class="lit">516</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">CtorThis</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">CtorThisBase</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> i</span><span class="pun">,</span><span class="pln"> j</span><span class="pun">,</span><span class="pln"> k</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="com">// منشئ جيد</span><span class="pln">
        </span><span class="typ">CtorThis</span><span class="pun">():</span><span class="pln"> i</span><span class="pun">(</span><span class="pln">s </span><span class="pun">+</span><span class="pln"> </span><span class="lit">42</span><span class="pun">),</span><span class="pln"> j</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">-&gt;</span><span class="pln">i</span><span class="pun">),</span><span class="pln"> k</span><span class="pun">(</span><span class="pln">j</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

    </span><span class="com">// منشئ سيء</span><span class="pln">
    </span><span class="typ">CtorThis</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> ii</span><span class="pun">):</span><span class="pln"> i</span><span class="pun">(</span><span class="pln">ii</span><span class="pun">),</span><span class="pln"> j</span><span class="pun">(</span><span class="kwd">this</span><span class="pun">-&gt;</span><span class="pln">k</span><span class="pun">),</span><span class="pln"> k</span><span class="pun">(</span><span class="pln">b </span><span class="pun">?</span><span class="pln"> </span><span class="lit">51</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="pun">-</span><span class="lit">51</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        virt_func</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">virtual</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> virt_func</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        i </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">CtorThisDerived</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">CtorThis</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">bool</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">CtorThisDerived</span><span class="pun">():</span><span class="pln"> b</span><span class="pun">(</span><span class="kwd">true</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="typ">CtorThisDerived</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> ii</span><span class="pun">):</span><span class="pln"> </span><span class="typ">CtorThis</span><span class="pun">(</span><span class="pln">ii</span><span class="pun">),</span><span class="pln"> b</span><span class="pun">(</span><span class="kwd">false</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> virt_func</span><span class="pun">()</span><span class="pln"> override </span><span class="pun">{</span><span class="pln">
        k </span><span class="pun">+=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">2</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> i</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="com">// ...</span><span class="pln">

</span><span class="typ">CtorThisDerived</span><span class="pln"> ctd_good</span><span class="pun">;</span><span class="pln">
</span><span class="typ">CtorThisDerived</span><span class="pln"> ctd_bad</span><span class="pun">(</span><span class="lit">3</span><span class="pun">);</span></pre>

<p>
	باعتبار هذه الأصناف والتوابع:
</p>

<ul>
<li>
		<p>
			في المُنشئ الجيّد (انظر الشيفرة)، فإنّه بالنسبة إلى <code>‎ctd_good‎</code>:
		</p>
	</li>
	<li>
		<p>
			يُنشأ <code>‎CtorThisBase‎</code> بالكامل بحلول وقت إدخال المُنشئ <code>‎CtorThis‎</code>، لذا تكون <code>‎s‎</code> في حالة صالحة أثناء تهيئة <code>‎i‎</code>، ومن ثم يمكن الوصول إليها.
		</p>
	</li>
	<li>
		<p>
			تُهيّأ <code>‎i‎</code> قبل الوصول إلى <code>‎j(this-&gt;i)‎</code>، لذلك تكون <code>‎i‎</code> في حالة صالحة أثناء تهيئة <code>‎j‎</code>، ومن ثم يمكن الوصول إليها.
		</p>
	</li>
	<li>
		<p>
			تُهيّأ <code>‎j‎</code> قبل الوصول إلى <code>k(j)‎‎‎</code>، لذلك تكون <code>‎j‎</code> في حالة صالحة أثناء تهيئة <code>‎k‎</code>، ومن ثم يمكن الوصول إليها.
		</p>
	</li>
	<li>
		<p>
			في المُنشئ السيئ، فإنّه بالنسبة إلى <code>‎ctd_bad‎</code>:
		</p>
	</li>
	<li>
		<p>
			تُهيّأ <code>‎k‎</code> بعد الوصول إلى <code>‎j(this-&gt;k)‎</code>، لذلك تكون <code>‎k‎</code> في حالة غير صالحة أثناء تهيئة <code>‎j‎</code> ، ويحدث سلوك غير محدد عند محاولة الوصول إليها.
		</p>
	</li>
	<li>
		<p>
			لا يُنشأ <code>‎CtorThisDerived‎</code> إلّا بعد إنشاء <code>‎CtorThis‎</code>، لذلك تكون <code>‎b‎</code> في حالة غير صالحة أثناء تهيئة <code>‎k‎</code> ، وقد تؤدّي محاولة الوصول إليها إلى سلوك غير محدّد.
		</p>
	</li>
	<li>
		<p>
			يبقى الكائن<code>‎ctd_bad‎</code> من النوع <code>‎CtorThis‎</code> إلى أن يغادر التابع <code>‎CtorThis()‎</code>، ولن يتم تحديثه لاستخدام الجدول الوهمي (vtable) الخاص بالصنف المشتق <code>‎CtorThisDerived‎</code> حتّى التابع <code>‎CtorThisDerived()‎</code>. وعليه تستدعي <code>‎virt_func ()‎</code> التابع <code>‎CtorThis::virt_func()‎</code> بغض النظر إن كان الهدف هو استدعاؤه هو أو استدعاء <code>‎CtorThisDerived::virt_func()‎</code>.
		</p>
	</li>
</ul>
<h3>
	استخدام المؤشر this للوصول إلى بيانات الأعضاء
</h3>

<p>
	لا يعدّ استخدام مؤشّر <code>‎this‎</code> في هذا السياق أمرًا ضروريًا، ولكنه سيجعل الشفرة أوضح للقارئ من خلال الإشارة إلى أنّ دالّة ما أو متغيرًا هو عضو من الصنف. انظر هذا المثال:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3595_49" style="">
<span class="com">// مثال على هذا المؤشّر</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;string&gt;</span><span class="pln">

</span><span class="kwd">using</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">cout</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Class</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">Class</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">~</span><span class="typ">Class</span><span class="pun">();</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> getPrivateNumber</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> private_number </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="typ">Class</span><span class="pun">::</span><span class="typ">Class</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="typ">Class</span><span class="pun">::~</span><span class="typ">Class</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> </span><span class="typ">Class</span><span class="pun">::</span><span class="pln">getPrivateNumber</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">this</span><span class="pln"> </span><span class="pun">-&gt;</span><span class="pln"> private_number</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Class</span><span class="pln"> class_example</span><span class="pun">;</span><span class="pln">
    cout </span><span class="pun">&lt;&lt;</span><span class="pln"> class_example</span><span class="pun">.</span><span class="pln">getPrivateNumber</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكنك مشاهدة مثال حيّ من <a data-ss1617022512="1" href="http://cpp.sh/9flka" rel="external nofollow">هنا</a>.
</p>

<h3>
	استخدام المؤشر this للتفريق بين المعامِلات وبيانات الأعضاء
</h3>

<p>
	هذه استراتيجية مفيدة لتمييز البيانات العضويّة عن المعاملات، لنأخذ مثالًا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3595_51" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;string&gt;</span><span class="pln">

</span><span class="kwd">using</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">cout</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">

</span><span class="com">/*
 * @class Dog
 *   @member name
 *       Dog's name
 *   @function bark
 *       Dog Barks!
 *   @function getName
 *       To Get Private
 *       Name Variable
 */</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Dog</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">Dog</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string name</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">~</span><span class="typ">Dog</span><span class="pun">();</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> bark</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">string getName</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">string name</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="typ">Dog</span><span class="pun">::</span><span class="typ">Dog</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string name</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span></pre>

<p>
	<code>this-&gt;name</code> هو متغير الاسم من صنف <code>dog</code>، ويكون <code>name</code> من معامِل الدالة. نتابع:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3595_53" style="">
<span class="pln">    </span><span class="kwd">this</span><span class="pln"> </span><span class="pun">-&gt;</span><span class="pln"> name </span><span class="pun">=</span><span class="pln"> name</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="typ">Dog</span><span class="pun">::~</span><span class="typ">Dog</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">

</span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Dog</span><span class="pun">::</span><span class="pln">bark</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"BARK"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

std</span><span class="pun">::</span><span class="pln">string </span><span class="typ">Dog</span><span class="pun">::</span><span class="pln">getName</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">this</span><span class="pln"> </span><span class="pun">-&gt;</span><span class="pln"> name</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Dog</span><span class="pln"> dog</span><span class="pun">(</span><span class="str">"Max"</span><span class="pun">);</span><span class="pln">
    cout </span><span class="pun">&lt;&lt;</span><span class="pln"> dog</span><span class="pun">.</span><span class="pln">getName</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">
    dog</span><span class="pun">.</span><span class="pln">bark</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	كما ترى هنا في المنشئ فقد نفذنا ما يلي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3595_55" style="">
<span class="kwd">this</span><span class="pun">-&gt;</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> name</span><span class="pun">;</span></pre>

<p>
	لاحظ أننا أسنَدنا المُعاملَ <code>name</code> إلى اسم المتغير الخاصّ من الصنف ‏‏Dog‏‏‏‏‏‏ (<code>this-&gt;name</code>)‏‏‏‏. انظر <a data-ss1617022512="1" href="http://cpp.sh/75r7" rel="external nofollow">هنا</a> لرؤية تطبيق حي للشيفرة أعلاه.
</p>

<h3>
	المؤهلات الخاصة بالمؤشر this ‏‏(this Pointer CV-Qualiﬁers)
</h3>

<p>
	يمكن للمؤشّر <code>‎this‎</code> أن يؤهَّل (cv-qualiﬁed) - أي تُحدَّد طبيعته، أهو ثابت أم متغير - مثل أيّ مؤشّر آخر. لكن بما أن المعامل <code>‎this‎</code> لا يُدرَج في قائمة المعاملات، فيجب استخدام صيغة خاصة بالمؤشّر <code>this</code>؛ لذا تُدرَج المؤهّلات (cv-qualifiers) بعد قائمة المعاملات، وقبل متن الدالة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3595_57" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">ThisCVQ</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> no_qualifier</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">            </span><span class="com">// "this" is: ThisCVQ*</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> c_qualifier</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">        </span><span class="com">// "this" is: const ThisCVQ*</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> v_qualifier</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">volatile</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">        </span><span class="com">// "this" is: volatile ThisCVQ*</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> cv_qualifier</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">volatile</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">    </span><span class="com">// "this" is: const volatile ThisCVQ*</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	بما أن <code>‎this‎</code> معامِل فيمكن زيادة تحميل (overload) دالّة على أساس مؤهِّلات <code>‎this‎</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3595_59" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">CVOverload</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> func</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> func</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">33</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> func</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">volatile</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">333</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> func</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">volatile</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">3333</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	لن تكون الدالّة قادرة على الكتابة في متغيرات الأعضاء من خلال <code>this</code> عندما يكون ثابتًا (<code>‎const‎</code>) (بما في ذلك <code>‎const volatile‎</code>)، سواء ضمنيًا أو بشكل صريح، والاستثناء الوحيد لهذا هو متغيرات الأعضاء القابلة للتغيير (<code>‎mutable‎</code>)، والتي يمكن أن تُكتب بغض النظر عن ثبوتيّتها. لهذا تُستخدم <code>‎const‎</code> للإشارة إلى أنّ التابع لا يغيِّر الحالة المنطقية للكائن -الطريقة التي يظهر بها الكائن للعالم الخارجي- حتى لو عدّل الحالة المادية، وهي الطريقة التي يظهر بها الكائن داخليًا.
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		<strong>الحالة المنطقية هي الطريقة التي يظهر بها الكائن للمُراقبين الخارجيين. ولا ترتبط بشكل مباشر بالحالة المادية، في الواقع، قد لا تُخزّن كحالة مادية. وطالما أنّ المراقبين الخارجيين لا يروْن أيّ تغييرات، فإنّ الحالة المنطقية ستُعدُّ ثابتة، حتى لو قُلِبتَ كل بتّة في الكائن. </strong>
	</p>

	<p>
		<strong>الحالة المادّية، والمعروفة أيضًا باسم الحالة البتّيّة (bitwise state)، هي الكيفية التي يُخزّن بها الكائن في الذاكرة. إنّها تمثل جسد الكائن (الوحدات والأصفار الخام التي تشكل بياناته). يكون الكائن ثابتًا ماديًّا (physically constant) ما دام تمثيله في الذاكرة ثابتًا لا يتغيّر. </strong>
	</p>
</blockquote>

<p>
	لاحظ أنّ لغة C++‎ تبني الثباتيّة (constness) على الحالة المنطقية وليس الحالة المادية.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3595_61" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">DoSomethingComplexAndOrExpensive</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">mutable</span><span class="pln"> </span><span class="typ">ResultType</span><span class="pln"> cached_result</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">mutable</span><span class="pln"> </span><span class="kwd">bool</span><span class="pln"> state_changed</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">ResultType</span><span class="pln"> calculate_result</span><span class="pun">();</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> modify_somehow</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Param</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> p</span><span class="pun">);</span><span class="pln">
    </span><span class="com">// ...</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">DoSomethingComplexAndOrExpensive</span><span class="pun">(</span><span class="typ">Param</span><span class="pln"> p</span><span class="pun">):</span><span class="pln"> state_changed</span><span class="pun">(</span><span class="kwd">true</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            modify_somehow</span><span class="pun">(</span><span class="pln">p</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> change_state</span><span class="pun">(</span><span class="typ">Param</span><span class="pln"> p</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        modify_somehow</span><span class="pun">(</span><span class="pln">p</span><span class="pun">);</span><span class="pln">
        state_changed </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="com">// إعادة نتيجة تحتاج إلى حسابات معقدة</span><span class="pln">
	</span><span class="com">// يُحدَّد كثابت بما أنه لا يوجد سبب لتعديل الحالة المنطقية.</span><span class="pln">
    </span><span class="typ">ResultType</span><span class="pln"> get_result</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">ResultType</span><span class="pln"> </span><span class="typ">DoSomethingComplexAndOrExpensive</span><span class="pun">::</span><span class="pln">get_result</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span></pre>

<p>
	يمكن تعديل <code>cached_result</code> و <code>state_changed</code> حتى مع مؤشر <code>const</code> ثابت، ورغم ان الدالة لن تغير الحالة المنطقية إلا أنها تعدّل الحالة المادية بتخزين النتيجة مؤقتًا كي لا تحتاج إلى إعادة حسابها في كل مرة تُستدعى الدالة فيها. ترى هذا واضحًا من قابلية كل من <code>cached_result</code> و <code>state_changed</code> للتغيير. انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3595_63" style="">
<span class="pln">    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">state_changed</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        cached_result </span><span class="pun">=</span><span class="pln"> calculate_result</span><span class="pun">();</span><span class="pln">
        state_changed </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> cached_result</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ورغم أنك تستطيع استخدام <code>‎const_cast‎</code> مع <code>‎this‎</code> لجعله غير مؤهّل (non-cv-qualiﬁed)، إلا أنّه يوصى بتجنّب ذلك، ويُنصح باستخدام <code>‎mutable‎</code> بدلًا منه. كذلك قد تُحدث الكائنات غير المؤهّلة (<code>‎const_cast‎</code>) سلوكًا غير مُحدّدٍ عند استخدامها على كائن ثابت (<code>‎const‎</code>)، على عكس <code>‎mutable‎</code> التي صُمِّمت لتكون آمنة للاستخدام.
</p>

<p>
	هناك استثناء لهذه القاعدة، وهو تعريف توابع وصول غير مؤهّلة (non-cv-qualiﬁed accessors) عبر توابع وصول ثابتة (<code>‎const‎</code>)، نظرًا لأنّ ذلك يضمن أنّ الكائن لن يكون ثابتًا إذا استُدعِيت النسخة غير المؤهّلة، لذلك لا توجد مخاطرة هنا.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3595_65" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">CVAccessor</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> arr</span><span class="pun">[</span><span class="lit">5</span><span class="pun">];</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> get_arr_element</span><span class="pun">(</span><span class="typ">size_t</span><span class="pln"> i</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> arr</span><span class="pun">[</span><span class="pln">i</span><span class="pun">];</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> get_arr_element</span><span class="pun">(</span><span class="typ">size_t</span><span class="pln"> i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">const_cast</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const_cast</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">
            </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">CVAccessor</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">this</span><span class="pun">)</span><span class="pln"> </span><span class="pun">-&gt;</span><span class="pln"> get_arr_element</span><span class="pun">(</span><span class="pln">i</span><span class="pun">));</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	هذا يمنع التكرار غير الضروري للشيفرة.
</p>

<p>
	وكما في المؤشّرات العادية، فإن كان <code>‎this‎</code> متغيّرًا <code>‎volatile‎</code> -بما في ذلك <code>‎const volatile‎</code>- فإنه سيُحمَّل من الذاكرة في كل مرة يتم الوصول إليه بدلاً من تخزينه مؤقتًا، ومن ثم فإنّ تأثيره على سرعة البرنامج يشبه تأُثير التصريح عن مؤشّر متغيّر <code>‎volatile‎</code>، لذا يجب توخّي الحذر.
</p>

<p>
	لاحظ أنّه إذا كانت نسخة ما مؤهّلةً ثباتيًّا، فإنّ الدوال التابعة الوحيدة التي يُسمح لها بالوصول إليها هي التي يحمل المؤشّر <code>‎this‎</code> الخاص بها نفس التأهيل للنسخة ذاتها على الأقل:
</p>

<ul>
<li>
		يمكن للنُّسخ غير المؤهّلة أن تصل إلى كل الدوال التابعة.
	</li>
	<li>
		يمكن للنسخ الثابتة (<code>‎const‎</code>) الوصول إلى الدوال ذات تأهيل <code>‎const‎</code> و <code>‎const ‎volatile‎</code>.
	</li>
	<li>
		يمكن للنسخ المتغيّرة (<code>‎volatile‎</code>) الوصول إلى الدوالّ ذات تأهيل <code>‎volatile‎</code> و <code>‎const‎ ‎volatile‎</code>.
	</li>
	<li>
		يمكن للنسخ ذات التأهيل <code>‎const ‎volatile‎</code> الوصول إلى الدوالّ ذات تأهيل <code>‎const ‎volatile‎</code>.
	</li>
</ul>
<p>
	هذا أحد المبادئ الأساسية للثباتيّة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3595_67" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">CVAccess</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> func</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> func_c</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> func_v</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">volatile</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> func_cv</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">volatile</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">CVAccess</span><span class="pln"> cva</span><span class="pun">;</span><span class="pln">
cva</span><span class="pun">.</span><span class="pln">func</span><span class="pun">();</span><span class="pln"> </span><span class="com">// جيد</span><span class="pln">
cva</span><span class="pun">.</span><span class="pln">func_c</span><span class="pun">();</span><span class="pln"> </span><span class="com">// جيد</span><span class="pln">
cva</span><span class="pun">.</span><span class="pln">func_v</span><span class="pun">();</span><span class="pln"> </span><span class="com">// جيد</span><span class="pln">
cva</span><span class="pun">.</span><span class="pln">func_cv</span><span class="pun">();</span><span class="pln"> </span><span class="com">// جيد</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">CVAccess</span><span class="pln"> c_cva</span><span class="pun">;</span><span class="pln">
c_cva</span><span class="pun">.</span><span class="pln">func</span><span class="pun">();</span><span class="pln"> </span><span class="com">// خطأ</span><span class="pln">
c_cva</span><span class="pun">.</span><span class="pln">func_c</span><span class="pun">();</span><span class="pln"> </span><span class="com">// جيد</span><span class="pln">
c_cva</span><span class="pun">.</span><span class="pln">func_v</span><span class="pun">();</span><span class="pln"> </span><span class="com">// خطأ</span><span class="pln">
c_cva</span><span class="pun">.</span><span class="pln">func_cv</span><span class="pun">();</span><span class="pln"> </span><span class="com">// جيد</span><span class="pln">
</span><span class="kwd">volatile</span><span class="pln"> </span><span class="typ">CVAccess</span><span class="pln"> v_cva</span><span class="pun">;</span><span class="pln">
v_cva</span><span class="pun">.</span><span class="pln">func</span><span class="pun">();</span><span class="pln"> </span><span class="com">// خطأ</span><span class="pln">
v_cva</span><span class="pun">.</span><span class="pln">func_c</span><span class="pun">();</span><span class="pln"> </span><span class="com">// خطأ</span><span class="pln">
v_cva</span><span class="pun">.</span><span class="pln">func_v</span><span class="pun">();</span><span class="pln"> </span><span class="com">// جيد</span><span class="pln">
v_cva</span><span class="pun">.</span><span class="pln">func_cv</span><span class="pun">();</span><span class="pln"> </span><span class="com">// جيد</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">volatile</span><span class="pln"> </span><span class="typ">CVAccess</span><span class="pln"> cv_cva</span><span class="pun">;</span><span class="pln">
cv_cva</span><span class="pun">.</span><span class="pln">func</span><span class="pun">();</span><span class="pln"> </span><span class="com">// خطأ</span><span class="pln">
cv_cva</span><span class="pun">.</span><span class="pln">func_c</span><span class="pun">();</span><span class="pln"> </span><span class="com">// خطأ</span><span class="pln">
cv_cva</span><span class="pun">.</span><span class="pln">func_v</span><span class="pun">();</span><span class="pln"> </span><span class="com">// خطأ</span><span class="pln">
cv_cva</span><span class="pun">.</span><span class="pln">func_cv</span><span class="pun">();</span><span class="pln"> </span><span class="com">// جيد</span></pre>

<h3>
	مؤهلات مؤشر this المرجعية
</h3>

<p>
	<strong>الإصدار C++‎ 11 </strong>
</p>

<p>
	يمكننا تطبيق المؤهّلات المرجعِيّة (ref-qualiﬁers) على <code>‎*this‎</code> على نحو مماثل لمؤهّلات <code>‎this‎</code> الثباتيّة، وتُستخدم المؤهّلات المرجعيّة للاختيار بين دلالات المرجع العادية والقيميّة اليمينيّة، ممّا يسمح للمُصرِّف أن يستخدم دلالات النسخ (copy) أو النقل (move) وفقًا لأيّهما أنسب، وتُطبَّق على <code>‎*this‎</code> بدلاً من <code>‎this‎</code>.
</p>

<p>
	وتجدر الإشارة أنه رغم استخدام المؤهِّلات المرجعية لصيغة المراجع (reference syntax) فلا يزال <code>‎this‎</code> مؤشّرًا، كذلك لاحظ أنّ المؤهّلات المرجِعيّة لا تغيّر في الواقع نوع <code>‎*this‎</code>، بيْد أنه من الأسهل وصفها وفهمها من هذا المنظور.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3595_69" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">RefQualifiers</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">string s</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">RefQualifiers</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&amp;</span><span class="pln"> ss </span><span class="pun">=</span><span class="pln"> </span><span class="str">"The nameless one."</span><span class="pun">):</span><span class="pln"> s</span><span class="pun">(</span><span class="pln">ss</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="com">// نسخة عادية</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> func</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Accessed on normal instance "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> s </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="com">// قيمة يمينية</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> func</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Accessed on temporary instance "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> s </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&amp;</span><span class="pln"> still_a_pointer</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">this</span><span class="pln"> </span><span class="pun">-&gt;</span><span class="pln"> s</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&amp;</span><span class="pln"> still_a_pointer</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">this</span><span class="pln"> </span><span class="pun">-&gt;</span><span class="pln"> s </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Bob"</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">this</span><span class="pln"> </span><span class="pun">-&gt;</span><span class="pln"> s</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="com">// ...</span><span class="pln">
</span><span class="typ">RefQualifiers</span><span class="pln"> rf</span><span class="pun">(</span><span class="str">"Fred"</span><span class="pun">);</span><span class="pln">
rf</span><span class="pun">.</span><span class="pln">func</span><span class="pun">();</span><span class="pln"> </span><span class="com">// الخرج:  Accessed on normal instance Fred</span><span class="pln">
</span><span class="typ">RefQualifiers</span><span class="pln"> </span><span class="pun">{}.</span><span class="pln">func</span><span class="pun">();</span><span class="pln"> </span><span class="com">// الخرج:  Accessed on temporary instance The nameless one</span></pre>

<p>
	لا يمكن زيادة تحميل دالة تابعة مع مؤهّل مرجعي مرة وبدونه مرّة أخرى، بل يختار المبرمج أحد الأمرَين. الجميل في الأمر أنه يمكن استخدام المؤهّلات الثباتيّة مع المؤهلات المرجعيّة، مما يسمح باتباع قواعد الثباتيّة. انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3595_71" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">RefCV</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> func</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> func</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> func</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> func</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> func</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">volatile</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> func</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">volatile</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> func</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">volatile</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> func</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">volatile</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	هذا الدرس جزء من <a data-ss1617022512="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة دروس عن C++‎</a>.
</p>

<p>
	ترجمة -بتصرّف- للفصول 30 وحتى 32 من كتاب <a data-ss1617022512="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">912</guid><pubDate>Sun, 05 Jul 2020 18:01:00 +0000</pubDate></item><item><title>&#x645;&#x627; &#x628;&#x64A;&#x646; &#x627;&#x644;&#x646;&#x633;&#x62E; (Copying) &#x648;&#x627;&#x644;&#x625;&#x633;&#x646;&#x627;&#x62F; (Assignment) &#x641;&#x64A; Cpp</title><link>https://academy.hsoub.com/programming/cpp/%D9%85%D8%A7-%D8%A8%D9%8A%D9%86-%D8%A7%D9%84%D9%86%D8%B3%D8%AE-copying-%D9%88%D8%A7%D9%84%D8%A5%D8%B3%D9%86%D8%A7%D8%AF-assignment-%D9%81%D9%8A-cpp-r911/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_06/18.jpg.cf44b91e8b7a1b5d6a7ef954c46102b0.jpg" /></p>

<h2>
	عامل الإسناد (Assignment Operator)
</h2>

<p>
	يُستخدم "عامل الإسناد" لإحلال بيانات كائن ما مكان بيانات كائن موجود سلفًا (مُهيّأ مُسبقًا). انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_468_7" style="">
<span class="com">// عامل الإسناد</span><span class="pln">
</span><span class="pun">#</span><span class="pln">include </span><span class="pun">&lt;</span><span class="pln">iostream</span><span class="pun">&gt;</span><span class="pln">
</span><span class="pun">#</span><span class="pln">include </span><span class="pun">&lt;</span><span class="pln">string</span><span class="pun">&gt;</span><span class="pln">

using std</span><span class="pun">::</span><span class="pln">cout</span><span class="pun">;</span><span class="pln">
using std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">Foo</span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> data</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">this</span><span class="pln"> </span><span class="pun">-&gt;</span><span class="pln"> data </span><span class="pun">=</span><span class="pln"> data</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}~</span><span class="typ">Foo</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
    </span><span class="typ">Foo</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> rhs</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        data </span><span class="pun">=</span><span class="pln"> rhs</span><span class="pun">.</span><span class="pln">data</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="kwd">this</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">int</span><span class="pln"> data</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Foo</span><span class="pln"> foo</span><span class="pun">(</span><span class="lit">2</span><span class="pun">);</span><span class="pln"> </span><span class="com">// Foo(int data) استدعاء</span><span class="pln">
    </span><span class="typ">Foo</span><span class="pln"> foo2</span><span class="pun">(</span><span class="lit">42</span><span class="pun">);</span><span class="pln">
    foo </span><span class="pun">=</span><span class="pln"> foo2</span><span class="pun">;</span><span class="pln"> </span><span class="com">// استدعاء عامل الإسناد</span><span class="pln">
    cout </span><span class="pun">&lt;&lt;</span><span class="pln"> foo</span><span class="pun">.</span><span class="pln">data </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln"> </span><span class="com">//  42</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تستطيع هنا أن تلاحظ أنّنا استدعينا عامل الإسناد بعد أن هيّئنا الكائن <code>‎foo‎</code>، ثم نسند بعد ذلك <code>‎foo2‎</code> إلى <code>‎foo‎</code>، وتكون جميع التغييرات التي ستحدث عند استدعاء عامل الإسناد مُعرّفة في الدالة <code>‎operator=‎</code>. انظر <a data-ss1617022510="1" href="http://cpp.sh/3qtbm" rel="external nofollow">هذا المثال الحي</a>.
</p>

<h2>
	منشئ النسخ (Copy Constructor)
</h2>

<p>
	مُنشئ النَّسخ من ناحية أخرى على النقيض من عامل الإسناد، إذ يُستخدم لتهيئة كائن غير موجود مسبقًا (أو غير مهيّأ مسبقًا)، هذا يعني أنه ينسخ جميع البيانات من الكائن الذي يُسند إليه، دون تهيئة الكائن الذي يتم نسخه بالفعل. دعنا نلقي نظرة على نفس الشيفرة أعلاه ولكن مع استخدام مُنشئ النسخ بدلًا من منشئ الإسناد:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_468_9" style="">
<span class="com">//منشئ النسخ     </span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;string&gt;</span><span class="pln">

</span><span class="kwd">using</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">cout</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">Foo</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> data</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">this</span><span class="pln"> </span><span class="pun">-&gt;</span><span class="pln"> data </span><span class="pun">=</span><span class="pln"> data</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}~</span><span class="typ">Foo</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
    </span><span class="typ">Foo</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> rhs</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        data </span><span class="pun">=</span><span class="pln"> rhs</span><span class="pun">.</span><span class="pln">data</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> data</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Foo</span><span class="pln"> foo</span><span class="pun">(</span><span class="lit">2</span><span class="pun">);</span><span class="pln"> </span><span class="com">//Foo(int data) استدعاء</span><span class="pln">
    </span><span class="typ">Foo</span><span class="pln"> foo2 </span><span class="pun">=</span><span class="pln"> foo</span><span class="pun">;</span><span class="pln"> </span><span class="com">// استدعاء منشئ النسخ</span><span class="pln">
    cout </span><span class="pun">&lt;&lt;</span><span class="pln"> foo2</span><span class="pun">.</span><span class="pln">data </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	في التعبير <code>‎Foo foo2 = foo;‎</code> في الدالّة الرئيسية، أسندنا الكائن على الفور قبل تهيئته، ما يعني أنه مُنشِئ نسخ، لكن لاحظ أنّنا لم نكن بحاجة إلى تمرير المعامل (int) للكائن <code>‎foo2‎</code>، لأننا سحبنا البيانات السابقة تلقائيًا من الكائن <code>foo</code>. انظر <a data-ss1617022510="1" href="http://cpp.sh/5iu7" rel="external nofollow">هذا المثال الحي</a> للمزيد.
</p>

<h2>
	مُنشئ النسخ مقابل منشئ الإسناد
</h2>

<p>
	بعد هذه النظرة السريعة على مفهومي مُنشئ النسخ ومنشئ الإسناد ورؤية مثال عن عمل كلٍ منهما، سننظر الآن كيف يمكن استخدامهما معًا في نفس الشيفرة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_468_11" style="">
<span class="com">// منشئ النسخ مقابل منشئ الإسناد</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;string&gt;</span><span class="pln">

</span><span class="kwd">using</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">cout</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">Foo</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> data</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">this</span><span class="pln"> </span><span class="pun">-&gt;</span><span class="pln"> data </span><span class="pun">=</span><span class="pln"> data</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}~</span><span class="typ">Foo</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
    </span><span class="typ">Foo</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> rhs</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        data </span><span class="pun">=</span><span class="pln"> rhs</span><span class="pun">.</span><span class="pln">data</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="typ">Foo</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> rhs</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        data </span><span class="pun">=</span><span class="pln"> rhs</span><span class="pun">.</span><span class="pln">data</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="kwd">this</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> data</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Foo</span><span class="pln"> foo</span><span class="pun">(</span><span class="lit">2</span><span class="pun">);</span><span class="pln"> </span><span class="com">//Foo(int data) استدعاء المنشئ العادي</span><span class="pln">
    </span><span class="typ">Foo</span><span class="pln"> foo2 </span><span class="pun">=</span><span class="pln"> foo</span><span class="pun">;</span><span class="pln"> </span><span class="com">// استدعاء منشئ النسخ</span><span class="pln">
    cout </span><span class="pun">&lt;&lt;</span><span class="pln"> foo2</span><span class="pun">.</span><span class="pln">data </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">Foo</span><span class="pln"> foo3</span><span class="pun">(</span><span class="lit">42</span><span class="pun">);</span><span class="pln">
    foo3 </span><span class="pun">=</span><span class="pln"> foo</span><span class="pun">;</span><span class="pln"> </span><span class="com">// استدعاء منشئ الإسناد</span><span class="pln">
    cout </span><span class="pun">&lt;&lt;</span><span class="pln"> foo3</span><span class="pun">.</span><span class="pln">data </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	الناتج:
</p>

<pre class="ipsCode">
2
2
</pre>

<p>
	لقد استدعينا في البداية مُنشئ النسخ عن طريق التعبير <code>‎Foo foo2 = foo;‎</code> لأننا لم نهيّئه من قبل، ثم استدعينا بعد ذلك عامل الإسناد على <code>foo3</code> لأنه سبقت تهيئته (<code>‎foo3=foo‎</code>).
</p>

<p>
	هذا الدرس جزء من <a data-ss1617022510="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة دروس عن C++‎</a>.
</p>

<p>
	ترجمة -بتصرّف- للفصل Chapter 29: Copying vs Assignment من كتاب <a data-ss1617022510="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">911</guid><pubDate>Fri, 03 Jul 2020 18:06:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x645;&#x631;&#x627;&#x62C;&#x639; (References) &#x648;&#x627;&#x644;&#x62F;&#x644;&#x627;&#x644;&#x627;&#x62A; &#x627;&#x644;&#x642;&#x64A;&#x645;&#x64A;&#x629; &#x648;&#x627;&#x644;&#x645;&#x631;&#x62C;&#x639;&#x64A;&#x629; &#x641;&#x64A; Cpp</title><link>https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D9%85%D8%B1%D8%A7%D8%AC%D8%B9-references-%D9%88%D8%A7%D9%84%D8%AF%D9%84%D8%A7%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D9%82%D9%8A%D9%85%D9%8A%D8%A9-%D9%88%D8%A7%D9%84%D9%85%D8%B1%D8%AC%D8%B9%D9%8A%D8%A9-%D9%81%D9%8A-cpp-r910/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_06/17.jpg.f4bea660d125a3c4583a2a2d7bd244f7.jpg" /></p>

<p>
	تتشابه المراجع في سلوكها وتختلف عن المؤشّرات الثابتة (const pointers)، وتُعرَّف عن طريق إتباع الرمز <code>‎&amp;‎</code> ‏‏(ampersand) باسم نوع.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4077_7" style="">
<span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">refi </span><span class="pun">=</span><span class="pln"> i</span><span class="pun">;</span></pre>

<p>
	يمثّل <code>‎refi‎</code> في المثال أعلاه مرجعًا مربوطًا (reference bound) إلى <code>‎i‎</code>، كذلك فإن المراجع تُجرِّد مفهوم المؤشرات وتتصرف كاسم للكائن المُشار إليه:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4077_9" style="">
<span class="pln">refi </span><span class="pun">=</span><span class="pln"> </span><span class="lit">20</span><span class="pun">;</span><span class="pln"> </span><span class="com">// i = 20;</span></pre>

<p>
	يمكنك أيضًا تعريف عدة مراجع في تعريف واحد:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4077_11" style="">
<span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pun">,</span><span class="pln"> j </span><span class="pun">=</span><span class="pln"> </span><span class="lit">20</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">refi </span><span class="pun">=</span><span class="pln"> i</span><span class="pun">,</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">refj </span><span class="pun">=</span><span class="pln"> j</span><span class="pun">;</span><span class="pln">
</span><span class="com">// خطأ شائع</span><span class="pln">
</span><span class="com">// int&amp; refi = i, k = j;</span></pre>

<p>
	في المثال السابق ستكون <code>refi</code> من نوع <code>‎&amp;int</code> رغم أن <code>k</code> ستكون من نوع <code>int</code> وليس <code>‎&amp;int</code>. أيضًا، يجب تهيئة المراجع بشكل صحيح في التعريف، ولن يمكنك تعديلها بعد ذلك. انظر المثال التالي حيث تؤدي الشيفرة إلى خطأ في التصريف لأن الإعلان عن متغير المرجع <code>i</code> يتطلب مهيِّئًا.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4077_13" style="">
<span class="typ">int</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">i</span><span class="pun">;</span><span class="pln"> </span></pre>

<p>
	كذلك لا يمكن ربط مرجع إلى المؤشر الفارغ <code>‎nullptr‎</code> مباشرة، على عكس المؤشرات، انظر المثال التالي حيث نحصل على خطأ لاستحالة ربط مرجع غير ثابت لقيمة يسارية من نوع <code>int</code> بعنصر من نوع <code>nullptr_t</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4077_15" style="">
<span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="kwd">const</span><span class="pln"> ptri </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">nullptr</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">refi </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">nullptr</span><span class="pun">;</span><span class="pln"> </span></pre>

<h2>
	الدلالات القيميّة والمرجعية
</h2>

<p>
	يكون لنوع ما دلالة قيميّة (value semantics) إذا كانت حالة الكائن القابلة للمُلاحظة مختلفة وظيفيًا عن جميع الكائنات الأخرى من ذلك النوع. هذا يعني أنه إذا نسخت أحد الكائنات فستحصل على كائن جديد، ولن تؤثر التعديلات على الكائن الجديد بأي شكل من الأشكال على الكائن القديم. معظم أنواع C++‎ الأساسية لها دلالات قيميّة، انظر المثال التالي حيث تطبع <code>std::cout &lt;&lt; i</code> الرقم 5 لأن <code>i</code> لم تتأثر بالتغييرات التي أجريت على <code>j</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4077_17" style="">
<span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> j </span><span class="pun">=</span><span class="pln"> i</span><span class="pun">;</span><span class="pln"> </span><span class="com">// منسوخ</span><span class="pln">
j </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">20</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> i</span><span class="pun">;</span><span class="pln"> </span><span class="com">// j لم تتأثر بالتغييرات التي أجريناها على i تطبع 5، لأنّ </span></pre>

<p>
	معظم الأنواع المُعرّفة في المكتبة القياسية لها دلالة قيميّة أيضًا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4077_19" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v1</span><span class="pun">(</span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">12</span><span class="pun">);</span><span class="pln"> </span><span class="com">// مصفوفة خماسية كل قيمها تساوي 12</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v2 </span><span class="pun">=</span><span class="pln"> v1</span><span class="pun">;</span><span class="pln"> </span><span class="com">// نسخ المتجهة</span><span class="pln">
v2</span><span class="pun">[</span><span class="lit">3</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">6</span><span class="pun">;</span><span class="pln"> v2</span><span class="pun">[</span><span class="lit">4</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">9</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> v1</span><span class="pun">[</span><span class="lit">3</span><span class="pun">]</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> v1</span><span class="pun">[</span><span class="lit">4</span><span class="pun">];</span><span class="pln"> </span><span class="com">//  "12 12" </span></pre>

<p>
	يقال إنّ نوعًا ما له دلالة مرجعيّة (reference semantics) إذا تشاركت نُسخ ذلك النوع حالتها القابلة للملاحظة مع كائنات أخرى (خارجية)، بحيث يؤدي تعديل كائن واحد إلى تغيير حالة كائن آخر، وللمؤشّرات دلالة قيميّة في C++‎ فيما يتعلّق بهويّة الكائن الذي تشير إليه، ولها دلالة مرجعيّة فيما يتعلق بحالة الكائن الذي تشير إليه:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4077_21" style="">
<span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="pln">pi </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">int</span><span class="pun">(</span><span class="lit">4</span><span class="pun">);</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="pln">pi2 </span><span class="pun">=</span><span class="pln"> pi</span><span class="pun">;</span><span class="pln">
pi </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">int</span><span class="pun">(</span><span class="lit">16</span><span class="pun">);</span><span class="pln">
assert</span><span class="pun">(</span><span class="pln">pi2 </span><span class="pun">!=</span><span class="pln"> pi</span><span class="pun">);</span><span class="pln"> </span><span class="com">// تتحقق دائما</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="pln">pj </span><span class="pun">=</span><span class="pln"> pi</span><span class="pun">;</span><span class="pln">
</span><span class="pun">*</span><span class="pln">pj </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">*</span><span class="pln">pi</span><span class="pun">;</span><span class="pln"> </span><span class="com">// يشيران إلى نفس العنصر pj و pi تطبع 9 لأن </span></pre>

<p>
	كذلك فإن مراجع C++‎ لها دلالة مرجعية.
</p>

<h2>
	النسخ العميق ودعم النقل
</h2>

<p>
	إذا كنت تريد أن تجعل لنوع ما دلالة قيميّة وكان ذلك النوع يحتاج إلى تخزين الكائنات الديناميكية (dynamically allocated)، فسيحتاج ذلك النوع عند عمليات النسخ إلى تخصيص (allocate) نسخ جديدة من تلك الكائنات، كما يجب أن يفعل ذلك أيضًا عند تعيين النسخة (copy assignment). يُسمّى هذا النوع من النسخ "النسخ العميق" (deep copy) إذ أنّه يحوّل الدلالة المرجعية إلى دلالة قيمية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4077_23" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Inner</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> NUM_INNER </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Value</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">Inner</span><span class="pln"> </span><span class="pun">*</span><span class="pln">array_</span><span class="pun">;</span><span class="pln"> </span><span class="com">// في العادة يكون لها دلالة مرجعية</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">Value</span><span class="pun">():</span><span class="pln"> array_</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Inner</span><span class="pun">[</span><span class="pln">NUM_INNER</span><span class="pun">])</span><span class="pln"> </span><span class="pun">{}~</span><span class="typ">Value</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">delete</span><span class="pun">[]</span><span class="pln"> array_</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="typ">Value</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Value</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">val</span><span class="pun">):</span><span class="pln"> array_</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Inner</span><span class="pun">[</span><span class="pln">NUM_INNER</span><span class="pun">])</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> NUM_INNER</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">i</span><span class="pun">)</span><span class="pln">
            array_</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> val</span><span class="pun">.</span><span class="pln">array_</span><span class="pun">[</span><span class="pln">i</span><span class="pun">];</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="typ">Value</span><span class="pln"> </span><span class="pun">&amp;</span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Value</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">val</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> NUM_INNER</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">i</span><span class="pun">)</span><span class="pln">
            array_</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> val</span><span class="pun">.</span><span class="pln">array_</span><span class="pun">[</span><span class="pln">i</span><span class="pun">];</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="kwd">this</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	تسمح الدلالة النقليّة (Move semantics) لنوع مثل الصنف <code>‎Value‎</code> أن يتجنب نسخ بياناته المرجعية (referenced data)، وإذا استعمل المُستخدم القيمة بطريقة تؤدي إلى نقلٍ (move) فيمكن أن يؤدّي ذلك إلى تفريغ الكائن المنسوخ من البيانات التي أشار إليها:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4077_25" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Inner</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">constexpr</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> NUM_INNER </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Value</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">Inner</span><span class="pln"> </span><span class="pun">*</span><span class="pln">array_</span><span class="pun">;</span><span class="pln"> </span><span class="com">// في العادة يكون لها دلالة مرجعية</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">Value</span><span class="pun">():</span><span class="pln"> array_</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Inner</span><span class="pun">[</span><span class="pln">NUM_INNER</span><span class="pun">])</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
        </span><span class="com">// nullptr يُسمح بالنقل حتى لو أعادت</span><span class="pln">
        </span><span class="pun">~</span><span class="typ">Value</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">delete</span><span class="pun">[]</span><span class="pln"> array_</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="typ">Value</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Value</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">val</span><span class="pun">):</span><span class="pln"> array_</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Inner</span><span class="pun">[</span><span class="pln">NUM_INNER</span><span class="pun">])</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> NUM_INNER</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">i</span><span class="pun">)</span><span class="pln">
            array_</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> val</span><span class="pun">.</span><span class="pln">array_</span><span class="pun">[</span><span class="pln">i</span><span class="pun">];</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="typ">Value</span><span class="pln"> </span><span class="pun">&amp;</span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Value</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">val</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> NUM_INNER</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">i</span><span class="pun">)</span><span class="pln">
            array_</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> val</span><span class="pun">.</span><span class="pln">array_</span><span class="pun">[</span><span class="pln">i</span><span class="pun">];</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="kwd">this</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="com">// النقل يعني لا تخصيص للذاكرة</span><span class="pln">
    </span><span class="com">// لا يمكن إطلاق اعتراض</span><span class="pln">
    </span><span class="typ">Value</span><span class="pun">(</span><span class="typ">Value</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln">val</span><span class="pun">)</span><span class="pln"> noexcept</span><span class="pun">:</span><span class="pln"> array_</span><span class="pun">(</span><span class="pln">val</span><span class="pun">.</span><span class="pln">array_</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// لقد أخذنا القيمة القديمة</span><span class="pln">
        val</span><span class="pun">.</span><span class="pln">array_ </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">nullptr</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="com">// لا يمكن رفع اعتراضات</span><span class="pln">
    </span><span class="typ">Value</span><span class="pln"> </span><span class="pun">&amp;</span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Value</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln">val</span><span class="pun">)</span><span class="pln"> noexcept </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// ستُدمّر قريبا val حيلة ذكية، لأن</span><span class="pln">
        </span><span class="com">// لقد استبدلنا بياناتنا ببياناته، وسيدمّر مدمّره بياناتنا</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">swap</span><span class="pun">(</span><span class="pln">array_</span><span class="pun">,</span><span class="pln"> val</span><span class="pun">.</span><span class="pln">array_</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	لا شك أننا نستطيع جعل مثل هذا النوع غير قابل للنسخ إن أردنا منع النسخ العميق مع السماح بنقل الكائن، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4077_27" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Inner</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">constexpr</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> NUM_INNER </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Value</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">Inner</span><span class="pln"> </span><span class="pun">*</span><span class="pln">array_</span><span class="pun">;</span><span class="pln"> </span><span class="com">// في العادة يكون لها دلالة مرجعية</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">Value</span><span class="pun">():</span><span class="pln"> array_</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Inner</span><span class="pun">[</span><span class="pln">NUM_INNER</span><span class="pun">])</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
        </span><span class="com">// nullptr يُسمح بالنقل حتى لو أعادت</span><span class="pln">
        </span><span class="pun">~</span><span class="typ">Value</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">delete</span><span class="pun">[]</span><span class="pln"> array_</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="typ">Value</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Value</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">val</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">delete</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">Value</span><span class="pln"> </span><span class="pun">&amp;</span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Value</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">val</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">delete</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// النقل يعني لا تخصيص للذاكرة</span><span class="pln">
    </span><span class="com">// لا يمكن إطلاق اعتراض</span><span class="pln">
    </span><span class="typ">Value</span><span class="pun">(</span><span class="typ">Value</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln">val</span><span class="pun">)</span><span class="pln"> noexcept</span><span class="pun">:</span><span class="pln"> array_</span><span class="pun">(</span><span class="pln">val</span><span class="pun">.</span><span class="pln">array_</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// لقد أخذنا القيمة القديمة</span><span class="pln">
        val</span><span class="pun">.</span><span class="pln">array_ </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">nullptr</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="com">// لا يمكن رفع اعتراضات</span><span class="pln">
    </span><span class="typ">Value</span><span class="pln"> </span><span class="pun">&amp;</span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Value</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln">val</span><span class="pun">)</span><span class="pln"> noexcept </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// ستُدمّر قريبا val حيلة ذكية، لأن</span><span class="pln">
        </span><span class="com">// لقد استبدلنا  بياناتنا ببياناته، مدمّره سيدمّر بياناتنا</span><span class="pln">

        std</span><span class="pun">::</span><span class="pln">swap</span><span class="pun">(</span><span class="pln">array_</span><span class="pun">,</span><span class="pln"> val</span><span class="pun">.</span><span class="pln">array_</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	نستطيع أن نطبق قاعدة الصفر (Rule of Zero) من خلال استخدام مؤشّر فريد <code>‎unique_ptr‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4077_29" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Inner</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">constexpr</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> NUM_INNER </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Value</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
        unique_ptr</span><span class="pun">&lt;</span><span class="typ">Inner</span><span class="pln"> </span><span class="pun">[]&gt;</span><span class="pln">array_</span><span class="pun">;</span><span class="pln"> </span><span class="com">// نوع للنقل فقط</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">Value</span><span class="pun">():</span><span class="pln"> array_</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Inner</span><span class="pun">[</span><span class="pln">NUM_INNER</span><span class="pun">])</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
        </span><span class="com">// لا داعي للحذف الصريح، أو حتى التصريح</span><span class="pln">
        </span><span class="pun">~</span><span class="typ">Value</span><span class="pun">()</span><span class="pln"> </span><span class="pun">=</span><span class="pln">
        </span><span class="kwd">default</span><span class="pun">;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">delete</span><span class="pun">[]</span><span class="pln"> array_</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="com">//  لا داعي للحذف الصريح، أو حتى التصريح</span><span class="pln">
    </span><span class="typ">Value</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Value</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">val</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln">
        </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">Value</span><span class="pln"> </span><span class="pun">&amp;</span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Value</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">val</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln">
        </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// تنفيذ النقل عنصرا بعنصر</span><span class="pln">
    </span><span class="typ">Value</span><span class="pun">(</span><span class="typ">Value</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln">val</span><span class="pun">)</span><span class="pln"> noexcept </span><span class="pun">=</span><span class="pln">
        </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
    </span><span class="com">//  تنفيذ النقل عنصرا بعنصر</span><span class="pln">
    </span><span class="typ">Value</span><span class="pln"> </span><span class="pun">&amp;</span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Value</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln">val</span><span class="pun">)</span><span class="pln"> noexcept </span><span class="pun">=</span><span class="pln">
        </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	هذا الدرس جزء من <a data-ss1617022508="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة دروس عن C++‎</a>.
</p>

<p>
	ترجمة -بتصرّف- للفصل Chapter 26: References والفصل Chapter 27: Value and Reference Semantics من كتاب <a data-ss1617022508="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">910</guid><pubDate>Tue, 30 Jun 2020 18:04:00 +0000</pubDate></item><item><title>&#x62A;&#x637;&#x628;&#x64A;&#x642; &#x627;&#x644;&#x62A;&#x639;&#x62F;&#x62F;&#x64A;&#x629; &#x627;&#x644;&#x634;&#x643;&#x644;&#x64A;&#x629; (Polymorphism) &#x641;&#x64A; Cpp</title><link>https://academy.hsoub.com/programming/cpp/%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-%D8%A7%D9%84%D8%AA%D8%B9%D8%AF%D8%AF%D9%8A%D8%A9-%D8%A7%D9%84%D8%B4%D9%83%D9%84%D9%8A%D8%A9-polymorphism-%D9%81%D9%8A-cpp-r900/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_06/16.jpg.5ac6a91b8a5b1a1b936239614cbe1094.jpg" /></p>

<h2>
	تعريف الأصناف متعددة الأشكال
</h2>

<p>
	أبسط مثال لتوضيح مفهوم تعددية الأشكال (Polymorphism) أنه إنشاء لصنف مجرّد يصف الأشكال الهندسية، والذي يمكن أن نشتق منه المربّعات والدوائر وغيرها من الأشكال الأخرى.
</p>

<h3>
	الصنف الأب
</h3>

<p>
	لنبدأ بالصنف متعدد الأشكال (polymorphic class):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1211_7" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Shape</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">virtual</span><span class="pun">~</span><span class="typ">Shape</span><span class="pun">()</span><span class="pln"> </span><span class="pun">=</span><span class="pln">
        </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">virtual</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> get_surface</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">virtual</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> describe_object</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"this is a shape"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">double</span><span class="pln"> get_doubled_surface</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> get_surface</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	تحليل الشيفرة:
</p>

<ul>
<li>
		تستطيع تعريف السلوك متعدد الأشكال عن طريق إسباق توابع الصنف باستخدام الكلمة المفتاحية <code>‎virtual‎</code>، فهنا سيُقَدَّم التابع ‎<code>get_surface()</code>‎ الخاص بالمربع بشكل مختلف عن <code>‎describe_object()‎</code> الخاص بالدائرة، عند استدعاء الدالة على كائن ما، ستُستدعى الدالة المقابلة للصنف الحقيقي للكائن في وقت التشغيل.
	</li>
	<li>
		لا معنى لتعريف التابع <code>‎get_surface()‎</code> لشكلٍ مجرّد، لهذا تُتبَع الدالة بالتعبير <code>‎= 0‎</code>، في إشارة إلى أنّ الدالة إنّما هي دالة وهمية خالصة.
	</li>
	<li>
		يجب أن تعرِّف الأصناف متعددة الأشكال مُدمِّرًا وهميًا (virtual destructor) دومًا.
	</li>
	<li>
		يجوز لك تعريف دوال تابعة غير وهمية، وسيُختار التابع المناسب عند استدعاء تلك التوابع على كائن ما وفقًا للصنف المستخدم في وقت التصريف، وقد عرَّفنا التابع <code>‎get_double_surface()‎</code> في المثال أعلاه بهذه الطريقة.
	</li>
	<li>
		الصنف الذي يحتوي على دالة وهميّة واحدة على الأقل يُعدُّ صنفًا مجرّدًا، ولا يمكن للأصناف المجرّدة أن تُستنسخ (instantiated)، وإنما تستطيع أن تحصل فقط على مؤشرات أو مراجع إليها.
	</li>
</ul>
<h3>
	الأصناف المشتقة (Derived classes)
</h3>

<p>
	بمجرد تعريف صنف أساسي متعدد الأشكال فيمكنك الاشتقاق منه، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1211_9" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Square</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">Shape</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Point</span><span class="pln"> top_left</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">double</span><span class="pln"> side_length</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">Square</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Point</span><span class="pun">&amp;</span><span class="pln"> top_left</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> side</span><span class="pun">):</span><span class="pln"> top_left</span><span class="pun">(</span><span class="pln">top_left</span><span class="pun">),</span><span class="pln"> side_length</span><span class="pun">(</span><span class="pln">side_length</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="kwd">double</span><span class="pln"> get_surface</span><span class="pun">()</span><span class="pln"> override </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> side_length </span><span class="pun">*</span><span class="pln"> side_length</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> describe_object</span><span class="pun">()</span><span class="pln"> override </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"this is a square starting at "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> top_left</span><span class="pun">.</span><span class="pln">x </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> top_left</span><span class="pun">.</span><span class="pln">y </span><span class="pun">&lt;&lt;</span><span class="pln">
            </span><span class="str">" with a length of "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> side_length </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	تفسير المثال:
</p>

<ul>
<li>
		يمكنك تعريف أو إعادة تعريف (override) أيٍّ من الدوال الوهميّة للصنف الأب، وستبقى الدوال الوهميّة في الصنف الأب وهميّة أيضًا في الصنف المشتق، ولا حاجة لإضافة الكلمة المفتاحية <code>‎virtual‎</code> مرّة أخرى، لكن يُوصى بإضافة الكلمة المفتاحية <code>‎override‎</code> إلى نهاية تصريح الدالة لمنع الأخطاء الناتجة عن الاختلافات غير الملحوظة في بصمة الدالّة.
	</li>
	<li>
		إذا عُرِّفت جميع الدوالّ الوهميّة للصنف الأب، فسيكون بمقدورك استنساخ كائنات من ذلك الصنف، أما إن بقيت دوالّ وهمية غير مُعرّفة فإنّ الصنف المشتق سيبقى صنفًا مجردًا.
	</li>
	<li>
		لست ملزمًا بإعادة تعريف كل الدوالّ الوهميّة، بل لا بأس بالاحتفاظ بنسخة الصنف الأب إن كان ذلك يناسب ما تحتاجه. انظر المثال التالي على الاستنساخ:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1211_11" style="">
<span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Square</span><span class="pln"> square</span><span class="pun">(</span><span class="typ">Point</span><span class="pun">(</span><span class="lit">10.0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0.0</span><span class="pun">),</span><span class="pln"> </span><span class="lit">6</span><span class="pun">);</span><span class="pln"> </span><span class="com">// نعلم أنه مربع</span><span class="pln">
    square</span><span class="pun">.</span><span class="pln">describe_object</span><span class="pun">();</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Surface: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> square</span><span class="pun">.</span><span class="pln">get_surface</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">Circle</span><span class="pln"> circle</span><span class="pun">(</span><span class="typ">Point</span><span class="pun">(</span><span class="lit">0.0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0.0</span><span class="pun">),</span><span class="pln"> </span><span class="lit">5</span><span class="pun">);</span><span class="pln">
    </span><span class="typ">Shape</span><span class="pln"> </span><span class="pun">*</span><span class="pln">ps </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">nullptr</span><span class="pun">;</span><span class="pln"> </span><span class="com">// لا نعلم بعدُ النوع الحقيقي للكائن</span><span class="pln">
    ps </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">circle</span><span class="pun">;</span><span class="pln"> </span><span class="com">// إنها دائرة، لكن كان من الممكن أن تكون مربعا</span><span class="pln">
    ps</span><span class="pun">-&gt;</span><span class="pln">describe_object</span><span class="pun">();</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Surface: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> ps </span><span class="pun">-</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> get_surface</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	التخفيض الآمن (Safe downcasting)
</h2>

<p>
	لنفترض أنّ لديك مؤشرًا يشير إلى كائن من صنف متعدد الأشكال:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1211_13" style="">
<span class="typ">Shape</span><span class="pln"> </span><span class="pun">*</span><span class="pln">ps</span><span class="pun">;</span><span class="pln">
ps </span><span class="pun">=</span><span class="pln">  get_a_new_random_shape</span><span class="pun">();</span><span class="pln"> </span><span class="com">// إذا لم تكن لديك هذه الدالة</span><span class="pln">
</span><span class="com">// ps = new Square(0.0,0.0, 5); :يمكنك أن تكتب</span></pre>

<p>
	فيكون التخفيض هنا هو أن تحوّل الصنف العام متعدد الأشكال <code>‎Shape‎</code> إلى أحد الأشكال المشتقة منه، مثل <code>‎Square‎</code> أو <code>‎Circle‎</code>.
</p>

<h3>
	لماذا التخفيض؟
</h3>

<p>
	لن تحتاج في معظم الأحيان إلى معرفة النوع الحقيقي للكائن لأنّ الدوال الوهميّة تسمح لك بمعالجة الكائن بشكل مستقل عن نوعه:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1211_15" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Surface: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> ps</span><span class="pun">-&gt;</span><span class="pln">get_surface</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></pre>

<p>
	أما إذا لم تحتج إلى التخفيض فهذا مؤشّر على أنّ شيفرتك جيدة، لكن قد تحتاج إليه في بعض الأحيان حين تريد استدعاء دالة غير وهميّة لا توجد إلا في الصنف الفرعي. على سبيل المثال، يختص مفهوم القطر بالدوائر فقط، لذلك سيُعرَّف الصنف على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1211_17" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Circle</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">Shape</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Point</span><span class="pln"> center</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">double</span><span class="pln"> radius</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">Circle</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Point</span><span class="pun">&amp;</span><span class="pln"> center</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> radius</span><span class="pun">):</span><span class="pln"> center</span><span class="pun">(</span><span class="pln">center</span><span class="pun">),</span><span class="pln"> radius</span><span class="pun">(</span><span class="pln">radius</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="kwd">double</span><span class="pln"> get_surface</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> override </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> r </span><span class="pun">*</span><span class="pln"> r </span><span class="pun">*</span><span class="pln"> M_PI</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="com">// هذا صالح للدوائر وحسب، ولا معنى له بالنسبة لبقية الأشكال</span><span class="pln">
    </span><span class="kwd">double</span><span class="pln"> get_diameter</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> r</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	لا توجد دالة التابع <code>‎get_diameter()‎</code> إلا في الدوائر، ولم تُعرَّف لكائن (<code>‎Shape‎</code>) عام:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1211_19" style="">
<span class="typ">Shape</span><span class="pun">*</span><span class="pln"> ps </span><span class="pun">=</span><span class="pln"> get_any_shape</span><span class="pun">();</span><span class="pln">
ps</span><span class="pun">-&gt;</span><span class="pln">get_diameter</span><span class="pun">();</span><span class="pln"> </span><span class="com">// خطأ في التصريف</span></pre>

<h3>
	كيفية التخفيض
</h3>

<p>
	إذا كنت متأكدًا أنّ المؤشّر <code>‎ps‎</code> يشير إلى دائرة، فيمكنك استخدام <code>‎static_cast‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1211_21" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Diameter: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="typ">Circle</span><span class="pun">*&gt;(</span><span class="pln">ps</span><span class="pun">)-&gt;</span><span class="pln">get_diameter</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></pre>

<p>
	هذا سيؤدي الغرض لكنه ينطوي على مخاطرة كبيرة، فإذا لم يكن المؤشّر <code>‎ps‎</code> يشير إلى دائرة (<code>‎Circle‎</code>)، فلا يمكن توقّع سلوك الشيفرة. لذلك يُفضّل استخدام الخيار الآمن <code>‎dynamic_cast‎</code> الذي يختص بالأصناف متعددة الأشكال:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1211_23" style="">
<span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Circle</span><span class="pln"> circle</span><span class="pun">(</span><span class="typ">Point</span><span class="pun">(</span><span class="lit">0.0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0.0</span><span class="pun">),</span><span class="pln"> </span><span class="lit">10</span><span class="pun">);</span><span class="pln">
    </span><span class="typ">Shape</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">shape </span><span class="pun">=</span><span class="pln"> circle</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"The shape has a surface of "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> shape</span><span class="pun">.</span><span class="pln">get_surface</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="com">//shape.get_diameter();   // خطأ في التصريف</span><span class="pln">
    </span><span class="typ">Circle</span><span class="pln"> </span><span class="pun">*</span><span class="pln">pc </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">dynamic_cast</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Circle</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> shape</span><span class="pun">);</span><span class="pln"> 
</span><span class="com">// nullptr يشير إلى دائرة فسنحصل على ps إذا لم يكن المؤشر</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">pc</span><span class="pun">)</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"The shape is a circle of diameter "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> pc </span><span class="pun">-</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> get_diameter</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">else</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"The shape isn't a circle !"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لاحظ أنّ <code>‎dynamic_cast‎</code> غير ممكنة على الأصناف ذات الشكل الواحد، وستحتاج إلى دالة وهميّة واحدة على الأقل في الصنف أو أحد آبائه لتتمكن من استخدامها.
</p>

<h2>
	التعددية الشكلية والمدمِّرَات (Polymorphism &amp; Destructors)
</h2>

<p>
	إذ أردت استخدام الصنف بحيث يكون متعدد الأشكال وتُخزَّن النسخ (instances) المشتقّة منه كمؤشّرات/مراجع أساسية، فيجب أن يكون مدمِّر الصنف الأساسي وهميًّا (<code>‎virtual‎</code>) أو محميًا (<code>‎protected‎</code>)، وفي الحالة الأولى سيؤدي تدمير الكائن إلى التحقّق من <code>‎vtable‎</code> وسَيستدعي المدمّر الصحيح تلقائيًا بناءً على النوع الديناميكي. أما في الثانية فتُعطَّل إمكانية تدمير الكائن عبر مؤشّر/مرجع للصنف الأساسي، ولا يمكن حذف الكائن إلا عند التعامل معه باعتباره من نوعه الفعلي.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1211_25" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">VirtualDestructor</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">virtual</span><span class="pun">~</span><span class="typ">VirtualDestructor</span><span class="pun">()</span><span class="pln"> </span><span class="pun">=</span><span class="pln">
        </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">VirtualDerived</span><span class="pun">:</span><span class="pln"> </span><span class="typ">VirtualDestructor</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">ProtectedDestructor</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pun">:</span><span class="pln">
        </span><span class="pun">~</span><span class="typ">ProtectedDestructor</span><span class="pun">()</span><span class="pln"> </span><span class="pun">=</span><span class="pln">
        </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">ProtectedDerived</span><span class="pun">:</span><span class="pln"> </span><span class="typ">ProtectedDestructor</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="pun">~</span><span class="typ">ProtectedDerived</span><span class="pun">()</span><span class="pln"> </span><span class="pun">=</span><span class="pln">
        </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="com">// ...</span><span class="pln">
</span><span class="typ">VirtualDestructor</span><span class="pun">*</span><span class="pln"> vd </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">VirtualDerived</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">delete</span><span class="pln"> vd</span><span class="pun">;</span><span class="pln">

</span><span class="typ">ProtectedDestructor</span><span class="pun">*</span><span class="pln"> pd </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ProtectedDerived</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">delete</span><span class="pln"> pd</span><span class="pun">;</span><span class="pln"> </span><span class="com">// Error: ProtectedDestructor::~ProtectedDestructor() is protected.</span><span class="pln">
</span><span class="kwd">delete</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">ProtectedDerived</span><span class="pun">*</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">pd</span><span class="pun">);</span><span class="pln"> </span><span class="com">// OK</span></pre>

<p>
	سيبحث <code>delete vd</code> عن <code>()VirtualDestructor::~VirtualDestructor</code> في <code>vtable</code> وعند وجوده سيبحث عن <code>()VirtualDerived::~VirtualDerived</code> ويستدعيه. كذلك سيعطي <code>delete pd</code> خطأً لأن <code>()ProtectedDestructor::~ProtectedDestructor</code> محميّ. سيضمن هذا أنّ مدمّر الصنف المشتق سيُستدعى على جميع نُسخ الصّنف المشتق، ممّا يمنع تسرّب الذاكرة.
</p>

<p>
	هذا الدرس جزء من <a data-ss1617022507="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة دروس عن C++‎</a>.
</p>

<p>
	ترجمة -بتصرّف- للفصل Chapter 25: Polymorphism من كتاب <a data-ss1617022507="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">900</guid><pubDate>Sun, 28 Jun 2020 18:08:00 +0000</pubDate></item><item><title>&#x627;&#x633;&#x62A;&#x62F;&#x639;&#x627;&#x621; &#x627;&#x644;&#x62F;&#x648;&#x627;&#x644; &#x648;&#x625;&#x639;&#x627;&#x62F;&#x629; &#x639;&#x62F;&#x629; &#x642;&#x64A;&#x645; &#x645;&#x646;&#x647;&#x627; &#x641;&#x64A; Cpp</title><link>https://academy.hsoub.com/programming/cpp/%D8%A7%D8%B3%D8%AA%D8%AF%D8%B9%D8%A7%D8%A1-%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-%D9%88%D8%A5%D8%B9%D8%A7%D8%AF%D8%A9-%D8%B9%D8%AF%D8%A9-%D9%82%D9%8A%D9%85-%D9%85%D9%86%D9%87%D8%A7-%D9%81%D9%8A-cpp-r899/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_06/15.jpg.041312bd49fa43df9ae759d0672599c2.jpg" /></p>

<h2>
	استدعاء الدوال بالقيمة أو بالمرجع
</h2>

<p>
	هدف هذا القسم هو شرح الاختلافات من الناحية النظرية والعمليّة بخصوص ما يحدث لمعاملات الدوال عند استدعائها، وأيضًا قابلية إعادة استخدام المتغيرات وقيمها بعد استدعاء الدالة، إذ يمكن النظر إلى المعامِلات على أنّها متغيّرات قبل استدعاء الدالّة وداخل الدالّة، إذ يختلف سلوك هذه المتغيرات وقابلية الوصول لها بحسب الطريقة المستخدمة لتمريرها.
</p>

<h2>
	الاستدعاء بالقيمة (Call by value)
</h2>

<p>
	عند استدعاء دالة، تُنشأ عناصر جديدة في مُكدِّس (stack) البرنامج، ويشمل ذلك بعض المعلومات عن الدالّة وكذلك المساحة (مواقع الذاكرة) المخصّصة للمعامِلات، والقيمة المُعادة.
</p>

<p>
	وعند تمرير معامِل إلى دالّة، تُنسخ قيمة المتغير المُستخدم (أو <a data-ss1617022546="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-2-%D8%A7%D9%84%D9%82%D9%8A%D9%85-%D9%85%D8%B5%D9%86%D9%91%D9%8E%D9%81%D8%A9-%D8%A7%D9%84%D9%86%D9%88%D8%B9-r803/" rel="">العنصر الحرفي</a>) إلى الموقع المخصّص في الذاكرة لمُعامل الدالة، هذا يعني أنه سيُوجد حينها موقعان في الذاكرة لهما نفس القيمة، وسنعمل دَاخل الدالة على الموقع المخصّص للمعامل في الذاكرة فقط.
</p>

<p>
	تُحذَف الذاكرة الموجودة في مُكدّس البرنامج بعد الخروج من الدالّة ممّا يؤدّي إلى مسح جميع بيانات استدعاء الدالّة بما في ذلك المواقع في الذاكرة المخصّصة للمعاملات التي استخدمناها داخلَ الدالّة، ومن ثم فإنّ القيم التي غُيِّرت داخل الدالّة لن تؤثر على قيم المتغيرات الخارجية.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5119_7" style="">
<span class="typ">int</span><span class="pln"> func</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> f</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span></pre>

<p>
	تُنشأ متغيرات جديدة، وتحمل القيم المنسوخة من خارج <code>f</code> القيمة <code>0</code>، وقيمة <code>inner_b</code> تساوي 1. نتابع:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5119_9" style="">
<span class="pln">    f </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// تساوي 1 f قيمة</span><span class="pln">
    b </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// تساوي 2 inner_b قيمة</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> f </span><span class="pun">+</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">(</span><span class="kwd">void</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln"> </span><span class="com">//outer_b</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> c</span><span class="pun">;</span><span class="pln">

    c </span><span class="pun">=</span><span class="pln"> func</span><span class="pun">(</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> b</span><span class="pun">);</span><span class="pln">
    </span><span class="com">// c تُنسخ القيمة المعادة إلى</span><span class="pln">

    </span><span class="com">// تساوي الصفر a </span><span class="pln">
    </span><span class="com">// تساوي 1 outer_b قيمة</span><span class="pln">
    </span><span class="com">// هما متغيّران مختلفان outer_b و inner_b </span><span class="pln">
    </span><span class="com">// تساوي 3 c قيمة</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	في المثال السابق نشئ متغيرات داخل الدالّة الرئيسية، وعند استدعاء الدوالّ يُنشأ متغيران جديدان: <code>‎f‎</code> و <code>‎inner_b‎</code>، حيث يتشارك <code>‎b‎</code> الاسم مع المتغيّر الخارجي ولكن لا يتشارك معه في موقع الذاكرة، كما أنّ سلوك <code>‎a&lt;-&gt;f‎</code> و <code>‎b&lt;-&gt;b‎</code> متماثلان هنا.
</p>

<p>
	يوضح الرسم التالي ما يحدث في المُكدّس ولماذا لا يحدث أيّ تغيير على المتغيّر <code>‎b‎</code>. هذا الرسم ليس دقيقًا تمامًا، ولكنّه يوضّح المثال.
</p>

<p style="text-align: center;">
	<img alt="call.png" class="ipsImage ipsImage_thumbnailed" data-fileid="45439" data-unique="kzfrgqkkn" src="https://academy.hsoub.com/uploads/monthly_2020_06/call.png.447880ed22b66fdcded5181cc26fc5c9.png"></p>

<p>
	يُطلق على هذا "استدعاءً بالقيمة" لأننا لا نمرّر المتغيرات نفسها، وإنما نمرّر قيمها فقط.
</p>

<h2>
	وإعادة عدة قيم من دالة
</h2>

<p>
	قد تحتاج أحيانًا أن تعيد عدة قيم من دالة ما، كأن ترغب في إدخال عنصر وتعيد ثمنه ورقمه في المخزن مثلًا، فهذه الوظيفة تكون مفيدة عندها، ولدينا عدة طرق لتنفيذ ذلك في ++C باستخدام مكتبة القوالب القياسية، وتستطيع تجنب هذه المكتبة إن احتجت ذلك، وسيزال لديك عدة طرق أخرى بما فيها البُنى والأصناف والمصفوفات.
</p>

<h3>
	استخدام الصّفوف std::tuple
</h3>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong> تستطيع الصفوف (<a data-ss1617022546="1" href="http://en.cppreference.com/w/cpp/utility/tuple" rel="external nofollow"><code>‎std::tuple‎</code></a>) أن تجمّع أيّ عدد من القيم حتى لو كانت من أنواع مختلفة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5119_11" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">tuple </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> foo</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">// or auto (C++14)</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">make_tuple</span><span class="pun">(</span><span class="pln">a </span><span class="pun">+</span><span class="pln"> b</span><span class="pun">,</span><span class="pln"> a </span><span class="pun">-</span><span class="pln"> b</span><span class="pun">,</span><span class="pln"> a </span><span class="pun">*</span><span class="pln"> b</span><span class="pun">,</span><span class="pln"> a </span><span class="pun">/</span><span class="pln"> b</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	في C++‎ 17، يمكن استخدام قائمة مهيِّئة ذات أقواس معقوصة (braced initializer list):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5119_13" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">tuple</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pun">&gt;</span><span class="pln"> foo</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">{</span><span class="pln">a </span><span class="pun">+</span><span class="pln"> b</span><span class="pun">,</span><span class="pln"> a </span><span class="pun">-</span><span class="pln"> b</span><span class="pun">,</span><span class="pln"> a </span><span class="pun">*</span><span class="pln"> b</span><span class="pun">,</span><span class="pln"> a </span><span class="pun">/</span><span class="pln"> b</span><span class="pun">};</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	قد تكون استعادة القيم المعادة من <code>‎tuple‎</code> مرهقة إذ تتطلّب استخدام دالة القالب <a data-ss1617022546="1" href="http://en.cppreference.com/w/cpp/utility/tuple/get" rel="external nofollow"><code>‎std::get‎</code></a>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5119_15" style="">
<span class="kwd">auto</span><span class="pln"> mrvs </span><span class="pun">=</span><span class="pln"> foo</span><span class="pun">(</span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">12</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> add </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">get</span><span class="pun">&lt;</span><span class="lit">0</span><span class="pun">&gt;(</span><span class="pln">mrvs</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> sub </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">get</span><span class="pun">&lt;</span><span class="lit">1</span><span class="pun">&gt;(</span><span class="pln">mrvs</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> mul </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">get</span><span class="pun">&lt;</span><span class="lit">2</span><span class="pun">&gt;(</span><span class="pln">mrvs</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> div </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">get</span><span class="pun">&lt;</span><span class="lit">3</span><span class="pun">&gt;(</span><span class="pln">mrvs</span><span class="pun">);</span></pre>

<p>
	إذا أمكن التصريح عن الأنواع قبل عودة الدالّة، فيمكن استخدام <a data-ss1617022546="1" href="http://en.cppreference.com/w/cpp/utility/tuple/tie" rel="external nofollow"><code>‎std::tie‎</code></a> لتفريغ الصف <code>‎tuple‎</code> في متغيّرات أخرى:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5119_17" style="">
<span class="typ">int</span><span class="pln"> add</span><span class="pun">,</span><span class="pln"> sub</span><span class="pun">,</span><span class="pln"> mul</span><span class="pun">,</span><span class="pln"> div</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">tie</span><span class="pun">(</span><span class="pln">add</span><span class="pun">,</span><span class="pln"> sub</span><span class="pun">,</span><span class="pln"> mul</span><span class="pun">,</span><span class="pln"> div</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> foo</span><span class="pun">(</span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">12</span><span class="pun">);</span></pre>

<p>
	يمكن استخدام <a data-ss1617022546="1" href="http://en.cppreference.com/w/cpp/utility/tuple/ignore" rel="external nofollow"><code>‎std::ignore‎</code></a> إذا انتفت الحاجة إلى قيمة من القيم المعادة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5119_19" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">tie</span><span class="pun">(</span><span class="pln">add</span><span class="pun">,</span><span class="pln"> sub</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">ignore</span><span class="pun">,</span><span class="pln"> div</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> foo</span><span class="pun">(</span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">12</span><span class="pun">);</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 17</strong>
</p>

<p>
	يمكن استخدام الارتباطات البنيوية (Structured bindings) لتجنّب استخدام <code>‎std::tie‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5119_21" style="">
<span class="kwd">auto</span><span class="pln"> </span><span class="pun">[</span><span class="pln">add</span><span class="pun">,</span><span class="pln"> sub</span><span class="pun">,</span><span class="pln"> mul</span><span class="pun">,</span><span class="pln"> div</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> foo</span><span class="pun">(</span><span class="lit">5</span><span class="pun">,</span><span class="lit">12</span><span class="pun">);</span></pre>

<p>
	إذا أردت إعادة صفٍّ مؤلَّف من مراجعِ القيم اليسارية (lvalue references) بدلًا من صفّ مؤلّف من القيم، فاستخدم <code>‎std::tie‎</code> بدلاً من <a data-ss1617022546="1" href="http://en.cppreference.com/w/cpp/utility/tuple/make_tuple" rel="external nofollow"><code>std::make_tuple</code></a>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5119_24" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">tuple </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> minmax</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">b </span><span class="pun">&lt;</span><span class="pln"> a</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">tie</span><span class="pun">(</span><span class="pln">b</span><span class="pun">,</span><span class="pln"> a</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">else</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">tie</span><span class="pun">(</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> b</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	والذي يسمح بما يلي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5119_26" style="">
<span class="kwd">void</span><span class="pln"> increase_least</span><span class="pun">(</span><span class="typ">int</span><span class="pun">&amp;</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pun">&amp;</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">get </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">minmax</span><span class="pun">(</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> b</span><span class="pun">))</span><span class="pln"> </span><span class="pun">++;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	في بعض الحالات النادرة، قد تُستخدم <a data-ss1617022546="1" href="http://en.cppreference.com/w/cpp/utility/tuple/forward_as_tuple" rel="external nofollow"><code>‎std::forward_as_tuple‎</code></a> بدلاً من <code>‎std::tie‎</code> لكن احذر في تلك الحالات إذ قد لا تدوم الكائنات المؤقّتة بما يكفي لاستهلاكها.
</p>

<h3>
	الارتباطات البنيوية (Structured Bindings)
</h3>

<p>
	<strong>الإصدار ≥ C++‎ 17</strong>
</p>

<p>
	قدّم الإصدار C++‎ 17 مفهوم الارتباطات البنيويّة التي سهّلت على المبرمجين التعامل مع عدة أنواع للإعادة، إذ أنّك لن تكون مضطرًّا إلى الاعتماد على <a data-ss1617022546="1" href="http://en.cppreference.com/w/cpp/utility/tuple/tie" rel="external nofollow"><code>‎std::tie()‎</code></a> أو تفريغ الصفوف يدويًِّا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5119_28" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">map</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> m</span><span class="pun">;</span><span class="pln">
</span><span class="com">// أدرج عنصرا في القاموس وتحقق من نجاح الإدراج</span><span class="pln">
</span><span class="kwd">auto</span><span class="pun">[</span><span class="typ">iterator</span><span class="pun">,</span><span class="pln"> success</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> m</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">({</span><span class="pln">
    </span><span class="str">"Hello"</span><span class="pun">,</span><span class="pln">
    </span><span class="lit">42</span><span class="pln">
</span><span class="pun">});</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">success</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// شيفرتك هنا</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="com">// 'second' و 'first' كرّر على كل العناصر دون الحاجة إلى استخدام الاسمين المبهميْن</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln">
    </span><span class="kwd">const</span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">[</span><span class="pln">key</span><span class="pun">,</span><span class="pln"> value</span><span class="pun">]:</span><span class="pln"> m</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"The value for "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> key </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" is "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> value </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكن استخدام الارتباطات البنيويّة افتراضيًّا مع الأزواج (<code>‎std::pair‎</code>) والصفوف (<code>‎std::tuple‎</code>) وكذلك أيّ نوع تكون بياناته العضويّة غير الساكنة (non-static data members) إما أعضاءً مباشرين علنيين أو أعضاءً من صنف أساسي محدد:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5119_30" style="">
<span class="kwd">struct</span><span class="pln"> A </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> B</span><span class="pun">:</span><span class="pln"> A </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> y</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
B foo</span><span class="pun">();</span><span class="pln">
</span><span class="com">// استخدام الارتباطات البنيويّة</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">auto</span><span class="pun">[</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> foo</span><span class="pun">();</span><span class="pln">
</span><span class="com">// الشيفرة المكافئة بدون استخدام الارتباطات البنيويّة</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> result </span><span class="pun">=</span><span class="pln"> foo</span><span class="pun">();</span><span class="pln">
</span><span class="kwd">auto</span><span class="pun">&amp;</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> result</span><span class="pun">.</span><span class="pln">x</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pun">&amp;</span><span class="pln"> y </span><span class="pun">=</span><span class="pln"> result</span><span class="pun">.</span><span class="pln">y</span><span class="pun">;</span></pre>

<p>
	إذا جعلت نوعًا ما "شبيهًا بالصفوف (tuple-like)" فسيعمل تلقائيًا مع ذلك النوع. النوع الشبيه بالصّفوف يتوفّر على التوابع التالية: <code>‎tuple_size‎</code> و <code>‎tuple_element‎</code> و <code>‎get‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5119_32" style="">
<span class="kwd">namespace</span><span class="pln"> my_ns </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> my_type </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">double</span><span class="pln"> d</span><span class="pun">;</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">string s</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> my_type_view </span><span class="pun">{</span><span class="pln">
        my_type</span><span class="pun">*</span><span class="pln"> ptr</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">namespace</span><span class="pln"> std </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">template</span><span class="pun">&lt;&gt;</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> tuple_size</span><span class="pun">&lt;</span><span class="pln">my_ns</span><span class="pun">::</span><span class="pln">my_type_view</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">integral_constant</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">&gt;</span><span class="pln">
</span><span class="pun">{};</span><span class="pln">

</span><span class="kwd">template</span><span class="pun">&lt;&gt;</span><span class="pln"> </span><span class="kwd">struct</span><span class="pln"> tuple_element</span><span class="pun">&lt;</span><span class="pln">my_ns</span><span class="pun">::</span><span class="pln">my_type_view</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">&gt;{</span><span class="pln"> </span><span class="kwd">using</span><span class="pln"> type </span><span class="pun">=</span><span class="pln"> </span><span class="typ">int</span><span class="pun">;</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">template</span><span class="pun">&lt;&gt;</span><span class="pln"> </span><span class="kwd">struct</span><span class="pln"> tuple_element</span><span class="pun">&lt;</span><span class="pln">my_ns</span><span class="pun">::</span><span class="pln">my_type_view</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">&gt;{</span><span class="pln"> </span><span class="kwd">using</span><span class="pln"> type </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">double</span><span class="pun">;</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">template</span><span class="pun">&lt;&gt;</span><span class="pln"> </span><span class="kwd">struct</span><span class="pln"> tuple_element</span><span class="pun">&lt;</span><span class="pln">my_ns</span><span class="pun">::</span><span class="pln">my_type_view</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">&gt;{</span><span class="pln"> </span><span class="kwd">using</span><span class="pln"> type </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">;</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">namespace</span><span class="pln"> my_ns </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> I</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">decltype</span><span class="pun">(</span><span class="kwd">auto</span><span class="pun">)</span><span class="pln"> get</span><span class="pun">(</span><span class="pln">my_type_view </span><span class="kwd">const</span><span class="pun">&amp;</span><span class="pln"> v</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="kwd">constexpr</span><span class="pln"> </span><span class="pun">(</span><span class="pln">I </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">ptr</span><span class="pun">-&gt;</span><span class="pln">x</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">else</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> </span><span class="kwd">constexpr</span><span class="pln"> </span><span class="pun">(</span><span class="pln">I </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">ptr</span><span class="pun">-&gt;</span><span class="pln">d</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">else</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> </span><span class="kwd">constexpr</span><span class="pln"> </span><span class="pun">(</span><span class="pln">I </span><span class="pun">==</span><span class="pln"> </span><span class="lit">2</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">ptr</span><span class="pun">-&gt;</span><span class="pln">s</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">static_assert</span><span class="pun">(</span><span class="pln">I </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Only 3 elements"</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ستعمل الآن الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5119_36" style="">
<span class="pln">my_ns</span><span class="pun">::</span><span class="pln">my_type t</span><span class="pun">{</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3.14</span><span class="pun">,</span><span class="pln"> </span><span class="str">"hello world"</span><span class="pun">};</span><span class="pln">

my_ns</span><span class="pun">::</span><span class="pln">my_type_view foo</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">{&amp;</span><span class="pln">t</span><span class="pun">};</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">auto</span><span class="pun">[</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> d</span><span class="pun">,</span><span class="pln"> s</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> foo</span><span class="pun">();</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> x </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">','</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> d </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">','</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> s </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	استخدام البُنى <code>struct</code>
</h3>

<p>
	يمكن استخدام البُنى (<a data-ss1617022546="1" href="http://en.cppreference.com/w/cpp/language/class" rel="external nofollow"><code>‎struct‎</code></a>) لتجميع عدّة قيم لكي تعيدها دالة:
</p>

<p>
	<strong>الإصدار C++‎ 11</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5119_40" style="">
<span class="kwd">struct</span><span class="pln"> foo_return_type </span><span class="pun">{</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> add</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> sub</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> mul</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> div</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

foo_return_type foo</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">{</span><span class="pln">a </span><span class="pun">+</span><span class="pln"> b</span><span class="pun">,</span><span class="pln"> a </span><span class="pun">-</span><span class="pln"> b</span><span class="pun">,</span><span class="pln"> a </span><span class="pun">*</span><span class="pln"> b</span><span class="pun">,</span><span class="pln"> a </span><span class="pun">/</span><span class="pln"> b</span><span class="pun">};</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">auto</span><span class="pln"> calc </span><span class="pun">=</span><span class="pln"> foo</span><span class="pun">(</span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">12</span><span class="pun">);</span></pre>

<p>
	الإصدار <c></c>++‎&gt;
</p>

<p>
	يمكن استخدام مُنشئ لتبسيط عمليّة إنشاء القيم المُعادة، بدلاً من الإسناد إلى حقول الصنف فرادى:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5119_42" style="">
<span class="kwd">struct</span><span class="pln"> foo_return_type </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> add</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> sub</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> mul</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> div</span><span class="pun">;</span><span class="pln">
    foo_return_type</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> add</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> sub</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> mul</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> div</span><span class="pun">):</span><span class="pln"> add</span><span class="pun">(</span><span class="pln">add</span><span class="pun">),</span><span class="pln"> sub</span><span class="pun">(</span><span class="pln">sub</span><span class="pun">),</span><span class="pln"> mul</span><span class="pun">(</span><span class="pln">mul</span><span class="pun">),</span><span class="pln"> div</span><span class="pun">(</span><span class="pln">div</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

foo_return_type foo</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> foo_return_type</span><span class="pun">(</span><span class="pln">a </span><span class="pun">+</span><span class="pln"> b</span><span class="pun">,</span><span class="pln"> a </span><span class="pun">-</span><span class="pln"> b</span><span class="pun">,</span><span class="pln"> a </span><span class="pun">*</span><span class="pln"> b</span><span class="pun">,</span><span class="pln"> a </span><span class="pun">/</span><span class="pln"> b</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

foo_return_type calc </span><span class="pun">=</span><span class="pln"> foo</span><span class="pun">(</span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">12</span><span class="pun">);</span></pre>

<p>
	يمكن استرداد النتائج الفردية المُعادة من قِبل دالة <code>‎foo()‎</code> عن طريق الوصول إلى المتغيرات الأعضاء لبُنية <code>calc</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5119_44" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> calc</span><span class="pun">.</span><span class="pln">add </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">' '</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> calc</span><span class="pun">.</span><span class="pln">sub </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">' '</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> calc</span><span class="pun">.</span><span class="pln">mul </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">' '</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> calc</span><span class="pun">.</span><span class="pln">div </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span></pre>

<p>
	الناتج:
</p>

<pre class="ipsCode" id="ips_uid_5119_46">
 17 -7 60 0
</pre>

<p>
	ملاحظة: ، تُجمَّع القيم المُعادة معًا عند استخدام البُنى في كائن واحد، ويمكن الوصول إليها باستخدام أسماء ذات معنى (meaningful)، وهذا يساعد على تقليل عدد المتغيرات الخارجية التي أنشئت في نطاق القيم المُعادة.
</p>

<p>
	الإصدار C++‎ 17 ويمكن استخدام الارتباطات البنيويّة لتفريغ بُنية <code>struct</code> المُعادة من دالة، وهذا يجعل معامِلات الخرج على قدم واحدة مع معامِلات الدخل، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5119_48" style="">
<span class="typ">int</span><span class="pln"> a</span><span class="pun">=</span><span class="lit">5</span><span class="pun">,</span><span class="pln"> b</span><span class="pun">=</span><span class="lit">12</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pun">[</span><span class="pln">add</span><span class="pun">,</span><span class="pln"> sub</span><span class="pun">,</span><span class="pln"> mul</span><span class="pun">,</span><span class="pln"> div</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> foo</span><span class="pun">(</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> b</span><span class="pun">);</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> add </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">' '</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> sub </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">' '</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> mul </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">' '</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> div </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span></pre>

<p>
	يطابق خرْجُ هذه الشيفرة خرجَ الشيفرة أعلاه، فما زالت <code>struct</code> تُستخدم لإعادة القيم من الدالة مما يسمح لك بالتعامل مع الحقول بشكل فردي.
</p>

<h3>
	استخدام معامِلات الخرج
</h3>

<p>
	يمكن استخدام المعاملات لإعادة قيمة واحدة أو أكثر بشرط أن تكون تلك المعاملاتُ مؤشّراتٍ أو مراجعَ غير ثابتة.
</p>

<p>
	المراجع:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5119_50" style="">
<span class="kwd">void</span><span class="pln"> calculate</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> b</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> c</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> d</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> e</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> f</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    c </span><span class="pun">=</span><span class="pln"> a </span><span class="pun">+</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
    d </span><span class="pun">=</span><span class="pln"> a </span><span class="pun">-</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
    e </span><span class="pun">=</span><span class="pln"> a </span><span class="pun">*</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
    f </span><span class="pun">=</span><span class="pln"> a </span><span class="pun">/</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	المؤشرات:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5119_52" style="">
<span class="kwd">void</span><span class="pln"> calculate</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> b</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> c</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> d</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> e</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> f</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="pun">*</span><span class="pln">c </span><span class="pun">=</span><span class="pln"> a </span><span class="pun">+</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">*</span><span class="pln">d </span><span class="pun">=</span><span class="pln"> a </span><span class="pun">-</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">*</span><span class="pln">e </span><span class="pun">=</span><span class="pln"> a </span><span class="pun">*</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">*</span><span class="pln">f </span><span class="pun">=</span><span class="pln"> a </span><span class="pun">/</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تَستخدم بعض المكتبات والأُطُر التعليمة البرمجية <code>‎#define OUT</code> لتحديد المعاملاتِ التي ستكون معاملاتِ الخرج في بصمة الدالة، رغم انعدام التأثير الوظيفي لها وأنها ستُهمَل عند التصريف، لكنها ستجعل بصمة الدالة أكثر وضوحًا، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5119_54" style="">
<span class="com">#define</span><span class="pln"> OUT
</span><span class="kwd">void</span><span class="pln"> calculate</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> b</span><span class="pun">,</span><span class="pln"> OUT </span><span class="typ">int</span><span class="pun">&amp;</span><span class="pln"> c</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    c </span><span class="pun">=</span><span class="pln"> a </span><span class="pun">+</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	استخدام مستهلِك دالة (Function Object Consumer)
</h3>

<p>
	نستطيع توفير مستهلك يُستدعى مع القيم المتعددة ذات الصّلة:
</p>

<p>
	الإصدار ++ C++‎ 11
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5119_56" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> F </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> b</span><span class="pun">,</span><span class="pln"> F consumer</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        consumer</span><span class="pun">(</span><span class="pln">a </span><span class="pun">+</span><span class="pln"> b</span><span class="pun">,</span><span class="pln"> a </span><span class="pun">-</span><span class="pln"> b</span><span class="pun">,</span><span class="pln"> a </span><span class="pun">*</span><span class="pln"> b</span><span class="pun">,</span><span class="pln"> a </span><span class="pun">/</span><span class="pln"> b</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="com">// الاستخدام سهل، كما أنه يمكن تجاهل بعض النتائج</span><span class="pln">
foo</span><span class="pun">(</span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">12</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[](</span><span class="typ">int</span><span class="pln"> sum</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"sum is "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> sum </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	يُعرَف هذا باسم "نمط التمرير المستمر" (continuation passing style)، يمكنك تكييف دالة تُعيد صفًّا إلى دالة ذات نمط تمرير مستمر عبر ما يلي:
</p>

<p>
	<strong>الإصدار ≥ C++‎ 17 </strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5119_58" style="">
<span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Tuple</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> continuation </span><span class="pun">{</span><span class="pln">
</span><span class="typ">Tuple</span><span class="pln"> t</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> F</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">decltype</span><span class="pun">(</span><span class="kwd">auto</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">-&gt;*(</span><span class="pln">F</span><span class="pun">&amp;&amp;</span><span class="pln"> f</span><span class="pun">)&amp;&amp;{</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">apply</span><span class="pun">(</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">forward</span><span class="pun">&lt;</span><span class="pln">F</span><span class="pun">&gt;(</span><span class="pln">f</span><span class="pun">),</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">move</span><span class="pun">(</span><span class="pln">t</span><span class="pun">)</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">tuple</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">,</span><span class="typ">int</span><span class="pun">,</span><span class="typ">int</span><span class="pun">,</span><span class="typ">int</span><span class="pun">&gt;</span><span class="pln"> foo</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> b</span><span class="pun">);</span><span class="pln">

continuation</span><span class="pun">(</span><span class="pln">foo</span><span class="pun">(</span><span class="lit">5</span><span class="pun">,</span><span class="lit">12</span><span class="pun">))-&gt;*[](</span><span class="typ">int</span><span class="pln"> sum</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">auto</span><span class="pun">&amp;&amp;...)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"sum is "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> sum </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	ستجد صيغًا أكثر تعقيدًا في C++‎ 14 أو C++‎ 11.
</p>

<h3>
	استخدام قالب <code>std::pair</code>
</h3>

<p>
	يستطيع قالب البُنية <a data-ss1617022546="1" href="http://en.cppreference.com/w/cpp/utility/pair" rel="external nofollow"><code>std::pair</code></a> أن يجمع قيمتيْ إعادة معًا حتى لو كانا من نوعين مختلفين:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5119_60" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;utility&gt;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">pair </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> foo</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">make_pair</span><span class="pun">(</span><span class="pln">a </span><span class="pun">+</span><span class="pln"> b</span><span class="pun">,</span><span class="pln"> a </span><span class="pun">-</span><span class="pln"> b</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	في C++‎ 11 والإصدارات الأحدث، يمكن استخدام قائمة مُهيِّئة بدلاً من <code>‎std::make_pair‎</code>:
</p>

<p>
	الإصدار C++‎ 11
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5119_62" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;utility&gt;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">pair</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pun">&gt;</span><span class="pln"> foo</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">{</span><span class="pln">a</span><span class="pun">+</span><span class="pln">b</span><span class="pun">,</span><span class="pln"> a</span><span class="pun">-</span><span class="pln">b</span><span class="pun">};</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكن جلب القيم الفردية للزوج المعاد باستخدام العضوين <code>‎first‎</code> و <code>‎second‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5119_64" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">pair</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pun">&gt;</span><span class="pln"> mrvs </span><span class="pun">=</span><span class="pln"> foo</span><span class="pun">(</span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">12</span><span class="pun">);</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> mrvs</span><span class="pun">.</span><span class="pln">first </span><span class="pun">+</span><span class="pln"> mrvs</span><span class="pun">.</span><span class="pln">second </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></pre>

<p>
	سيكون الناتج:
</p>

<pre class="ipsCode">
<strong>10 
</strong></pre>

<h3>
	استخدام المصفوفات <code>std::array</code>
</h3>

<p>
	الإصدار ≥ C++‎ 11
</p>

<p>
	يُمكن لِمَصفوفة ما (<code>‎std::array‎</code>) أن تُجمّع معًا عددًا ثابتًا من القيم لغرض إعادتها، ويجب أن يكون عدد العناصر معروفًا عند التصريف، كذلك يجب أن تكون جميع القيم المعادة من نفس النوع:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5119_66" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">array</span><span class="pun">&lt;</span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">&gt;</span><span class="pln"> bar</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> a </span><span class="pun">+</span><span class="pln"> b</span><span class="pun">,</span><span class="pln"> a </span><span class="pun">-</span><span class="pln"> b</span><span class="pun">,</span><span class="pln"> a </span><span class="pun">*</span><span class="pln"> b</span><span class="pun">,</span><span class="pln"> a </span><span class="pun">/</span><span class="pln"> b </span><span class="pun">};</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تستبدل هذه الطريقةُ نمطَ صياغة <a data-ss1617022546="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-7-%D8%A7%D9%84%D9%85%D8%B5%D9%81%D9%88%D9%81%D8%A7%D8%AA-%D9%81%D9%8A-cpp-r891/" rel="">المصفوفات</a> في لغة ‏C‏‏ (<code>‎int bar[4]‎</code>)، فميزتها أنّه يمكن الآن استخدام دوال عديدة من مكتبة القوالب القياسية std الخاصة بلغة <code>‎c++‎</code>، كما أنها توفر عدّة دوال تابعة مفيدة مثل <code>‎at‎</code> وهو تابع وصول آمن يتحقَّق من الحدود، وتابع <code>‎size‎</code> الذي يعيد حجم المصفوفة.
</p>

<h3>
	استخدام مُكرّرات الخرج
</h3>

<p>
	يمكن إعادة عدة قيم من نفس النوع بتمرير <a data-ss1617022546="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-7-%D8%A7%D9%84%D9%85%D8%B5%D9%81%D9%88%D9%81%D8%A7%D8%AA-%D9%81%D9%8A-cpp-r891/" rel="">مُكرّر</a> خرْج إلى الدالة، ويشيع هذا في الدوال العامة مثل خوارزميات المكتبة القياسية. انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5119_68" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">Incrementable</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> </span><span class="typ">OutputIterator</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> generate_sequence</span><span class="pun">(</span><span class="typ">Incrementable</span><span class="pln"> from</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Incrementable</span><span class="pln"> to</span><span class="pun">,</span><span class="pln"> </span><span class="typ">OutputIterator</span><span class="pln"> output</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Incrementable</span><span class="pln"> k </span><span class="pun">=</span><span class="pln"> from</span><span class="pun">;</span><span class="pln"> k </span><span class="pun">!=</span><span class="pln"> to</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">k</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">*</span><span class="pln">output</span><span class="pun">++</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> k</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	مثال تطبيقي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5119_70" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> digits</span><span class="pun">;</span><span class="pln">
generate_sequence</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">10</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">back_inserter</span><span class="pun">(</span><span class="pln">digits</span><span class="pun">));</span><span class="pln">
</span><span class="com">// {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}</span></pre>

<h3>
	استخدام المتجهات <code>‎std::vector‎</code>
</h3>

<p>
	تساعد المتجهات (<code>‎std::vector‎</code>) في إعادة عدد غير ثابت من المتغيّرات من نفس النوع. انظر المثال التالي حيث نستخدم <code>‎int‎</code> كنوع بيانات، رغم أن المتجهات يمكنها احتواء أي نوع قابل للنسخ، ستعيد الدالة كل الأعداد الصحيحة بين <code>a</code> و <code>b</code> في متجه ما، وسيكون الحد الأقصى من العناصر التي يمكن للدالة أن تعيدها هو <code>std::vector::max_size</code> على فرض أن ذاكرة النظام تستطيع احتواء ذلك الحجم.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5119_72" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;vector&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> fillVectorFrom</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> temp</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> a</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;=</span><span class="pln"> b</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        temp</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="pln">i</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> temp</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ستعيِّن الشيفرة التالية المتجه الذي أنشئ داخل الدالة والمملوء إلى المتجه <code>v</code> الجديد، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5119_74" style="">
<span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> v </span><span class="pun">=</span><span class="pln"> fillVectorFrom</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">10</span><span class="pun">);</span><span class="pln">
    </span><span class="com">// "1 2 3 4 5 6 7 8 9 10 "</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">size</span><span class="pun">();</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> v</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" "</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	هذا الدرس جزء من <a data-ss1617022546="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة دروس عن C++‎</a>.
</p>

<p>
	ترجمة -بتصرّف- للفصل Chapter 24: Returning several values from والفصل Chapter 28: C++ function "call by value" vs. "call by reference"‎ من كتاب <a data-ss1617022546="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">899</guid><pubDate>Fri, 26 Jun 2020 18:09:00 +0000</pubDate></item><item><title>&#x623;&#x647;&#x645; &#x627;&#x644;&#x643;&#x644;&#x645;&#x627;&#x62A; &#x627;&#x644;&#x645;&#x641;&#x62A;&#x627;&#x62D;&#x64A;&#x629; (Keywords) &#x648;&#x62F;&#x644;&#x627;&#x644;&#x627;&#x62A;&#x647;&#x627; &#x641;&#x64A; Cpp</title><link>https://academy.hsoub.com/programming/cpp/%D8%A3%D9%87%D9%85-%D8%A7%D9%84%D9%83%D9%84%D9%85%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D9%81%D8%AA%D8%A7%D8%AD%D9%8A%D8%A9-keywords-%D9%88%D8%AF%D9%84%D8%A7%D9%84%D8%A7%D8%AA%D9%87%D8%A7-%D9%81%D9%8A-cpp-r898/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_06/14.jpg.194c7a494f9931f1ce45063999c377e3.jpg" /></p>

<p>
	الكلمات المفتاحية هي كلمات لها معنى محدّد في C++‎ ولا يمكن استخدامها كمُعرّفات، كذلك لا يجوز إعادة تعريف الكلمات المفتاحية باستخدام المعالج المُسبق (preprocessor) في أيّ وحدة ترجمة تتضمن ترويسة المكتبة القياسية. لكن بأي حال فإن الكلمات المفتاحية تفقد معناها المميِّز داخل السمات (attributes).
</p>

<h2>
	decltype
</h2>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	تعيد الكلمة المفتاحية <code>decltype</code> نوع المعامَل الخاص بها، والذي لا يُقيَّم.
</p>

<ul>
<li>
		إذا كان المعامَل <code>‎e‎</code> اسمًا بدون أي أقواس إضافية، فإنّ <code>‎decltype(e)‎</code> ستكون النوع المُصرَّح للمعامل <code>‎e‎</code>. انظر المثال التالي حيث تكون <code>v</code> من نوع <code>&lt;vector&lt;int</code>:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_8" style="">
<span class="typ">int</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="pun">&lt;</span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">x</span><span class="pun">)&gt;</span><span class="pln"> v</span><span class="pun">(</span><span class="lit">100</span><span class="pun">,</span><span class="pln"> x</span><span class="pun">);</span></pre>

<ul>
<li>
		إذا كان المعامَل <code>‎e‎</code> عضوًا من صنفٍ، ولم يكن محاطًا بأيّة أقواس، فإنّ <code>‎decltype(e)‎</code> ستكون النوع المُصرّح للعضو الذي تم الوصول إليه. انظر المثال التالي حيث تكون <code>y</code> من نوع <code>int</code> رغم أن <code>s.x</code> ثابتة.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_10" style="">
<span class="kwd">struct</span><span class="pln"> S </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> S s</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">s</span><span class="pun">.</span><span class="pln">x</span><span class="pun">)</span><span class="pln"> y</span><span class="pun">;</span></pre>

<ul>
<li>
		تعيد <code>‎decltype(e)‎</code> في جميع الحالات الأخرى كلًّا من نوع وصنف التعبير <code>‎e‎</code> كما يلي:
	</li>
	<li>
		إذا كانت <code>‎e‎</code> تعبيرًا يساريًا (lvalue) من النوع <code>‎T‎</code>، فإنّ <code>‎decltype(e)‎</code> ستساوي <code>‎T&amp;‎</code>.
	</li>
	<li>
		إذا كانت <code>‎e‎</code> تعبيرًا من فئة (xvalue ) من <code>‎T‎</code>، فإنّ <code>‎decltype(e)‎</code> ستساوي <code>‎T&amp;&amp;‎</code>.
	</li>
	<li>
		إذا كانت <code>‎e‎</code> تعبيرًا من فئة (prvalue) من <code>‎T‎</code>، فإنّ <code>‎decltype(e)‎</code> ستساوي <code>‎T‎</code>.
	</li>
</ul>
<p>
	وهذا يشمل حالة الأقواس الخارجية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_12" style="">
<span class="typ">int</span><span class="pln"> f</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> g</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">f</span><span class="pun">())</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> f</span><span class="pun">();</span><span class="pln"> 
</span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">g</span><span class="pun">())</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> g</span><span class="pun">();</span><span class="pln">
</span><span class="kwd">decltype</span><span class="pun">((</span><span class="pln">x</span><span class="pun">))</span><span class="pln"> c </span><span class="pun">=</span><span class="pln"> x</span><span class="pun">;</span><span class="pln"> </span></pre>

<p>
	لاحظ في المثال السابق أن <code>a</code> من نوع <code>int</code>، و <code>b</code> من نوع <code>&amp;int</code>، و <code>c</code> من نوع <code>&amp;int</code> كذلك لأن <code>x</code> قيمة يسارية (lvalue).
</p>

<p>
	<strong>الإصدار ≥ C++‎ 14</strong>
</p>

<p>
	يستنتج الشكل الخاص <code>‎decltype(auto)‎</code> نوعَ متغيّر ما من مُهيِّئه (initializer) أو نوع الإعادة لدالة من تعليمات <code>‎return‎</code> الموجودة في تعريف الدالة، باستخدام قواعد الاستنتاج الخاصة بـ <code>‎decltype‎</code> بدلاً من قواعد <code>‎auto‎</code>. انظر المثال التالي حيث تكون <code>y</code> من نوع <code>int</code>، و <code>z</code> من نوع <code>const int</code>، وهو النوع المصرح من <code>x</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_14" style="">
<span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">123</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> y </span><span class="pun">=</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">decltype</span><span class="pun">(</span><span class="kwd">auto</span><span class="pun">)</span><span class="pln"> z </span><span class="pun">=</span><span class="pln"> x</span><span class="pun">;</span></pre>

<h2>
	const
</h2>

<p>
	تمثل <code>const</code> مُحدِّدًا للنوع، وتنتج النسخة المؤهلة ثبوتيًا من نوع ما عند تطبيقها على ذلك النوع.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_16" style="">
<span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">123</span><span class="pun">;</span><span class="pln">
x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">456</span><span class="pun">;</span><span class="pln"> </span><span class="com">// خطأ</span><span class="pln">
</span><span class="typ">int</span><span class="pun">&amp;</span><span class="pln"> r </span><span class="pun">=</span><span class="pln"> x</span><span class="pun">;</span><span class="pln"> </span><span class="com">// خطأ</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> S </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">();</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> g</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> S s</span><span class="pun">;</span><span class="pln">
s</span><span class="pun">.</span><span class="pln">f</span><span class="pun">();</span><span class="pln"> </span><span class="com">// خطأ</span><span class="pln">
s</span><span class="pun">.</span><span class="pln">g</span><span class="pun">();</span><span class="pln"> </span><span class="com">// OK</span></pre>

<h3>
	تجنّب تكرار الشيفرة البرمجية في التوابع الجالبة (Getter Methods)
</h3>

<p>
	يمكن زيادة تحميل التوابع التي لا تختلف إلا في مؤهِّل‏‏ <code>‎const‎</code>، وقد تحتاج أحيانًا إلى نسختين من الجالب الذي يعيد مرجعًا إلى عضو ما. ولنفرض أن <code>‎Foo‎</code> صنف له تابعان يُجرِيان عمليّات متطابقة ويُعيدان مرجعًا إلى كائن من النوع <code>‎Bar‎</code>، فإنه يكون على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_18" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">Bar</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="typ">GetBar</span><span class="pun">(</span><span class="pln"> </span><span class="com">/* some arguments */</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="com">/* افعل شيئا ما هنا */</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> bar</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Bar</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="typ">GetBar</span><span class="pun">(</span><span class="pln"> </span><span class="com">/* some arguments */</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">/* افعل شيئا ما هنا */</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> bar</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="com">// ...</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	الفرق الوحيد بينهما هو أنّ أحد التابعين غير ثابت (non-const) ويُعيد مرجعًا غير ثابت كذلك يمكن استخدامه لتعديل الكائن، أما الثاني فهو ثابت ويعيد مرجعًا ثابتًا.
</p>

<p>
	وقد نميل إلى استدعاء أحد التابعيْن من التابع الآخر من أجل تجنّب تكرار الشيفرة، لكن لا يمكننا استدعاء تابع غير ثابت من تابع ثابت، وإنما نستطيع استدعاء تابع ثابت من آخر غير ثابت، وسيتطلّب ذلك استخدام "const_cast" لإزالة مُؤهِّل <code>const</code>. انظر الحل فيما يلي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_20" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Bar</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="typ">GetBar</span><span class="pun">(</span><span class="pln"> </span><span class="com">/*arguments*/</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">const_cast</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Bar</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const_cast</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">
            </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">this</span><span class="pun">)</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="typ">GetBar</span><span class="pun">(</span><span class="pln"> </span><span class="com">/*arguments*/</span><span class="pln"> </span><span class="pun">));</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Bar</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="typ">GetBar</span><span class="pun">(</span><span class="pln"> </span><span class="com">/*arguments*/</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">/* افعل شيئًا ما هنا */</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> foo</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	في الشيفرة أعلاه، استدعينا نسخة ثابتة من <code>‎GetBar‎</code> من التابع المتغير <code>‎GetBar‎</code> عن طريق تحويله إلى النوع الثابت <code>const_cast&lt;const Foo*&gt;(this)‎</code>. وبما أننا استدعينا تابعًا ثابتًا من آخرَ متغيرٍ فإن الكائن نفسه يكون متغيرًا، ويُسمح بإهمال الثابت. انظر المثال التالي لمزيد من الشرح:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_22" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Student</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
</span><span class="kwd">char</span><span class="pun">&amp;</span><span class="pln"> </span><span class="typ">GetScore</span><span class="pun">(</span><span class="kwd">bool</span><span class="pln"> midterm</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">const_cast</span><span class="pun">&lt;</span><span class="kwd">char</span><span class="pun">&amp;&gt;(</span><span class="kwd">const_cast</span><span class="pun">&lt;</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Student</span><span class="pun">*&gt;(</span><span class="kwd">this</span><span class="pun">)-&gt;</span><span class="typ">GetScore</span><span class="pun">(</span><span class="pln">midterm</span><span class="pun">));</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">&amp;</span><span class="pln"> </span><span class="typ">GetScore</span><span class="pun">(</span><span class="kwd">bool</span><span class="pln"> midterm</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">midterm</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> midtermScore</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">else</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> finalScore</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
</span><span class="kwd">char</span><span class="pln"> midtermScore</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">char</span><span class="pln"> finalScore</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="com">// كائن متغير</span><span class="pln">
</span><span class="typ">Student</span><span class="pln"> a</span><span class="pun">;</span></pre>

<p>
	هنا نستطيع الإسناد إلى المرجع، وتُستدعى نسخة متغيرة من GetScore، انظر بقية المثال:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_24" style="">
<span class="pln">a</span><span class="pun">.</span><span class="typ">GetScore</span><span class="pun">(</span><span class="kwd">true</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">'B'</span><span class="pun">;</span><span class="pln">
a</span><span class="pun">.</span><span class="typ">GetScore</span><span class="pun">(</span><span class="kwd">false</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">'A'</span><span class="pun">;</span><span class="pln">

</span><span class="com">// كائن ثابت</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Student</span><span class="pln"> b</span><span class="pun">(</span><span class="pln">a</span><span class="pun">);</span></pre>

<p>
	لا زلنا نستطيع استدعاء تابع <code>GetScore</code> الخاص بكائن ثابت لأننا زدنا تحميل النسخة الثابتة منه -أي من GetScore-، انظر بقية المثال:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_26" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> b</span><span class="pun">.</span><span class="typ">GetScore</span><span class="pun">(</span><span class="kwd">true</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> b</span><span class="pun">.</span><span class="typ">GetScore</span><span class="pun">(</span><span class="kwd">false</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	الدوال التوابع الثابتة (Const member functions)
</h3>

<p>
	يمكن التصريح أنّ توابع صنف ما ثابتة (<code>‎const‎</code>)، وذلك سيخبر المصرّف والقارئ أنّ هذا التابع لن يعدّل الكائن، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_28" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">MyClass</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> myInt_</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> myInt</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> myInt_</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> setMyInt</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> myInt</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> myInt_ </span><span class="pun">=</span><span class="pln"> myInt</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	يكون مؤشر <code>this</code> في دالة التابع <code>const</code> من نوع <code>‎const MyClass *‎</code> وليس <code>‎MyClass *‎</code>، وهذا يعني أننا لا نستطيع تغيير أي متغير عضو داخل الدالة وإلا سيعطي المصرفُ تحذيرًا، لذا لا يمكن التصريح بأن <code>‎setMyInt‎</code> ثابتة.
</p>

<p>
	كذلك يجب التصريح أنّ الدوال التوابع ثابتة <code>const</code> متى كان ذلك ممكنًا، ذلك أن التوابع الثابتة فقط هي التي يمكن أن تُستدعى على النوع <code>‎const MyClass‎</code>. أيضًا لا يمكن التصريح عن التوابع الساكنة <code>‎static‎</code> أنها ثابتة <code>const</code>، ذلك أنّ التابع الساكن ينتمي إلى صنف ولا يستدعى على الكائن، فلا يمكنه تعديل المتغيّرات الداخلية للكائن، وعليه يكون التصريح عن توابع <code>static</code> على أنها <code>const</code> حشوًا لا فائدة منه.
</p>

<h3>
	المتغيرات المحلية الثابتة
</h3>

<p>
	تبين الشيفرة التالية كيفية التصريح عن متغيرات محلية ثابتة، وكيفية استخدامها، حيث يكون <code>a</code> من نوع <code>const int</code> فلا يمكن تغييره، وعليه لا يمكن تعيين قيمة جديدة إلى متغير ثابت. انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_30" style="">
<span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">15</span><span class="pun">;</span><span class="pln">
a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">12</span><span class="pun">;</span><span class="pln"> </span><span class="com">// خطأ، لا يمكن تعيين قيمة جديدة لمتغير ثابت</span><span class="pln">
a </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln"> </span><span class="com">// خطأ، لا يمكن تعيين قيمة جديدة لمتغير ثابت</span></pre>

<p>
	جمع المراجع مع المؤشّرات:
</p>

<p>
	في الشيفرة التالية، لا يمكن ربط مرجع غير ثابت بمتغير ثابت كما ترى في السطر الأول، لكن في السطر الثاني يمكن ذلك بما أن <code>c</code> مرجع ثابت. انظر:
</p>

<pre class="ipsCode">
int &amp;b = a;
const int &amp;c = a;
</pre>

<p>
	بالمثل، لا يمكن جمع مؤشر إلى قيمة متغيرة مع متغير ثابت، لكن يمكن ذلك كما ترى في السطر الثاني بما أن <code>e</code> مؤشر إلى قيمة ثابتة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_32" style="">
<span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="pln">d </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">a</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="pln">e </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">a </span></pre>

<p>
	يمكن ربط <code>e</code> بـ <code>*int</code> أو <code>*const int</code> بما أنها مؤشر غير ثابت إلى قيمة ثابتة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_34" style="">
<span class="typ">int</span><span class="pln"> f </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
e </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">f</span><span class="pun">;</span></pre>

<p>
	<code>e</code> مؤشر إلى قيمة ثابتة، وذلك يعني أن القيمة التي تشير إليها لا يمكن تغييرها بتحصيل <code>e</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_36" style="">
<span class="pun">*</span><span class="pln">e </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span></pre>

<p>
	يمكن تغيير القيمة التالية من خلال تحصيل مؤشر إلى قيمة غير ثابتة:
</p>

<pre class="ipsCode">
int *g = &amp;f;
*g = 1;
</pre>

<h3>
	المؤشرات الثابتة
</h3>

<p>
	في المثال التالي، <code>const int* pA = &amp; a</code> هو مؤشر إلى قيمة ثابتة، ولا يمكن تغيير قيمة <code>a</code>، بينما <code>int* const pB = &amp;a</code> مؤشر ثابت، ويمكن تغيير قيمة <code>a</code> لكن لا يمكن تغيير قيمة المؤشر نفسه. انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_38" style="">
<span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pun">*</span><span class="pln"> pA </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> a</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pun">*</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> pB </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">a</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pun">*</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> pC </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">a</span><span class="pun">;</span><span class="pln">  </span><span class="com">// مؤشر ثابت إلى قيمة ثابتة.</span><span class="pln">

</span><span class="com">// خطأ، لا يمكن التعيين إلى مرجع ثابت</span><span class="pln">
</span><span class="pun">*</span><span class="pln">pA </span><span class="pun">=</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
pA </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">b</span><span class="pun">;</span><span class="pln">
</span><span class="pun">*</span><span class="pln">pB </span><span class="pun">=</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
</span><span class="com">// خطأ، لا يمكن التعيين إلى مؤشر ثابت</span><span class="pln">
pB </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">b</span><span class="pun">;</span><span class="pln">
</span><span class="com">// خطأ، لا يمكن التعيين إلى مرجع ثابت</span><span class="pln">
</span><span class="pun">*</span><span class="pln">pC </span><span class="pun">=</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
</span><span class="com">// خطأ، لا يمكن التعيين إلى مؤشر ثابت</span><span class="pln">
pC </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">b</span><span class="pun">;</span></pre>

<h2>
	asm
</h2>

<p>
	تأخذ الكلمة المفتاحية <code>‎asm‎</code> مُعامَلًا واحدًا، وينبغي أن يكون سلسلة نصّية حرفيّة، ويتغيّر معناها بحسب التنفيذ ولكنها تُمرَّر عادةً إلى مُجمِّع التنفيذ (implementation's assembler)، مع دمج خَرْج المُجمِّع في وحدة الترجمة.
</p>

<p>
	التعليمة <code>‎asm‎</code> هي تعريفٌ وليست تعبيرًا، لذلك قد تظهر إمّا في نطاق كتلة (block scope) أو نطاق فضاء الاسم - namespace scope - بما في ذلك النطاق العام، ولكن قد لا تظهر <code>‎asm‎</code> داخل دالة تعبير ثابت <code>‎constexpr‎</code> نظرًا لتعذُّر تقييد التجميع المُضمّّن (inline assembly) بواسطة قواعد لغة C++‎. انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_40" style="">
<span class="pun">[</span><span class="pln">
    </span><span class="pun">[</span><span class="pln">noreturn</span><span class="pun">]</span><span class="pln">
</span><span class="pun">]</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> halt_system</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">asm</span><span class="pun">(</span><span class="str">"hlt"</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	char
</h2>

<p>
	تمثّل <code>char</code> نوعًا عدديًّا صحيحًا ذا حجم كبير بقدر يسمح بتخزين أي عضو من مجموعة محارف التطبيق الأساسية، ويُمكن أن يكون مؤشَّرًا - signed - (ولديه نطاق يتراوح بين -127 و +127، مضمنة) أو غير مؤشَّر - unsigned - (ولديه نطاق يتراوح بين 0 و 255 مُضمّنة).
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_42" style="">
<span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> zero </span><span class="pun">=</span><span class="pln"> </span><span class="str">'0'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> one </span><span class="pun">=</span><span class="pln"> zero </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> newline </span><span class="pun">=</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> one </span><span class="pun">&lt;&lt;</span><span class="pln"> newline</span><span class="pun">;</span><span class="pln"> </span><span class="com">// تطبع 1 متبوع بسطر جديد</span></pre>

<h2>
	char16_t
</h2>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	تمثل <code>char16_t</code> نوعًا عدديًا صحيحًا غير مؤشَّر له نفس حجم ومحاذاة النوع <code>‎uint_least16_t‎</code>، وعليه فهو كبير بما يكفي ليحتوي قيمةً من النوع UTF-16.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_44" style="">
<span class="kwd">const</span><span class="pln"> </span><span class="typ">char16_t</span><span class="pln"> message</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> u</span><span class="str">"你好，世界\\n"</span><span class="pun">;</span><span class="pln"> </span><span class="com">// مرحبا بالعالم  بالصينية</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="pln">message</span><span class="pun">)/</span><span class="kwd">sizeof</span><span class="pun">(</span><span class="typ">char16_t</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\\n"</span><span class="pun">;</span><span class="pln"> </span><span class="com">// 7 يطبع</span></pre>

<h2>
	char32_t
</h2>

<p>
	<strong>الإصدار ++ C++‎ 11</strong>
</p>

<p>
	تمثّل <code>char32_t</code> نوعًا عدديًا صحيحًا غير مؤشّر له نفس حجم ومحاذاة <code>‎uint_least32_t‎</code>، وعليه فهو كبير بما يكفي لِيحتوي قيمة من النوع UTF-32.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_46" style="">
<span class="kwd">const</span><span class="pln"> </span><span class="typ">char32_t</span><span class="pln"> full_house</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> U</span><span class="str">"▯▯▯▯▯"</span><span class="pun">;</span><span class="pln"> 
</span><span class="com">// محارف ليست من المستوى الأساسي متعدد اللغات</span><span class="pln">
</span><span class="com">// non-BMP characters</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="pln">full_house</span><span class="pun">)/</span><span class="kwd">sizeof</span><span class="pun">(</span><span class="typ">char32_t</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\\n"</span><span class="pun">;</span><span class="pln"> </span><span class="com">// يطبع 6</span></pre>

<h2>
	int
</h2>

<p>
	تمثّل <code>int</code> نوعًا عدديًا صحيحًا مؤشّرًا يختلف حجمه بحسب معماريّة بيئة التنفيذ، ويشمل نطاقه من -32767 إلى +32767 مُضمّنة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_48" style="">
<span class="typ">int</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> y </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> z </span><span class="pun">=</span><span class="pln"> x </span><span class="pun">+</span><span class="pln"> y</span><span class="pun">;</span></pre>

<p>
	يمكن دمج <code>int</code> مع <code>‎unsigned‎</code> و <code>‎short‎</code> و <code>‎long‎</code> و <code>‎long long‎</code> للحصول على أنواع عددية صحيحة أخرى.
</p>

<h2>
	wchar_t
</h2>

<p>
	تمثل <code>wchar_t</code> نوعًا عدديًا صحيحًا كبيرًا بما يكفي لتمثيل جميع الأحرف في مجموعة المحارف الممتدة (extended character set) المدعومة، ولا يمكن افتراض أن <code>wchar_t</code> تستخدم ترميزًا معينًا مثل UTF-16 لاختلاف طريقة تقديمها، وهي تُستخدم عادةً عندما تحتاج إلى تخزين أحرف من خارج ASCII لأنّ حجمها أكبر من <code>‎char‎</code>. انظر المثال التالي الذي يعرض عبارة "مرحبا بالعالم\n" بعدة لغات:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_50" style="">
<span class="com">// الأمهرية</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">wchar_t</span><span class="pln"> message_ahmaric</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> L</span><span class="str">"▯▯▯ ▯▯▯ \\n"</span><span class="pun">;</span><span class="pln"> 
</span><span class="com">// الصينية</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">wchar_t</span><span class="pln"> message_chinese</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> L</span><span class="str">"你好，世界\\n"</span><span class="pun">;</span><span class="pln">
</span><span class="com">// العبرية</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">wchar_t</span><span class="pln"> message_hebrew</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> L</span><span class="str">"םלוע םולש\\n"</span><span class="pun">;</span><span class="pln"> 
</span><span class="com">// الروسية</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">wchar_t</span><span class="pln"> message_russian</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> L</span><span class="str">"Привет мир\\n"</span><span class="pun">;</span><span class="pln"> 
 </span><span class="com">// التاميلية</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">wchar_t</span><span class="pln"> message_tamil</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> L</span><span class="str">"ஹலே◌◌ா உலகம◌்\\n"</span><span class="pun">;</span></pre>

<h2>
	ﬂoat
</h2>

<p>
	تمثّل <code>ﬂoat</code> نوعًا من الأعداد العشرية، وهي أصغر أنواع الأعداد العشرية في C++‎.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_52" style="">
<span class="typ">float</span><span class="pln"> area</span><span class="pun">(</span><span class="typ">float</span><span class="pln"> radius</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">float</span><span class="pln"> pi </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3.14159f</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> pi </span><span class="pun">*</span><span class="pln"> radius </span><span class="pun">*</span><span class="pln"> radius</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	double
</h2>

<p>
	تمثّل <code>double</code> نوعًا من الأعداد العشرية، ويشمل نطاقها ‎float‎<code>، وتشير عند دمجها مع </code>‎long‎ <code>إلى النوع </code>‎long double‎ <code>الذي يتضمّن نطاقه نطاقَ </code>‎double.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_54" style="">
<span class="kwd">double</span><span class="pln"> area</span><span class="pun">(</span><span class="kwd">double</span><span class="pln"> radius</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> pi </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3.141592653589793</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> pi </span><span class="pun">*</span><span class="pln"> radius </span><span class="pun">*</span><span class="pln"> radius</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	long
</h2>

<p>
	تمثل <code>long</code> نوعًا عدديًّا صحيحًا مؤشَّرًا بطول يماثل <code>‎int‎</code> على الأقل، ويتضمن نطاقه المجال من -2147483647 إلى +2147483647 مُضمّنة (أي، من - (2 ^ 31 - 1) إلى + (2 ^ 31 - 1))، ويمكن كتابة هذا النوع أيضًا بالصيغة <code>‎long int‎</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_56" style="">
<span class="kwd">const</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> approx_seconds_per_year </span><span class="pun">=</span><span class="pln"> </span><span class="lit">60L</span><span class="pun">*</span><span class="lit">60L</span><span class="pun">*</span><span class="lit">24L</span><span class="pun">*</span><span class="lit">365L</span><span class="pun">;</span></pre>

<p>
	يشير التركيب <code>‎long double‎</code> إلى نوع عددي ذي فاصلة عائمة، والذي له النطاق الأوسع مقارنة بأنواع الأعداد العشرية الأخرى.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_58" style="">
<span class="kwd">long</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> area</span><span class="pun">(</span><span class="kwd">long</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> radius</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> pi </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3.1415926535897932385L</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> pi </span><span class="pun">*</span><span class="pln"> radius </span><span class="pun">*</span><span class="pln"> radius</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	عند تكرار <code>‎long‎</code> مرتين كما في <code>‎long long‎</code> فإنّها تشير إلى نوع عددي صحيح مؤشَّر طوله يساوي على الأقل طوال <code>‎long‎</code>، ويشمل نطاقه على الأقل المجال من -9223372036854775807 إلى +9223372036854775807 مُضمّنة (أي، من - (2 ^ 63 - 1) إلى + (2 ^ 63 - 1)).
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_60" style="">
<span class="com">// دعم أحجام ملفات تصل إلى 2 تيرا بايت</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> max_file_size </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2LL</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">40</span><span class="pun">;</span></pre>

<h2>
	short
</h2>

<p>
	تشير <code>short</code> إلى نوع عددي صحيح مؤشَّر طوله يساوي <code>‎char‎</code> على الأقل، ويتضمن نطاقه المجال من -32767 إلى +32767 مُضمّنة، ويمكن كتابة هذا النوع أيضًا هكذا <code>‎short int‎</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_62" style="">
<span class="com">// خلال السنة الماضية</span><span class="pln">
</span><span class="kwd">short</span><span class="pln"> hours_worked</span><span class="pun">(</span><span class="kwd">short</span><span class="pln"> days_worked</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">8</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> days_worked</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	bool
</h2>

<p>
	تمثّل bool نوعًا عدديًا صحيحًا يمكن أن تكون قيمته إما <code>‎true‎</code> أو <code>‎false‎</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_64" style="">
<span class="kwd">bool</span><span class="pln"> is_even</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> x </span><span class="pun">%</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">bool</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> is_even</span><span class="pun">(</span><span class="lit">47</span><span class="pun">);</span><span class="pln"> </span><span class="com">// false</span></pre>

<h2>
	signed
</h2>

<p>
	<code>signed</code> هي كلمة مفتاحية تكون جزءًا من أسماء بعض الأنواع العددية الصحيحة.
</p>

<ul>
<li>
		عند استخدامها بمفردها، تعيد النوع <code>‎int‎</code> ضمنيًا، وفي هذه الحالة فإنّ الأنواع <code>‎signed‎</code> و <code>‎signed int‎</code> و <code>‎int‎</code> متماثلة.
	</li>
	<li>
		عند دمجها مع <code>‎char‎</code> تعيد النوع <code>‎signed char‎</code>، وهو نوع مختلف عن <code>‎char‎</code>، حتى لو كانت <code>‎char‎</code> مؤشّرة، كما يحتوي نطاق <code>‎signed char‎</code> بين -127 إلى +127 مضمّنة على الأقل.
	</li>
	<li>
		عند دمجها مع <code>‎short‎</code> أو <code>‎long‎</code> أو <code>‎long long‎</code>، فستكون مجرّد تكرار، لأنّ هذه الأنواع مؤشَّرة سلفًا.
	</li>
	<li>
		لا يمكن دمج <code>‎signed‎</code> مع <code>‎bool‎</code> أو <code>‎wchar_t‎</code> أو <code>‎char16_t‎</code> أو <code>‎char32_t‎</code>.
	</li>
</ul>
<p>
	مثال:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_66" style="">
<span class="kwd">signed</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> celsius_temperature</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cin </span><span class="pun">&gt;&gt;</span><span class="pln"> celsius_temperature</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">celsius_temperature </span><span class="pun">&lt;</span><span class="pln"> </span><span class="pun">-</span><span class="lit">35</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"cold day, eh?\n"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	unsigned
</h2>

<p>
	<code>unsigned</code> هي مُحدِّد نوع يتطلب النسخة غير المؤشّرة (unsigned) من نوع عددي صحيح.
</p>

<ul>
<li>
		عند استخدامها بمفردها، فإنّها تعيد النوع <code>‎int‎</code> ضمنيًا،، وعليه يتماثل كل من <code>‎unsigned‎</code> و <code>‎unsigned int‎</code> في النوع.
	</li>
	<li>
		يختلف النوع <code>‎unsigned char‎</code> عن <code>‎char‎</code> حتى لو كان الأخير غير مؤشّر، ويمكن استخدامه لتمثيل الأعداد الصحيحة الأصغر من 255.
	</li>
	<li>
		يمكن أيضًا دمج <code>‎unsigned‎</code> مع <code>‎short‎</code> أو <code>‎long‎</code> أو <code>‎long‎</code> <code>‎long‎</code>. ولا يمكن دمجها مع <code>‎bool‎</code> أو <code>‎wchar_t‎</code> أو <code>‎char16_t‎</code> أو <code>‎char32_t‎</code>.
	</li>
</ul>
<p>
	مثال:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_68" style="">
<span class="kwd">char</span><span class="pln"> invert_case_table</span><span class="pun">[</span><span class="lit">256</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="pun">...,</span><span class="pln">
    </span><span class="str">'a'</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'b'</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'c'</span><span class="pun">,</span><span class="pln">
    </span><span class="pun">...,</span><span class="pln">
    </span><span class="str">'A'</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'B'</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'C'</span><span class="pun">,</span><span class="pln">
    </span><span class="pun">...</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">char</span><span class="pln"> invert_case</span><span class="pun">(</span><span class="kwd">char</span><span class="pln"> c</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">unsigned</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> index </span><span class="pun">=</span><span class="pln"> c</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> invert_case_table</span><span class="pun">[</span><span class="pln">index</span><span class="pun">];</span><span class="pln">
    </span><span class="com">// مباشرة invert_case_table[c] إعادة</span><span class="pln">
    </span><span class="com">// مؤشّرة char  غير مناسب إن كانت </span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لاحظ في المثال السابق أن إعادة <code>[invert_case_table[c</code> غير مناسب إن كانت <code>char</code> مؤشَّرة.
</p>

<h2>
	كلمات النوع المفتاحية
</h2>

<h3>
	class
</h3>

<p>
	تشمل استخدامات كلمة <code>class</code> المفتاحية ما يلي:
</p>

<ol>
<li>
		تقديم تعريف نوع الصنف:
	</li>
</ol>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_70" style="">
<span class="kwd">class</span><span class="pln"> foo </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> get_x</span><span class="pun">();</span><span class="pln">f
    </span><span class="kwd">void</span><span class="pln"> set_x</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> new_x</span><span class="pun">);</span><span class="pln">
</span><span class="pun">};</span></pre>

<ol start="2">
<li>
		تقديم مُحدِّد مفصّل للنوع يشير إلى أنّ الاسم التالي هو اسم لنوع صنف (class type)، وإن كان اسم الصنف قد صُرِّح عنه سلفًا فيمكن العثور عليه حتى لو كان مخفيًا باسم آخر، أما إن لم يكن قد صُرح عنه فسيُعدّ مُصرّحًا عنه بشكل لاحق (forward-declared).
	</li>
</ol>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_72" style="">
<span class="kwd">class</span><span class="pln"> foo</span><span class="pun">;</span><span class="pln"> </span><span class="com">// مُحدِّد مفصّل للنوع -&gt; تصريح لاحق</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> bar </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        bar</span><span class="pun">(</span><span class="pln">foo </span><span class="pun">&amp;</span><span class="pln"> f</span><span class="pun">);</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> baz</span><span class="pun">();</span></pre>

<p>
	لدينا في الشيفرة التالية محدِّد مفصَّل للنوع، وتصريح لاحق آخر، لاحظ أن الصنف ودالة <code>()void baz</code> لهما نفس الاسم:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_74" style="">
<span class="kwd">class</span><span class="pln"> baz</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> foo </span><span class="pun">{</span><span class="pln">
    bar b</span><span class="pun">;</span></pre>

<p>
	في الشيفرة التالية، مُحدِّد نوع مفصّل يشير إلى الصنف وليس إلى الدالة التي لها نفس الاسم:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_76" style="">
<span class="pln">    </span><span class="kwd">friend</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> baz</span><span class="pun">;</span><span class="pln"> 
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        foo</span><span class="pun">();</span><span class="pln">
</span><span class="pun">};</span></pre>

<ol start="3">
<li>
		تقديم نوع المعاملات في تصريح القالب.
	</li>
</ol>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_78" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> T</span><span class="pun">&amp;</span><span class="pln"> min</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> T</span><span class="pun">&amp;</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> T</span><span class="pun">&amp;</span><span class="pln"> y</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> b </span><span class="pun">&lt;</span><span class="pln"> a </span><span class="pun">?</span><span class="pln"> b </span><span class="pun">:</span><span class="pln"> a</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span></pre>

<ol start="4">
<li>
		في التصريح عن معامل قالب القالب (template template parameter)، تسبق الكلمة المفتاحيّة <code>‎class‎</code> اسمَ المعامل، ونظرًا لأنّ الوسيط الخاص بمعامل قالب القالب لا يمكن أن يكون إلّا قالب صنف (class template)، فلا حاجة لاستخدام <code>‎class‎</code> هنا، لكن رغم هذا فإنّ لغة C++‎ تُوجِبه. لاحظ في المثال التالي كيف تُستخدم <code>class</code> الأخيرة في الصف الأول، حيث يكون <code>U</code> هو معامل قالب القالب.
	</li>
</ol>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_80" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> U </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        U </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="pln">do_it</span><span class="pun">();</span><span class="pln">
        U </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="pln">do_it</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span></pre>

<ol start="5">
<li>
		لاحظ أنّه يمكن الجمع بين النقطتين الثانية والثالثة في نفس التصريح، انظر المثال التالي حيث لا يُشترط أن تكون <code>bar</code> قد ظهرت من قبل:
	</li>
</ol>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_82" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">class</span><span class="pln"> foo </span><span class="pun">{};</span><span class="pln">
foo </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> bar </span><span class="pun">&gt;</span><span class="pln"> x</span><span class="pun">;</span><span class="pln"> </span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>.
</p>

<ol start="6">
<li>
		في تصريح أو تعريف نوع عددي <code>enum</code>، تصرّح أن التعداد هو تعدادٌ نطاقي (scoped enum):
	</li>
</ol>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_84" style="">
<span class="kwd">enum</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Format</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    TEXT</span><span class="pun">,</span><span class="pln">
    PDF</span><span class="pun">,</span><span class="pln">
    OTHER</span><span class="pun">,</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">Format</span><span class="pln"> f </span><span class="pun">=</span><span class="pln"> F</span><span class="pun">::</span><span class="pln">TEXT</span><span class="pun">;</span></pre>

<h3>
	enum
</h3>

<p>
	هناك عدة أدوار للكلمة المفتاحية <code>enum</code>، وهي كالتالي:
</p>

<ol>
<li>
		تقديم تعريف لنوع عددي.
	</li>
</ol>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_86" style="">
<span class="kwd">enum</span><span class="pln"> </span><span class="typ">Direction</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    UP</span><span class="pun">,</span><span class="pln">
    LEFT</span><span class="pun">,</span><span class="pln">
    DOWN</span><span class="pun">,</span><span class="pln">
    RIGHT
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">Direction</span><span class="pln"> d </span><span class="pun">=</span><span class="pln"> UP</span><span class="pun">;</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	قد تُلحَق <code>‎enum‎</code> اختياريًا في الإصدار C++‎ 11 بكلمة <code>‎class‎</code> المفتاحية أو <code>‎struct‎</code> من أجل تعريف نوع تعداد نطاقي، ويمكن تحديد النوع الأساسي (underlying type) لكلٍّ من الأنواع العددية النطاقية وغير النطاقية عبر وضع <code>‎: T‎</code> بعد اسم النوع العددي، إذ تشير <code>‎T‎</code> إلى نوع عددي صحيح.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_88" style="">
<span class="kwd">enum</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Format</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
TEXT</span><span class="pun">,</span><span class="pln">
PDF</span><span class="pun">,</span><span class="pln">
OTHER
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">Format</span><span class="pln"> f </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Format</span><span class="pun">::</span><span class="pln">TEXT</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">enum</span><span class="pln"> </span><span class="typ">Language</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
ENGLISH</span><span class="pun">,</span><span class="pln">
FRENCH</span><span class="pun">,</span><span class="pln">
OTHER
</span><span class="pun">};</span></pre>

<p>
	كذلك يمكن أن تُسبق العدّادات (Enumerators) في أنواع <code>‎enum‎</code> العاديّة بعامِل النطاق (scope operator). لكن رغم ذلك ستُعدّ ضمن النطاق الذي عُرِّف فيه <code>‎enum‎</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_90" style="">
<span class="typ">Language</span><span class="pln"> l1</span><span class="pun">,</span><span class="pln"> l2</span><span class="pun">;</span><span class="pln">
l1 </span><span class="pun">=</span><span class="pln"> ENGLISH</span><span class="pun">;</span><span class="pln">
l2 </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Language</span><span class="pun">::</span><span class="pln">OTHER</span><span class="pun">;</span></pre>

<ol start="2">
<li>
		تقديم مُحدّد مفصَّل للنوع يشير إلى أنّ الاسم التالي هو اسم نوع عددي سبق التصريح عنه. (لا يمكن استخدام مُحدّد مفصَّل للنوع في تصريح لاحق لنوع عددي)، ويمكن تسمية نوع عددي بهذه الطريقة حتى لو كان يخفيه اسم آخر. انظر في المثال التالي كيف أن صيغة <code>Foo foo = FOO</code> غير صحيح لأن <code>Foo</code> تشير إلى الدالة، بينما <code>enum Foo foo = FOO</code> صحيحة لأنها تشير إلى النوع العددي.
	</li>
</ol>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_92" style="">
<span class="kwd">enum</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    FOO
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Foo</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="typ">Foo</span><span class="pln"> foo </span><span class="pun">=</span><span class="pln"> FOO</span><span class="pun">;</span><span class="pln"> 
</span><span class="kwd">enum</span><span class="pln"> </span><span class="typ">Foo</span><span class="pln"> foo </span><span class="pun">=</span><span class="pln"> FOO</span><span class="pun">;</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<ol start="3">
<li>
		تقديم تصريح عن نوع عددي مبهم يصرّح عن نوع عددي لكن دون تعريفه، وقد يعيد التصريح عن نوع عددي سبق التصريح عنه، ويمكن كذلك أن يُصرِّح لاحقًا (forward declaration) عن نوع عدديّ لم يسبق التصريح عنه. لكن من الناحية الأخرى، لا يمكن لنوع سبق التصريح عنه كنوع نطاقي أن يُعاد التصريح عنه كنوع عددي وتحويله إلى نوع غير نطاقي، والعكس صحيح. ويجب أن تتوافق جميع تصريحات النوع العددي على مستوى النوع الأساسي (underlying type). كذلك يجب تحديد النوع الأساسي بشكل صريح عند التصريح اللاحق عن نوع عددي غير نطاقي،ذلك أنه لا يمكن أن يُستنتج إلى حين التعرّف على قيم العدّادات. انظر المثال التالي حيث يكون النوع الأساسي هو <code>int</code>:
	</li>
</ol>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_94" style="">
<span class="kwd">enum</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Format</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="typ">Format</span><span class="pln"> f</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">enum</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Format</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    TEXT</span><span class="pun">,</span><span class="pln">
    PDF</span><span class="pun">,</span><span class="pln">
    OTHER</span><span class="pun">,</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">enum</span><span class="pln"> </span><span class="typ">Direction</span><span class="pun">;</span><span class="pln"> </span><span class="com">// غير صالح، يجب تحديد النوع الأساسي</span></pre>

<h3>
	struct
</h3>

<p>
	الكلمة المفتاحية <code>struct</code> مشابهة للكلمة <code>‎class‎</code>، بيد أنّ هناك بعض الاختلافات، وهي:
</p>

<ul>
<li>
		في حال تعريف نوعِ صنفٍ باستخدام الكلمة المفتاحية <code>‎struct‎</code> فستكون صلاحيات الوصول الافتراضية للأصناف الأساسية (bases) والأعضاءِ عامةً أي <code>‎public‎</code> وليس <code>‎private‎</code>.
	</li>
	<li>
		لا يمكن استخدام <code>‎struct‎</code> للتصريح عن معامل نوع قالب (template type parameter) أو قالب معامِل القالب بل <code>‎class‎</code> فقط هو من يمكنه ذلك.
	</li>
</ul>
<h3>
	union
</h3>

<p>
	هناك عدة أدوار للكلمة المفتاحية <code>union</code>، وهي كالتالي:
</p>

<ol>
<li>
		تقديم تعريف نوع الاتحاد (union type) :
	</li>
</ol>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_96" style="">
<span class="com">// POSIX مثال من</span><span class="pln">
</span><span class="kwd">union</span><span class="pln"> sigval </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln">        sival_int</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln">        </span><span class="pun">*</span><span class="pln">sival_ptr</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span></pre>

<ol start="2">
<li>
		تقديم محدِّد مفصّل للنوع يشير إلى أنّ الاسم التالي هو اسم لنوع اتحاد، وإذا صُرِّح عن اسم الاتحاد سلفًا فيمكن العثور عليه حتى لو كان يخفيه اسم آخر، وإلا فسيكون مُصرَّحا عنه بشكل لاحق (forward-declared):
	</li>
</ol>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_98" style="">
<span class="kwd">union</span><span class="pln"> foo</span><span class="pun">;</span><span class="pln"> </span><span class="com">// محدِّد مفصّل للنوع  -&gt; تصريح اللاحق.</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> bar </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        bar</span><span class="pun">(</span><span class="pln">foo </span><span class="pun">&amp;</span><span class="pln"> f</span><span class="pun">);</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> baz</span><span class="pun">();</span><span class="pln">
</span><span class="kwd">union</span><span class="pln"> baz</span><span class="pun">;</span><span class="pln">
</span><span class="com">// baz() الصنف له نفس اسم الدالة</span><span class="pln">
</span><span class="kwd">union</span><span class="pln"> foo </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">long</span><span class="pln"> l</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">union</span><span class="pln"> baz </span><span class="pun">*</span><span class="pln"> b</span><span class="pun">;</span><span class="pln"> </span><span class="com">// محدّد نوع مفصل يشير إلى الصنف وليس الدالة ذات الاسم نفسه</span><span class="pln">
</span><span class="pun">};</span></pre>

<h2>
	الكلمة المفتاحية mutable
</h2>

<h3>
	تعابير لامدا القابلة للتغيير
</h3>

<p>
	يُمنع إجراء العمليات غير الثابتة <code>non-const</code> على تعابير لامدا (λ) بسبب كون العامل الضمني <code>‎operator()‎</code> ثابتًا (<code>const</code>)، ويمكن التصريح عن تعبير (λ) كقيمة قابلة للتغير لجعل <code>‎operator()‎</code> غير ثابت (<code>non-const</code>)، ومن ثم يمكننا التعديل على الأعضاء. انظر المثال التالي حيث نحصل على خطأ لأن <code>‎operator()‎</code> ثابت فلا يمكننا تعديل الأعضاء.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_100" style="">
<span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> bad_counter </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">a</span><span class="pun">]</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> a</span><span class="pun">++;</span><span class="pln"> 
</span><span class="pun">};</span></pre>

<p>
	لاحظ الآن كيف يمكننا تعديل الأعضاء بعد جعل تعبير لامدا قابلًا للتغيير:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_102" style="">
<span class="kwd">auto</span><span class="pln"> good_counter </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">a</span><span class="pun">]()</span><span class="pln"> </span><span class="kwd">mutable</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> a</span><span class="pun">++;</span><span class="pln"> </span><span class="com">// OK</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
good_counter</span><span class="pun">();</span><span class="pln"> </span><span class="com">// 0</span><span class="pln">
good_counter</span><span class="pun">();</span><span class="pln"> </span><span class="com">// 1</span><span class="pln">
good_counter</span><span class="pun">();</span><span class="pln"> </span><span class="com">// 2</span></pre>

<h3>
	معدِّلات الصنف المتغيرة
</h3>

<p>
	تُستخدَم المُعدِّلات القابلة للتغيير <code>‎mutable‎</code> في هذا السياق للإشارة إلى إمكانية تعديل حقل كائن ثابت دون التأثير على حالة الكائن المرئية من الخارج، فيفضَّل استخدام كلمة <code>mutable</code> المفتاحية إن كنت تريد أن تخزّن نتيجةَ عمليّات حسابية مكلّفة وطويلة بشكل مؤقتٍ (caching).
</p>

<p>
	وإذا كان لديك حقل مقفول - lock data ﬁeld - (مثال: <code>‎std::unique_lock‎</code>)، والذي يُقفَل ويُفتَح داخل تابع ثابت، فستكون هذه الكلمة المفتاحية مفيدة في هذه الحالة كذلك.
</p>

<p>
	لكن لا تستخدم هذه الكلمة لإلغاء ثباتيّة (const-ness) كائن، انظرالمثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_104" style="">
<span class="kwd">class</span><span class="pln"> pi_calculator </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">double</span><span class="pln"> get_pi</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">pi_calculated</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                </span><span class="kwd">return</span><span class="pln"> pi</span><span class="pun">;</span><span class="pln">
            </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                </span><span class="kwd">double</span><span class="pln"> new_pi </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
                </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">1000000000</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                    </span><span class="com">// new_pi بعض الحسابات لتحسين </span><span class="pln">
                </span><span class="pun">}</span><span class="pln">

                pi </span><span class="pun">=</span><span class="pln"> new_pi</span><span class="pun">;</span><span class="pln">
                pi_calculated </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
                </span><span class="kwd">return</span><span class="pln"> pi</span><span class="pun">;</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">mutable</span><span class="pln"> </span><span class="kwd">bool</span><span class="pln"> pi_calculated </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">mutable</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> pi </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	لاحظ أنه في الشيفرة السابقة، إن كان كل من <code>pi</code> و <code>pi_calculated</code> لا يقبلان التعديل فسنحصل على خطأ من المصرِّف إذ لا يمكن تعديل حقل غير قابل للتغيير في تابع ثابت.
</p>

<h2>
	كلمات مفتاحية أخرى
</h2>

<h3>
	void
</h3>

<p>
	تمثل <code>void</code> نوعًا فارغًا غير مكتمل، ويستحيل لكائن أن يكون من النوع <code>‎void‎</code>، ولا مصفوفات من هذا النوع ولا حتى مرجع إليه، وإنّما يُستخدم كنوع إعادة للدوال التي لا تُعيد أيّ شيء.
</p>

<ol>
<li>
		عند استخدام <code>void</code> كنوع للقيمة المعادة من دالة فإنّها تشير إلى أنّ تلك الدالة لا تُعيد أيّ قيمة، وعند استخدامها في قائمة معاملاتِ دالةٍ فإنها تدلّ على أنّ تلك الدالة لا تأخذ أيّ معاملات (مثلًا: <code>‎int main()‎</code> و <code>‎int main(void)‎</code> متكافئتان) وأُجيزَت هذه الصياغة للتوافق مع C حيث تصريحات الدوال لها معنى مختلف عن مثيلاتها C++‎. أما عند استخدامها في تصريح مؤشّر فذلك يعني أنّ ذلك المؤشّر عام (universal).
	</li>
	<li>
		إذا كان المؤشّر من النوع <code>void *‎</code> فإنّه يستطيع الإشارة إلى أيّ متغير لم يُصرّح عنه باستخدام <code>const</code> أو <code>volatile</code>، ولا يمكن تحصيل (dereferencing) مؤشّر فارغ (من النوع <code>void *‎</code>) إلا إن حُوِّل إلى نوع آخر. كذلك يمكن تحويل مؤشر فارغ إلى أيّ نوع آخر من مؤشّرات البيانات. وهذه الميزة تجعل النوع <code>‎void*‎</code> مناسبًا لأنواع معيّنة من واجهات مسح الأنواع (type-erasing interfaces) غير الآمنة (type-unsafe)، مثل السياقات العامة في الواجهات البرمجية (<abbr title="Application Programming Interface | واجهة برمجية">API</abbr>) الشبيهة بـC مثل <code>‎qsort‎</code> و <code>‎pthread_create‎</code>.
	</li>
	<li>
		يمكن أن يشير المؤشّر الفارغ إلى دالة، ولكن ليس إلى عضو من صنف في C++‎.
	</li>
</ol>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_106" style="">
<span class="kwd">void</span><span class="pln"> vobject</span><span class="pun">;</span><span class="pln"> </span><span class="com">// C2182</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> </span><span class="pun">*</span><span class="pln">pv</span><span class="pun">;</span><span class="pln"> </span><span class="com">// okay</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="pln">pint</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        pv </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">i</span><span class="pun">;</span><span class="pln">
        </span><span class="com">// C++ لكنه ضروري في  C التحويل اختياري في </span><span class="pln">
        pint </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> pv</span><span class="pun">;</span></pre>

<p>
	يمكن تحويل أيّ تعبير ليكون من نوع <code>‎void‎</code>، وهو ما يسمى تعبير القيمة المهملة (discarded-value expression):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_108" style="">
<span class="kwd">static_cast</span><span class="str">&lt;void&gt;</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">printf</span><span class="pun">(</span><span class="str">"Hello, %s!\n"</span><span class="pun">,</span><span class="pln"> name</span><span class="pun">));</span><span class="pln"> </span><span class="com">// إهمال القيمة المعادة</span></pre>

<p>
	قد يكون هذا مفيدًا للإشارة إلى أنّ قيمة التعبير ليست مهمّة، وأنّ التعبير يجب تقييمه لأجل آثاره الجانبية فقط.
</p>

<h3>
	Volatile
</h3>

<p>
	الكلمة المفتاحية <code>Volatile</code> هي مؤهِّلُ نوع (type qualiﬁer) يمكن استخدامه للتصريح بأنّ كائنًا ما قابلٌ لأن يُغيَّر في البرنامج من قِبل عتاد الحاسوب وتنتج النسخة المتغيرة (volatile-qualiﬁed) من نوع عند تطبيقها عليه، ويلعب التأهيل المتغير (Volatile qualiﬁcation) نفس الدور الذي تلعبه <code>‎const‎</code> في نظام الأنواع، لكن <code>‎volatile‎</code> لا تمنع تعديل الكائنات، بل تفرض على المُصرّف معاملة عمليّات الوصول إلى هذه الكائنات كآثار جانبية.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_110" style="">
<span class="kwd">volatile</span><span class="pln"> declarator </span><span class="pun">;</span></pre>

<p>
	في المثال أدناه، إذا لم تكن <code>‎memory_mapped_port‎</code> متغيّرة (Volatile) فيمكن للمصرّف تحسين الدالة بحيث لا ينفّذُ إلا الكتابة النهائية، وسيكون ذلك غير صحيح إذا كانت <code>‎sizeof(int)‎</code> أكبر من 1، ويجبر التأهيل المتغير <code>‎volatile‎</code> المُصرّفَ على معاملة عمليات كتابة <code>‎sizeof(int)‎</code> على أنها تأثيرَات جانبية، وعليه ينفّذها جميعهًا بالترتيب.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_112" style="">
<span class="kwd">extern</span><span class="pln"> </span><span class="kwd">volatile</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> memory_mapped_port</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> write_to_device</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">*</span><span class="pln"> p </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">reinterpret_cast</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">x</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="typ">int</span><span class="pun">);</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        memory_mapped_port </span><span class="pun">=</span><span class="pln"> p</span><span class="pun">[</span><span class="pln">i</span><span class="pun">];</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	virtual
</h3>

<p>
	تصرح الكلمة المفتاحية <code>virtual</code> عن دالة وهمية، أو عن صنف أساسي وهمي (virtual base class).
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_114" style="">
<span class="kwd">virtual</span><span class="pln"> </span><span class="pun">[</span><span class="pln">type</span><span class="pun">-</span><span class="pln">specifiers</span><span class="pun">]</span><span class="pln"> member</span><span class="pun">-</span><span class="pln">function</span><span class="pun">-</span><span class="pln">declarator
</span><span class="kwd">virtual</span><span class="pln"> </span><span class="pun">[</span><span class="pln">access</span><span class="pun">-</span><span class="pln">specifier</span><span class="pun">]</span><span class="pln"> base</span><span class="pun">-</span><span class="kwd">class</span><span class="pun">-</span><span class="pln">name</span></pre>

<p>
	<strong>المعامِلات</strong>
</p>

<ul>
<li>
		<code>type-speciﬁers</code>: تحدّد نوع القيمة المعادة من دالة التابع الوهمي.
	</li>
	<li>
		<code>member-function-declarator</code>: تصرّح عن دالة تابع.
	</li>
	<li>
		<code>access-speciﬁer</code>: تحدّد مستوى الوصول إلى الصنف الأساسي: عام (public) أو محمي (protected ) أو خاص (private)، ويمكن أن تظهر قبل أو بعد الكلمة المفتاحية <code>virtual</code>.
	</li>
	<li>
		<code>base-class-name</code>: تعرّف نوع صنف سبق تعريفه.
	</li>
</ul>
<h3>
	مؤشر this
</h3>

<p>
	<code>this</code> هو مؤشّر يمكن الوصول إليه فقط داخل دوال التوابع المتغيرة (non static) لنوع أو صنف أو اتحاد أو بِنية. ويشير إلى الكائن الذي استُدعِي عليه التابع، ولا تملك دوال التوابع الساكنة مؤشر <code>this</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_116" style="">
<span class="kwd">this</span><span class="pun">-&gt;</span><span class="pln">member</span><span class="pun">-</span><span class="pln">identifier</span></pre>

<p>
	المؤشّر <code>this</code> ليس جزءًا من الكائن نفسه ولا يُحسب في تعليمة الحجم <code>sizeof</code> للكائن، بل يُمرَّر عنوان ذلك الكائن من قبل المُصرِّف كوسيط مخفي إلى الدالة عند استدعاء دالة تابع غير ساكن على كائن ما. انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_118" style="">
<span class="pln">myDate</span><span class="pun">.</span><span class="pln">setMonth</span><span class="pun">(</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">);</span></pre>

<p>
	يمكن تأويله بهذه الطريقة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_120" style="">
<span class="pln">setMonth</span><span class="pun">(</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">myDate</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">);</span></pre>

<p>
	معظم استخدامات <code>this</code>ضمنيّة، ويُسمح باستخدام <code>this</code> صراحة عند الرجوع إلى أعضاء الصنف رغم أنّ ذلك غير ضروري. انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_122" style="">
<span class="kwd">void</span><span class="pln"> </span><span class="typ">Date</span><span class="pun">::</span><span class="pln">setMonth</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> mn</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    month </span><span class="pun">=</span><span class="pln"> mn</span><span class="pun">;</span><span class="pln"> </span><span class="com">// هذه العبارات الثلاث متكافئة</span><span class="pln">
    </span><span class="kwd">this</span><span class="pun">-&gt;</span><span class="pln"> month </span><span class="pun">=</span><span class="pln"> mn</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">(</span><span class="pln"> </span><span class="pun">*</span><span class="kwd">this</span><span class="pun">).</span><span class="pln">month </span><span class="pun">=</span><span class="pln"> mn</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يُستخدم التعبير <code>‎</code>*this لإعادة الكائن الحالي من دالة تابع، ويُستخدم هذا المؤشّر أيضًا لمنع التنكيس أو الإشارة الذاتية ( self-reference):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_124" style="">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln"> </span><span class="pun">&amp;</span><span class="typ">Object</span><span class="pln"> </span><span class="pun">!=</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// لا تنفّذ في حال الإشارة الذاتية.</span></pre>

<h3>
	عبارات try و throw و catch
</h3>

<ol>
<li>
		تُستخدم عبارات <code>try</code> و <code>throw</code> و <code>catch</code> لمُعالجة الاعتراضات (Exceptions) في C++‎،
	</li>
	<li>
		أولًا، استخدم كتلة <code>try</code> لتضع فيها تعليمة أو أكثر من التي قد تطلق اعتراضًا.
	</li>
	<li>
		يشير تعبير <code>throw</code> إلى أنّ شيئًا اعتراضيًا قد حدث في كتلة <code>try</code> -غالبًا ما يكون خطأ-، ويمكنك استخدام كائن من أيّ نوع كمعامَل لـ <code>throw</code>، ويُستخدم هذا الكائن لتوصيل معلومات بخصوص الخطأ. ويوصى في معظم الحالات باستخدام الصنف <code>std::exception</code> أو أحد الأصناف المشتقة منه والمُعرّفة في المكتبة القياسية، أما إذا لم تكن تلك الاستثناءات مناسبة فيمكنك اشتقاق اعتراض خاص بك من <code>std::exception</code>.
	</li>
	<li>
		استخدم كتلةَ <code>catch</code> واحدة أو أكثر بعد كتلة <code>try</code> لمعالجة الاعتراضات التي يمكن إطلاقها، إذ تحدّد كل كتلة من كتل <code>catch</code> نوعًا من الاستثناءات التي يمكنها معالجتها. انظر:
	</li>
</ol>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_126" style="">
<span class="typ">MyData</span><span class="pln"> md</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">try</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// شيفرة قد تؤدّي إلى إطلاق اعتراض</span><span class="pln">
    md </span><span class="pun">=</span><span class="pln"> </span><span class="typ">GetNetworkResource</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> networkIOException</span><span class="pun">&amp;</span><span class="pln"> e</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// شيفرة ستُنفّذ في حال إطلاق اعتراض من نوع</span><span class="pln">
    </span><span class="com">// networkIOException </span><span class="pln">
    </span><span class="com">// try في كتلة ...</span><span class="pln">
    </span><span class="com">// عرض رسالة الخطأ الخاصة بالاعتراض</span><span class="pln">
    cerr </span><span class="pun">&lt;&lt;</span><span class="pln"> e</span><span class="pun">.</span><span class="pln">what</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> myDataFormatException </span><span class="pun">&amp;</span><span class="pln"> e</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// شيفرة تعالج بقيّة أنواع الاعتراضات</span><span class="pln">
    </span><span class="com">// ...</span><span class="pln">
    cerr </span><span class="pun">&lt;&lt;</span><span class="pln"> e</span><span class="pun">.</span><span class="pln">what</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// throw الصيغة التالية تُظهر عبارة</span><span class="pln">
</span><span class="typ">MyData</span><span class="pln"> </span><span class="typ">GetNetworkResource</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// ...</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="typ">IOSuccess</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">throw</span><span class="pln"> networkIOException</span><span class="pun">(</span><span class="str">"Unable to connect"</span><span class="pun">);</span><span class="pln">
    </span><span class="com">// ...</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">readError</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">throw</span><span class="pln"> myDataFormatException</span><span class="pun">(</span><span class="str">"Format error"</span><span class="pun">);</span><span class="pln">
    </span><span class="com">// ...</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	الشيفرة التي تلي <code>try</code> هي الجزء المَحمِيّ من الشيفرة، ويطلق التعبير <code>throw</code> اعتراضًا، أمّا كتلة التعليمات البرمجية الموضوعة بعد <code>catch</code> فهي المسؤولة عن إمساك ومعالجة الاعتراض الذي أُطلق إذا توافقت الأنواع في تعبيرات <code>throw</code> و <code>catch</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_128" style="">
<span class="kwd">try</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">throw</span><span class="pln"> </span><span class="typ">CSomeOtherException</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(...)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// إمساك كل الاستثناءات</span><span class="pln">
    </span><span class="com">// معالجة الاستثناء جزئيا، ثم إعادة إطلاق الاستثناء ليُعالِجه معالِجٌ آخر</span><span class="pln">
    </span><span class="com">// ...</span><span class="pln">
    </span><span class="kwd">throw</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	friend
</h3>

<p>
	تغلف الأصناف المصممة جيدًا وظائفها لتخفي تفاصيلها في نفس الوقت الذي تقدم فيه واجهة نظيفة وبسيطة وموثقة جيدًا، وذلك يسهِّل التعديل أو إعادة التصميم طالما ظلت الواجهة كما هي. لكن قد تحتاج بعض الأصناف في الحالات الأكثر تعقيدًا إلى معرفة تفاصيل تطبيق بعضها البعض، ويتيح مفهوم الأصناف والدّوال الصديقة (Friend classes and functions) لها الوصول إلى تلك التفاصيل دون المساس بتغليف المعلومات.
</p>

<ol>
<li>
		يكون من المفيد أحيانًا أن تمنح حقّ الوصول لأعضاءِ صنفٍ ما إلى دالةٍ ليست من أعضاء ذلك الصنف، أو إلى جميع الأعضاء في صنف آخر، ولا يمكن إلّا لمنفِّذ الصنف أن يصرح عن أصدقائه، ولا يمكن أن يصرح صنف أنه صديق لصنف آخر، وبالمثل لا يمكن لدالة أن تصرح عن ذلك. استخدام كلمة <code>friend</code> واسم دالة غير عضو أو اسم صنف آخر في تعريف الصنف، وذلك لمنحه حق الوصول إلى الأعضاء الخاصّين والمحميّين في ذلك الصنف، كما يمكن التصريح عن معامِل نوع كصديق في تعريف قالب ما.
	</li>
	<li>
		إذا صرحت عن دالة صديقة لم يسبق التصريح عنها، فستُصدَّر تلك الدالة إلى النطاق المحيط غير الصنفي (enclosing nonclass scope).
	</li>
</ol>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_130" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="kwd">friend</span><span class="pln"> F
</span><span class="kwd">friend</span><span class="pln"> F</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">ForwardDeclared</span><span class="pun">;</span><span class="pln"> </span><span class="com">// اسم الصنف معروف</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">HasFriends</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">friend</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="typ">ForwardDeclared</span><span class="pun">::</span><span class="typ">IsAFriend</span><span class="pun">();</span><span class="pln"> </span><span class="com">// C2039 خطأ</span><span class="pln">
</span><span class="pun">};</span></pre>

<h3>
	الدوال الصديقة (friend functions)
</h3>

<ol>
<li>
		الدالة الصديقة هي دالة ليست عضوًا في صنف، ولكن لها حق الوصول إلى الأعضاء المحميّين والخواصّ في ذلك الصنف، ولا تُعدّ الدوال الصديقة من أعضاء الصنف بل هي دوال خارجية طبيعية تُمنح امتيازات وصول خاصّة.
	</li>
	<li>
		لا تدخل الدوال الصديقة في نطاق الصنف ولا تُستدعى باستخدام عوامل اختيار الأعضاء <code>.</code> و <code>‎-&gt;‎</code> إلّا إن كانت أعضاء من صنف آخر.
	</li>
	<li>
		يُصرَّح عن الدالّة الصديقة من قِبل الصنف الذي يمنح حق الوصول، ويمكن وضع تصريح الصداقة في أيّ مكان في تصريح الصنف، ولا يتأثّر التصريح بالكلمات المفتاحيّة الخاصّة المسؤولة عن التحكم في الوصول.
	</li>
</ol>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_132" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">

</span><span class="kwd">using</span><span class="pln"> </span><span class="kwd">namespace</span><span class="pln"> std</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Point</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">friend</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">ChangePrivate</span><span class="pun">(</span><span class="typ">Point</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">Point</span><span class="pun">(</span><span class="kwd">void</span><span class="pun">):</span><span class="pln"> m_i</span><span class="pun">(</span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">PrintPrivate</span><span class="pun">(</span><span class="kwd">void</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        cout </span><span class="pun">&lt;&lt;</span><span class="pln"> m_i </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> m_i</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> </span><span class="typ">ChangePrivate</span><span class="pln">  </span><span class="pun">(</span><span class="typ">Point</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    i</span><span class="pun">.</span><span class="pln">m_i</span><span class="pun">++;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Point</span><span class="pln"> sPoint</span><span class="pun">;</span><span class="pln">
    sPoint</span><span class="pun">.</span><span class="typ">PrintPrivate</span><span class="pun">();</span><span class="pln">
    </span><span class="typ">ChangePrivate</span><span class="pun">(</span><span class="pln">sPoint</span><span class="pun">);</span><span class="pln">
    sPoint</span><span class="pun">.</span><span class="typ">PrintPrivate</span><span class="pun">();</span><span class="pln">
    </span><span class="com">// الخرج 0</span><span class="pln">
    </span><span class="lit">1</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تستطيع الأصناف والبُنى أن تصرح عن أيّ دالة على أنها صديقة لها، وإذا كانت دالة ما صديقة لصنف معيّن، فإنها تصل إلى جميع أعضائه المحميّين (protected) والخواص (private)، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_134" style="">
<span class="com">// تصريح مسبق للدوال</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> friend_function</span><span class="pun">();</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> non_friend_function</span><span class="pun">();</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">PrivateHolder</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">PrivateHolder</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> val</span><span class="pun">):</span><span class="pln"> private_value</span><span class="pun">(</span><span class="pln">val</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> private_value</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// إعلان إحدى الدوال صديقة</span><span class="pln">
    </span><span class="kwd">friend</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> friend_function</span><span class="pun">();</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> non_friend_function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">PrivateHolder</span><span class="pln"> ph</span><span class="pun">(</span><span class="lit">10</span><span class="pun">);</span><span class="pln">
    </span><span class="com">// Compilation error: private_value is private.</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> ph</span><span class="pun">.</span><span class="pln">private_value </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> friend_function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// يُسمح للأصدقاء بالدخول إلى القيم الخاصة</span><span class="pln">
    </span><span class="typ">PrivateHolder</span><span class="pln"> ph</span><span class="pun">(</span><span class="lit">10</span><span class="pun">);</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> ph</span><span class="pun">.</span><span class="pln">private_value </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	مُعدِّلات الوصول لا تغيّر الدلالات الصديقة، وستكون الأعضاء العامة والمحمية والخاصّة لصنفٍ صديقٍ متكافئة كلها. كذلك لا تُورّث تصريحات الصداقة (Friend declarations)، فإن أنشأنا مثلًا صنفًا فرعيا من <code>‎PrivateHolder‎</code> … :
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_136" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">PrivateHolderDerived</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">PrivateHolder</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln"> </span><span class="typ">PrivateHolderDerived</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> val</span><span class="pun">):</span><span class="pln"> </span><span class="typ">PrivateHolder</span><span class="pun">(</span><span class="pln">val</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> derived_private_value </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	… ثم حاولنا الوصول إلى أعضائه، سنحصل على ما يلي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_138" style="">
<span class="kwd">void</span><span class="pln"> friend_function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">PrivateHolderDerived</span><span class="pln"> pd</span><span class="pun">(</span><span class="lit">20</span><span class="pun">);</span><span class="pln">
    </span><span class="com">// OK</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> pd</span><span class="pun">.</span><span class="pln">private_value </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// Compilation error: derived_private_value is private.</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> pd</span><span class="pun">.</span><span class="pln">derived_private_value </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لاحظ أنّ دالة التابع <code>‎PrivateHolderDerived‎</code> لا يمكنها الوصول إلى <code>‎PrivateHolder::private_value‎</code>، في حين أنّ الدوال الصديقة تستطيع ذلك.
</p>

<h3>
	التوابع الصديقة
</h3>

<p>
	يمكن جعل التوابع صديقة تمامًا مثل الدوال، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_140" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Accesser</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">void</span><span class="pln"> private_accesser</span><span class="pun">();</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">PrivateHolder</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">PrivateHolder</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> val</span><span class="pun">):</span><span class="pln"> private_value</span><span class="pun">(</span><span class="pln">val</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="kwd">friend</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Accesser</span><span class="pun">::</span><span class="pln">private_accesser</span><span class="pun">();</span><span class="pln">
    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> private_value</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Accesser</span><span class="pun">::</span><span class="pln">private_accesser</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">PrivateHolder</span><span class="pln"> ph</span><span class="pun">(</span><span class="lit">10</span><span class="pun">);</span><span class="pln">
    </span><span class="com">// الإعلان عن هذا التابع كصديق</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> ph</span><span class="pun">.</span><span class="pln">private_value </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	الصنف الصديق (Friend class)
</h3>

<p>
	يمكن الإعلان عن صنف بأكمله كصديق، ويعني ذلك أنّه يجوز لأيّ عضو من أعضاء الصنف الصديق الوصول إلى الأعضاء الخاصّة والمحمية للصنف الآخر، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_142" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Accesser</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">void</span><span class="pln"> private_accesser1</span><span class="pun">();</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> private_accesser2</span><span class="pun">();</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">PrivateHolder</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">PrivateHolder</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> val</span><span class="pun">):</span><span class="pln"> private_value</span><span class="pun">(</span><span class="pln">val</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="kwd">friend</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Accesser</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> private_value</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Accesser</span><span class="pun">::</span><span class="pln">private_accesser1</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">PrivateHolder</span><span class="pln"> ph</span><span class="pun">(</span><span class="lit">10</span><span class="pun">);</span><span class="pln">
    </span><span class="com">// OK</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> ph</span><span class="pun">.</span><span class="pln">private_value </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Accesser</span><span class="pun">::</span><span class="pln">private_accesser2</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">PrivateHolder</span><span class="pln"> ph</span><span class="pun">(</span><span class="lit">10</span><span class="pun">);</span><span class="pln">
    </span><span class="com">// OK</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> ph</span><span class="pun">.</span><span class="pln">private_value </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لا يمكن عكس التصريح بالصداقة بين الأصناف، فإن كان صنف A صديقًا لصنف B، فإنّ B لن يصبح تلقائيًّا صديقًا للصنف A. وإذا احتاجت الأصناف وصولًا خاصًا في كلا الاتجاهين فسيحتاجان كليهما إلى تصريحات صداقة. انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_144" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Accesser</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">void</span><span class="pln"> private_accesser1</span><span class="pun">();</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> private_accesser2</span><span class="pun">();</span><span class="pln">
    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> private_value </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">PrivateHolder</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">PrivateHolder</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> val</span><span class="pun">):</span><span class="pln"> private_value</span><span class="pun">(</span><span class="pln">val</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
    </span><span class="kwd">friend</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Accesser</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> reverse_accesse</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Accesser</span><span class="pln"> a</span><span class="pun">;</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> a</span><span class="pun">.</span><span class="pln">private_value</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> private_value</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	في المثال السابق، لاحظ كيف أن <code>Accessor</code> صديق للصنف <code>PrivateHolder</code>، لكن الأخير لا يستطيع الوصول إلى أعضاء الأول.
</p>

<h3>
	مصادقة أعضاء صنف
</h3>

<p>
	يوضّح المثال التالي كيفيّة مُصادَقة أعضاء صنف ما، حيث تكون <code>A::Func1</code> دالة صديقة للصنف <code>B</code>، لذا يمكنها الدخول إلى جميع أعضاء <code>B</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_146" style="">
<span class="kwd">class</span><span class="pln"> B</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> A </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> </span><span class="typ">Func1</span><span class="pun">(</span><span class="pln">B</span><span class="pun">&amp;</span><span class="pln"> b</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> </span><span class="typ">Func2</span><span class="pun">(</span><span class="pln">B</span><span class="pun">&amp;</span><span class="pln"> b</span><span class="pun">);</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> B </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> _b</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">friend</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> A</span><span class="pun">::</span><span class="typ">Func1</span><span class="pun">(</span><span class="pln">B</span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> A</span><span class="pun">::</span><span class="typ">Func1</span><span class="pun">(</span><span class="pln">B</span><span class="pun">&amp;</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> b</span><span class="pun">.</span><span class="pln">_b</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="com">// OK</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> A</span><span class="pun">::</span><span class="typ">Func2</span><span class="pun">(</span><span class="pln">B</span><span class="pun">&amp;</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> b</span><span class="pun">.</span><span class="pln">_b</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="com">// C2248</span></pre>

<h2>
	typename
</h2>

<ol>
<li>
		عند إلحاق اسم مؤهَّل بكلمة <code>‎typename‎</code> فإنها تشير إلى أنها اسم لنوع، وغالبًا ما يكون هذا ضروريًا في القوالب، خاصة عندما يكون مُحدِّد الاسم المتشعّب (nested name speciﬁer) نوعًا غير مستقل يخالف الاستنساخ الحالي. انظر المثال التالي حيث يعتمد <code>‎std::decay&lt;T&gt;‎</code> على معامل القالب <code>‎T‎</code>، فنحتاج إلى إسباق الاسم المؤهَّل كله بكلمة <code>typename</code> المفتاحية من أجل تسمية النوع المتشعّب <code>‎type‎</code>. راجع <a data-ss1617022547="1" href="https://stackoverflow.com/questions/610245/where-and-why-do-i-have-to-put-the-template-and-typename-keywords" rel="external nofollow">هذا الرابط</a> لتعرف أين تضع كلمات <code>template</code> و<code>typename</code> وأين أيضًا:
	</li>
</ol>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_148" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> decay_copy</span><span class="pun">(</span><span class="pln">T</span><span class="pun">&amp;&amp;</span><span class="pln"> r</span><span class="pun">)</span><span class="pln"> </span><span class="pun">-&gt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">decay</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;::</span><span class="pln">type</span><span class="pun">;</span></pre>

<ol start="2">
<li>
		تقدّم <code>‎typename‎</code> معامِلَ نوعٍ (type parameter) في تصريح القالب، وهي تماثل <code>class</code> في هذا السياق.
	</li>
</ol>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_150" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> T</span><span class="pun">&amp;</span><span class="pln"> min</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> T</span><span class="pun">&amp;</span><span class="pln"> x</span><span class="pun">,</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> T </span><span class="pun">&amp;</span><span class="pln"> y</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> b </span><span class="pun">&lt;</span><span class="pln"> a </span><span class="pun">?</span><span class="pln"> b </span><span class="pun">:</span><span class="pln"> a</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 17</strong>
</p>

<ol start="3">
<li>
		يمكن أيضًا استخدام <code>‎typename‎</code> عند التصريح عن معامِل قالب القالب (template template parameter)، سابقة بهذا اسم المعامل تمامًا مثل <code>‎class‎</code>.
	</li>
</ol>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_152" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> U </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        U</span><span class="str">&lt;int&gt;</span><span class="pun">::</span><span class="pln">do_it</span><span class="pun">();</span><span class="pln">
        U</span><span class="str">&lt;double&gt;</span><span class="pun">::</span><span class="pln">do_it</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span></pre>

<h2>
	explicit
</h2>

<p>
	عند تطبيق الكلمة المفتاحية <code>explicit</code> على مُنشئ ذي وسيط واحد، فإنها تمنع أن يُستخدَم ذلك المُنشئ لإجراء أيّ تحويلات ضمنية.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_154" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">MyVector</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">explicit</span><span class="pln"> </span><span class="typ">MyVector</span><span class="pun">(</span><span class="typ">uint64_t</span><span class="pln"> size</span><span class="pun">);</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">MyVector</span><span class="pln"> v1</span><span class="pun">(</span><span class="lit">100</span><span class="pun">);</span><span class="pln">    </span><span class="com">// OK</span><span class="pln">
</span><span class="typ">uint64_t</span><span class="pln"> len1 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">100</span><span class="pun">;</span><span class="pln">
</span><span class="typ">MyVector</span><span class="pln"> v2 </span><span class="pun">{</span><span class="pln">
    len1
</span><span class="pun">};</span><span class="pln"> </span><span class="com">// uint64_t من النوع len1 </span><span class="pln">
</span><span class="typ">int</span><span class="pln"> len2 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">100</span><span class="pun">;</span><span class="pln">
</span><span class="typ">MyVector</span><span class="pln"> v3 </span><span class="pun">{</span><span class="pln">
    len2
</span><span class="pun">};</span><span class="pln"> </span><span class="com">// uint64_t إلى  int  غير مسموح لأنه تحويل ضمني من النوع</span></pre>

<p>
	منذ إدخال قوائم المهيئات (initializer lists) في C++‎ 11، صار بالإمكان تطبيق <code>‎explicit‎</code> على أيّ مُنشئ بغضّ النظر عن عدد وسائطه. انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_156" style="">
<span class="kwd">struct</span><span class="pln"> S </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">explicit</span><span class="pln"> S</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> y</span><span class="pun">);</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
S f</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">{</span><span class="lit">12</span><span class="pun">,</span><span class="pln"> </span><span class="lit">34</span><span class="pun">};</span><span class="pln"> </span><span class="com">// صيغة غير صحيحة.</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> S</span><span class="pun">{</span><span class="lit">12</span><span class="pun">,</span><span class="pln"> </span><span class="lit">34</span><span class="pun">};</span><span class="pln"> </span><span class="com">// ok</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	عندما تُطبّق على دالّة تحويل (conversion function)، فإنّها تمنع استخدام تلك الدالّة لإجراء أيّ تحويلات ضمنية.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_158" style="">
<span class="kwd">class</span><span class="pln"> C </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
C</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">)</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> x</span><span class="pun">(</span><span class="pln">x</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="kwd">explicit</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="typ">int</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> x</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
C c</span><span class="pun">(</span><span class="lit">42</span><span class="pun">);</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> c</span><span class="pun">;</span><span class="pln"> </span><span class="com">// غير صحيح.</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> y </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="str">&lt;int&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">c</span><span class="pun">);</span><span class="pln"> </span><span class="com">// صيغة صحيحة لأنه تحويل صريح.</span></pre>

<h2>
	sizeof
</h2>

<p>
	<code>sizeof</code> هو عامل أحادي يعيد حجم معامَله بالبايت، وقد يكون يكون ذلك المعامَل تعبيرًا أو نوعًا، وإذا كان المعامَل تعبيرًا فلن يُقيَّم، وسيكون الحجم تعبيرًا ثابتًا من النوع <code>‎std::size_t‎</code>. أما إن كان العامل نوعًا، فيجب أن يوضع بين قوسين.
</p>

<ul>
<li>
		لا يجوز تطبيق <code>‎sizeof‎</code> على نوع دالّة (function type).
	</li>
	<li>
		لا يجوز تطبيق <code>‎sizeof‎</code> على نوع غير مكتمل، بما في ذلك <code>‎void‎</code>.
	</li>
	<li>
		إذا طُبِّق <code>sizeof</code> على نوع مرجعي مثل <code>‎T&amp;‎</code> أو <code>‎T&amp;&amp;‎</code>، فسيكون مكافئًا لـ <code>‎sizeof(T)‎</code>.
	</li>
	<li>
		عندما تُطبّق <code>‎sizeof‎</code> على نوع صنف فإنها تعيد عدد البايتات في كائن كامل من ذلك النوع، بما في ذلك أيّ بايت للحشو (padding bytes) في المنتصف أو في النهاية. لذا لا تساوي <code>‎sizeof‎</code> القيمة صفر أبدًا.
	</li>
	<li>
		حجم كل من النوع <code>‎char‎</code> و <code>‎signed char‎</code> و <code>‎unsigned char‎</code> يساوي واحد، لكن تذكّر أنّ البايت هو مقدار الذاكرة المطلوبة لتخزين كائن من النوع <code>‎char‎</code>، وهذا لا يعني بالضرورة أنه يساوي 8 بتّات (bits) لأنّ بعض الأنظمة تخزِّن كائنات <code>‎char‎</code> في مساحة أكبر من 8 بتات.
	</li>
</ul>
<p>
	كذلك، إذا كان <code>expr</code> تعبيرًا، فإنّ <code>‎sizeof(‎</code> expr <code>‎)‎</code> تكافئ <code>‎sizeof(T)‎</code>، حيث يمثّل <code>‎T‎</code> نوع التعبير <code>expr</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_160" style="">
<span class="typ">int</span><span class="pln"> a</span><span class="pun">[</span><span class="lit">100</span><span class="pun">];</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"The number of bytes in `a` is: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pln"> a</span><span class="pun">;</span><span class="pln">
memset</span><span class="pun">(</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pln"> a</span><span class="pun">);</span><span class="pln"> </span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	يعيد العامل <code>‎sizeof...‎</code> عدد العناصر في حُزمة معامِلات ما.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_162" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">...</span><span class="pln">T </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="pln">T </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="pun">...)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"f was called with "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">...(</span><span class="pln">T</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" arguments\n"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span></pre>

<h2>
	noexcept
</h2>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<ol>
<li>
		<code>noexcept</code> هو معامل أحاديٌّ يحدّد إمكانية نشرُ اعتراض كنتيجة لتقييم عامِله، لاحظ أنّ متون الدوال المُستدعاة لا تُفحَص، وعليه فقد تؤدي <code>‎noexcept‎</code> إلى نتائج غير متوقّعة، بالمثل فإن العامل لا يُقيَّم.
	</li>
</ol>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_164" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;stdexcept&gt;</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">throw</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">runtime_error</span><span class="pun">(</span><span class="str">"oops"</span><span class="pun">);</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> bar</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> S </span><span class="pun">{};</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
 std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> noexcept</span><span class="pun">(</span><span class="pln">foo</span><span class="pun">())</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln"> </span><span class="com">// يطبع صفرًا</span><span class="pln">
 std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> noexcept</span><span class="pun">(</span><span class="pln">bar</span><span class="pun">())</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln"> </span><span class="com">// يطبع صفرًا</span><span class="pln">
 std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> noexcept</span><span class="pun">(</span><span class="lit">1</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln"> </span><span class="com">// يطبع واحدًا</span><span class="pln">
 std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> noexcept</span><span class="pun">(</span><span class="pln">S</span><span class="pun">())</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln"> </span><span class="com">// يطبع واحدًا</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	رغم أنّ <code>‎bar()‎</code> في المثال السابق لن تطلق أيّ اعتراض إلا أنّ <code>‎noexcept(bar())‎</code> تبقى خاطئة (false)، والسبب أنّه لم يُحدَّد بشكل صريح أنّ <code>‎bar()‎</code> غير قادرة على نشر اعتراض.
</p>

<ol start="2">
<li>
		تحدّد <code>noexcept</code> عند التصريح عن دالّة إن كانت تلك الدالّة قادرة على نشر اعتراض أم لا، وإذا استُخدِمت وحدَها فإنها تعلن أنّ الدالة لا يمكنها نشر أيّ اعتراض، وإذا استُخدِمت مع وسيط موضوع بين قوسين فإنها تحدّد إن كانت الدالّة تستطيع أن تنشر اعتراض اعتمادًا على قيمة الوسيط الحقيقية.
	</li>
</ol>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_166" style="">
<span class="kwd">void</span><span class="pln"> f1</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">throw</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">runtime_error</span><span class="pun">(</span><span class="str">"oops"</span><span class="pun">);</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f2</span><span class="pun">()</span><span class="pln"> noexcept</span><span class="pun">(</span><span class="kwd">false</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">throw</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">runtime_error</span><span class="pun">(</span><span class="str">"oops"</span><span class="pun">);</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f3</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f4</span><span class="pun">()</span><span class="pln"> noexcept </span><span class="pun">{}</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f5</span><span class="pun">()</span><span class="pln"> noexcept</span><span class="pun">(</span><span class="kwd">true</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> f6</span><span class="pun">()</span><span class="pln"> noexcept </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">try</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
f1</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">runtime_error</span><span class="pun">&amp;)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	في هذا المثال، صرّحنا بأنّ <code>‎f4‎</code> و <code>‎f5‎</code> و <code>‎f6‎</code> لا يمكنها نشر الاعتراضات (Exceptions) -رغم أنّه يمكن إطلاق اعتراض أثناء تنفيذ <code>‎f6‎</code>، إلا أنّه سيُحصَر ولن يُسمح له بالانتشار خارج الدالّة-، وصرحنا كذلك أن <code>‎f2‎</code> تستطيع نشر اعتراض. ويكافئ حذف مُحدِّدات <code>‎noexcept‎</code> التعبيرَ ‎<code>noexcept(false)</code>‎‎، لذلك فقد صرحنا ضمنيًا أنّ <code>f1</code> و <code>f3</code> يمكنهما نشر الاعتراضات رغم أنّه لا يمكن إطلاق الاعتراضات أثناء تنفيذ <code>‎f3‎</code>.
</p>

<p>
	<strong>الإصدار ≥ C++‎ 17</strong>
</p>

<p>
	تتوقف قدرة دالة ما في حصر الاعتراضات (<code>‎noexcept‎</code>) على نوع تلك الدالة، ففي المثال أعلاه، تختلف أنواع <code>‎f1‎</code> و <code>‎f2‎</code> و <code>‎f3‎</code> عن <code>‎f4‎</code> و <code>‎f5‎</code> و <code>‎f6‎</code>، لذلك فإنّ <code>‎noexcept‎</code> مهمّة في مؤشّرات الدوالّ ووسائط القوالب وغير ذلك.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7569_168" style="">
<span class="kwd">void</span><span class="pln"> g1</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> g2</span><span class="pun">()</span><span class="pln"> noexcept </span><span class="pun">{}</span><span class="pln">
</span><span class="kwd">void</span><span class="pun">(</span><span class="pln"> </span><span class="pun">*</span><span class="pln">p1</span><span class="pun">)()</span><span class="pln"> noexcept </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">g1</span><span class="pun">;</span><span class="pln"> </span><span class="com">// غير صالح</span><span class="pln">
</span><span class="kwd">void</span><span class="pun">(</span><span class="pln"> </span><span class="pun">*</span><span class="pln">p2</span><span class="pun">)()</span><span class="pln"> noexcept </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">g2</span><span class="pun">;</span><span class="pln"> </span><span class="com">// تطابق الأنواع</span><span class="pln">
</span><span class="kwd">void</span><span class="pun">(</span><span class="pln"> </span><span class="pun">*</span><span class="pln">p3</span><span class="pun">)()</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">g1</span><span class="pun">;</span><span class="pln"> </span><span class="com">// تطابق الأنواع</span><span class="pln">
</span><span class="kwd">void</span><span class="pun">(</span><span class="pln"> </span><span class="pun">*</span><span class="pln">p4</span><span class="pun">)()</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">g2</span><span class="pun">;</span><span class="pln"> </span><span class="com">// تحويل ضمني</span></pre>

<p>
	هذا الدرس جزء من <a data-ss1617022547="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة دروس عن C++‎</a>.
</p>

<p>
	ترجمة -بتصرّف- للفصل Chapter 23: Keywords من كتاب <a data-ss1617022547="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>.
</p>
]]></description><guid isPermaLink="false">898</guid><pubDate>Wed, 24 Jun 2020 18:08:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629; &#x627;&#x644;&#x648;&#x635;&#x641;&#x64A;&#x629; (Metaprogramming) &#x641;&#x64A; Cpp</title><link>https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A7%D9%84%D9%88%D8%B5%D9%81%D9%8A%D8%A9-metaprogramming-%D9%81%D9%8A-cpp-r897/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_06/13.jpg.0fe7c21f2f2509255a63ec25289f2464.jpg" /></p>

<p>
	تشير البرمجة الوصفية (Metaprogramming) في C++‎ إلى استخدام وحدات الماكرو أو القوالب لتوليد شيفرة أثناء وقت التصريف (compile)، ويُفضّل استخدام القوالب بدلًا من وحدات الماكرو رغم أنّها أقلّ شمولية منها.
</p>

<p>
	وغالبًا ما تستفيد البرمجة الوصفية للقوالب من الحسابات أثناء وقت التصريف (compile-time)، سواء عبر القوالب أو عبر دوال <code>‎constexpr‎</code> لتوليد الشيفرة البرمجية. تجدر الإشارة إلى أنّ حسابات وقت التصريف لا تُصنّف على أنّها من البرمجة الوصفية.
</p>

<h2>
	حساب المضروب (Calculating Factorial)
</h2>

<p>
	يمكن حساب المضروب أثناء التصريف باستخدام تقنيّات البرمجة الوصفية للقوالب (template metaprogramming)، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3178_7" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">

</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">unsigned</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> n </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> factorial </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">enum</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            value </span><span class="pun">=</span><span class="pln"> n </span><span class="pun">*</span><span class="pln"> factorial </span><span class="pun">&lt;</span><span class="pln"> n </span><span class="pun">-</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="pln">value
        </span><span class="pun">};</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> factorial </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">enum</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            value </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
        </span><span class="pun">};</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> factorial </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">7</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="pln">value </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln"> </span><span class="com">// "5040" طباعة</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	المضروب <code>‎factorial‎</code> هو بُنية (struct)، بيْد أنّ البرمجة الوصفية للقوالب تُعامله على أنّه دالة قالب وصفية (template metafunction). اصطلاحًا، تُقيَّم دوال القالب الوصفية عن طريق التحقق من عضو معيّن، إمّا <code>‎::type‎</code> بالنسبة للدوال الوصفية التي تعيد أنواعًا، أو <code>‎::value‎</code> بالنسبة للدوال الوصفية التي تعيد قيمًا. وفي الشيفرة أعلاه، نقيِّم الدالة الوصفية <code>‎factorial‎</code> عن طريق استنساخ (instantiating) القالب باستخدام المعامِلات التي نريد تمريرها، ونستخدم <code>‎::value‎</code> للحصول على نتيجة التقييم.
</p>

<p>
	تعتمد الدالة الوصفية على استنساخ نفس الدالة الوصفية ذاتيًا لكن مع قيم أصغر، فيما تمثّل الحالة الخاصة <code>‎factorial &lt;‎0‎‎&gt;‎</code> شرطَ الإنهاء. وتنطبق على البرمجة الوصفية للقوالب معظم قيود لغات البرمجة الدالّية (functional programming language)، لذا فإنّ الذاتية (recursion) هي البنية الأساسية للتكرار "looping". ولمّا كانت دوال القالب الوصفية تُنفَّذ في وقت التصريف، فيمكن استخدام نتائجها في السياقات التي تتطلب قِيَمَ وقت التصريف (compiletime values). انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3178_9" style="">
<span class="typ">int</span><span class="pln"> my_array</span><span class="pun">[</span><span class="pln">factorial</span><span class="pun">&lt;</span><span class="lit">5</span><span class="pun">&gt;::</span><span class="pln">value</span><span class="pun">];</span></pre>

<p>
	يجب أن يُحدَّ حجم <a data-ss1617022549="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-7-%D8%A7%D9%84%D9%85%D8%B5%D9%81%D9%88%D9%81%D8%A7%D8%AA-%D9%81%D9%8A-cpp-r891/" rel="">المصفوفات</a> أثناء التصريف، وتكونَ نتيجة الدالة الوصفية قيمة ثابتة وقت التصريف كي يمكن استخدامها هنا.
</p>

<p>
	<strong>ملاحظة</strong>: لن تسمح معظم المُصرّفات بأن تتعمّق العوديّة أبعد من حدّ معيّن. على سبيل المثال، المُصرّف <code>‎g++‎</code> افتراضيًّا يحدُّ العوديّة في 256 مستوى. في حالة المصرّف <code>‎g++‎</code>، يمكن للمُبرمج ضبط عمق الذاتية باستخدام الخيار <code>‎-ftemplate-depth-‎‎X‎</code>.
</p>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	منذ الإصدار C++‎ 11، يمكن استخدام قالب <code>‎std::integral_constant‎</code> في هذا النوع من حسابات القوالب:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3178_11" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;type_traits&gt;</span><span class="pln">

</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> n </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> factorial</span><span class="pun">:</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">integral_constant </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> </span><span class="kwd">long</span><span class="pun">,</span><span class="pln"> n </span><span class="pun">*</span><span class="pln"> factorial </span><span class="pun">&lt;</span><span class="pln"> n </span><span class="pun">-</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="pln">value </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">

</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> factorial </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">&gt;:</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">integral_constant </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> </span><span class="kwd">long</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> factorial </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">7</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="pln">value </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln"> </span><span class="com">// "5040"</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	كذلك فإن دوال <code>‎constexpr‎</code> بديل أفضل. انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3178_13" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">

</span><span class="kwd">constexpr</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> factorial</span><span class="pun">(</span><span class="kwd">long</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> n</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="pln">n </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> n </span><span class="pun">*</span><span class="pln"> factorial</span><span class="pun">(</span><span class="pln">n </span><span class="pun">-</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">char</span><span class="pln"> test</span><span class="pun">[</span><span class="pln">factorial</span><span class="pun">(</span><span class="lit">3</span><span class="pun">)];</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> factorial</span><span class="pun">(</span><span class="lit">7</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يُكتب متن الدالة <code>‎factorial()‎</code> كتعليمة واحدة لأن دوال التعابير الثابتة <code>constexpr</code> في C++‎ 11 تستخدم قسمًا محدودًا للغاية من اللغة.
</p>

<p>
	<strong>الإصدار ≥ C++‎ 14</strong>
</p>

<p>
	صار من السهل كتابة دوال التعابير الثابتة <code>constexpr</code> منذ إصدار C++ 14 بعد إسقاط العديد من القيود على كتابتها، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3178_15" style="">
<span class="kwd">constexpr</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> factorial</span><span class="pun">(</span><span class="kwd">long</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> n</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">n </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">else</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> n </span><span class="pun">*</span><span class="pln"> factorial</span><span class="pun">(</span><span class="pln">n </span><span class="pun">-</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	أو حتى بالصورة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3178_17" style="">
<span class="kwd">constexpr</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> factorial</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> n</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="kwd">long</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> result </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;=</span><span class="pln"> n</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
result </span><span class="pun">*=</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> result</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 17</strong>
</p>

<p>
	بدءًا من الإصدار C++‎ 17، صار من الممكن استخدام تعبير مطوي (fold expression) لحساب المضروب، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3178_19" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;utility&gt;</span><span class="pln">

</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> T N</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> I </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">make_integer_sequence </span><span class="pun">&lt;</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> N </span><span class="pun">&gt;&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> factorial</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> T N</span><span class="pun">,</span><span class="pln"> T</span><span class="pun">...</span><span class="typ">Is</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> factorial </span><span class="pun">&lt;</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> N</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">index_sequence </span><span class="pun">&lt;</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Is</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">constexpr</span><span class="pln"> T value </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">static_cast</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="pun">...</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Is</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">));</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> factorial </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="pln">value </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	التكرار على حزمة معامِلات
</h2>

<p>
	قد نحتاج أحيانًا إلى إجراء عملية على كل عنصر من عناصر حزمة معاملات قالب متغير (variadic template parameter pack)، وهناك عدة طرق لفعل ذلك كما أنها صارت أسهل في C++‎ 17.
</p>

<p>
	إذا افترضنا أننا نريد طباعة كل عنصر في الحزمة يكون أبسط حل لدينا هو الذاتية (Recursion)، انظر المثال التالي:
</p>

<p>
	<strong>الإصدار C++‎ 11</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3178_21" style="">
<span class="kwd">void</span><span class="pln"> print_all</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">ostream </span><span class="pun">&amp;</span><span class="pln"> os</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// الحالة الأساسية</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">...</span><span class="typ">Ts</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> print_all</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">ostream </span><span class="pun">&amp;</span><span class="pln"> os</span><span class="pun">,</span><span class="pln"> T
        </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> first</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Ts</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">...</span><span class="pln">rest</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        os </span><span class="pun">&lt;&lt;</span><span class="pln"> first</span><span class="pun">;</span><span class="pln">

        print_all</span><span class="pun">(</span><span class="pln">os</span><span class="pun">,</span><span class="pln"> rest</span><span class="pun">...);</span><span class="pln">
    </span><span class="pun">}</span></pre>

<p>
	نستطيع استخدام أسلوب الموسِّع <code>expander</code> بدلًا مما سبق من أجل تنفيذ كل عمليات البث (streaming) في دالة واحدة، ولم نكن لنحتاج إلى تحميلٍ زائدٍ آخر، لكن يعيب هذا الأسلوب أنه يجعل من الصعب قراءة الشيفرة. انظر:
</p>

<p>
	<strong>الإصدار C++‎ 11</strong>
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3178_23" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">...</span><span class="typ">Ts</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> print_all</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">ostream </span><span class="pun">&amp;</span><span class="pln"> os</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Ts</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">...</span><span class="pln">args</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">using</span><span class="pln"> expander </span><span class="pun">=</span><span class="pln"> </span><span class="typ">int</span><span class="pun">[];</span><span class="pln">
        </span><span class="pun">(</span><span class="kwd">void</span><span class="pun">)</span><span class="pln"> expander </span><span class="pun">{</span><span class="pln">
            </span><span class="lit">0</span><span class="pun">,</span><span class="pln">
            </span><span class="pun">(</span><span class="kwd">void</span><span class="pun">(</span><span class="pln">os </span><span class="pun">&lt;&lt;</span><span class="pln"> args</span><span class="pun">),</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)...</span><span class="pln">
        </span><span class="pun">};</span><span class="pln">
    </span><span class="pun">}</span></pre>

<p>
	راجع <a data-ss1617022549="1" href="https://stackoverflow.com/questions/25680461/variadic-template-pack-expansion/25683817#25683817" rel="external nofollow">إجابة TC في موقع stackoverflow</a> لتفهم كيفية عمل ما سبق بشكل أوضح.
</p>

<p>
	<strong>الإصدار ≥ C++‎ 17</strong>
</p>

<p>
	لدينا بدءًا من الإصدار C++‎ 17 أَداتين جديدتين لحلّ هذه المشكلة، الأولى هي التعبير المطوي (fold-expression):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3178_25" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">...</span><span class="typ">Ts</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> print_all</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">ostream </span><span class="pun">&amp;</span><span class="pln"> os</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Ts</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">...</span><span class="pln">args</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="pun">((</span><span class="pln">os </span><span class="pun">&lt;&lt;</span><span class="pln"> args</span><span class="pun">),</span><span class="pln"> </span><span class="pun">...);</span><span class="pln">
    </span><span class="pun">}</span></pre>

<p>
	والثانية هي تعليمة <code>‎if constexpr‎</code>، والتي تسمح لنا بكتابة حلّنا الذاتي الأول في دالة واحدة، انظر المثال التالي حيث يُستنسَخ سطر <code>if constexpr</code> في حالة وجود وسائط أخرى فقط، أما إن كان <code>rest</code> فارغًا فلن يكون أي استدعاءٍ لـ <code>(print_all(os</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3178_27" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">...</span><span class="typ">Ts</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> print_all</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">ostream </span><span class="pun">&amp;</span><span class="pln"> os</span><span class="pun">,</span><span class="pln"> T
        </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> first</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Ts</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">...</span><span class="pln">rest</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        os </span><span class="pun">&lt;&lt;</span><span class="pln"> first</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="kwd">constexpr</span><span class="pun">(</span><span class="kwd">sizeof</span><span class="pun">...(</span><span class="pln">rest</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                      print_all</span><span class="pun">(</span><span class="pln">os</span><span class="pun">,</span><span class="pln"> rest</span><span class="pun">...);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span></pre>

<h2>
	التكرار عبر <code>std::integer_sequence</code>
</h2>

<p>
	صار قالب الصنف (class template) متاحًا منذ إصدار C++‎ 14، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3178_29" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> T</span><span class="pun">...</span><span class="typ">Ints</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">class</span><span class="pln"> integer_sequence</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pun">...</span><span class="typ">Ints</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">using</span><span class="pln"> index_sequence </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">integer_sequence </span><span class="pun">&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Ints</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">;</span></pre>

<p>
	وكذلك دالةُ عُليا مولِّدة (generating metafunction) لأجله:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3178_31" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> T N </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">using</span><span class="pln"> make_integer_sequence </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">integer_sequence </span><span class="pun">&lt;</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> </span><span class="com">/* a sequence 0, 1, 2, ..., N-1 */</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">;</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> N </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">using</span><span class="pln"> make_index_sequence </span><span class="pun">=</span><span class="pln"> make_integer_sequence </span><span class="pun">&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pun">,</span><span class="pln"> N </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">;</span></pre>

<p>
	ورغم أنّ هذا لم يصبح معتمدًا إلا منذ الإصدار C++‎ 14، إلا أنه يمكن تنفيذه باستخدام أدوات C++‎ 11، ونستطيع استخدام هذه الأداة لاستدعاء دالّة مع تمرير صفّ <code>‎std::tuple‎</code> من الوسائط (اعتُمِدَت في C++‎ 17 كـ <code>‎std::apply‎</code>) انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3178_33" style="">
<span class="kwd">namespace</span><span class="pln"> detail </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> F</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Tuple</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pun">...</span><span class="pln"> </span><span class="typ">Is</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">decltype</span><span class="pun">(</span><span class="kwd">auto</span><span class="pun">)</span><span class="pln"> apply_impl</span><span class="pun">(</span><span class="pln">F</span><span class="pun">&amp;&amp;</span><span class="pln"> f</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Tuple</span><span class="pun">&amp;&amp;</span><span class="pln"> tpl</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">index_sequence</span><span class="pun">&lt;</span><span class="typ">Is</span><span class="pun">...&gt;</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">forward</span><span class="pun">&lt;</span><span class="pln">F</span><span class="pun">&gt;(</span><span class="pln">f</span><span class="pun">)(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">get</span><span class="pun">&lt;</span><span class="typ">Is</span><span class="pun">&gt;(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">forward</span><span class="pun">&lt;</span><span class="typ">Tuple</span><span class="pun">&gt;(</span><span class="pln">tpl</span><span class="pun">))...);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> F</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Tuple</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">decltype</span><span class="pun">(</span><span class="kwd">auto</span><span class="pun">)</span><span class="pln"> apply</span><span class="pun">(</span><span class="pln">F</span><span class="pun">&amp;&amp;</span><span class="pln"> f</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Tuple</span><span class="pun">&amp;&amp;</span><span class="pln"> tpl</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> detail</span><span class="pun">::</span><span class="pln">apply_impl</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">forward</span><span class="pun">&lt;</span><span class="pln">F</span><span class="pun">&gt;(</span><span class="pln">f</span><span class="pun">),</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">forward</span><span class="pun">&lt;</span><span class="typ">Tuple</span><span class="pun">&gt;(</span><span class="pln">tpl</span><span class="pun">),</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">make_index_sequence</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">tuple_size</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="typ">decay_t</span><span class="pun">&lt;</span><span class="typ">Tuple</span><span class="pun">&gt;&gt;::</span><span class="pln">value</span><span class="pun">&gt;{});</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">//  3 هذا سيطبع </span><span class="pln">
</span><span class="typ">int</span><span class="pln"> f</span><span class="pun">(</span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">double</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> some_args </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">make_tuple</span><span class="pun">(</span><span class="lit">42</span><span class="pun">,</span><span class="pln"> </span><span class="str">'x'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3.14</span><span class="pun">);</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> r </span><span class="pun">=</span><span class="pln"> apply</span><span class="pun">(</span><span class="pln">f</span><span class="pun">,</span><span class="pln"> some_args</span><span class="pun">);</span><span class="pln"> </span><span class="com">// تستدعي f(42, 'x', 3.14)</span></pre>

<h2>
	إرسال الوسوم (Tag Dispatching)
</h2>

<p>
	إحدى أبسط الطرق للاختيار بين الدوال عند وقت التصريف هي إرسال دالة إلى زوج من الدوال المُحمّلة بحمل زائد والتي تأخذ وسمًا كأحد وسائطها (attributes) -يكون الأخير عادة-، فمثلًا لتطبيق <code>‎std::advance()‎</code>، نستطيع تنفيذ الإرسال على فئة <a data-ss1617022549="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-8-%D8%A7%D9%84%D9%85%D9%83%D8%B1%D8%A7%D8%B1%D8%A7%D8%AA-iterators-%D9%81%D9%8A-cpp-r892/" rel="">المُكرّر</a>، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3178_35" style="">
<span class="kwd">namespace</span><span class="pln"> details </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">RAIter</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Distance</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
        </span><span class="kwd">void</span><span class="pln"> advance</span><span class="pun">(</span><span class="typ">RAIter</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> it</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Distance</span><span class="pln"> n</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">random_access_iterator_tag</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            it </span><span class="pun">+=</span><span class="pln"> n</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">BidirIter</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Distance</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
        </span><span class="kwd">void</span><span class="pln"> advance</span><span class="pun">(</span><span class="typ">BidirIter</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> it</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Distance</span><span class="pln"> n</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">bidirectional_iterator_tag</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">n </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">n</span><span class="pun">--)</span><span class="pln"> </span><span class="pun">++</span><span class="pln">it</span><span class="pun">;</span><span class="pln">
            </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">n</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">--</span><span class="pln">it</span><span class="pun">;</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">InputIter</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Distance</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
        </span><span class="kwd">void</span><span class="pln"> advance</span><span class="pun">(</span><span class="typ">InputIter</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> it</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Distance</span><span class="pln"> n</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">input_iterator_tag</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">n</span><span class="pun">--)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                </span><span class="pun">++</span><span class="pln">it</span><span class="pun">;</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Iter</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Distance</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> advance</span><span class="pun">(</span><span class="typ">Iter</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> it</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Distance</span><span class="pln"> n</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        details</span><span class="pun">::</span><span class="pln">advance</span><span class="pun">(</span><span class="pln">it</span><span class="pun">,</span><span class="pln"> n</span><span class="pun">,</span><span class="pln">
            </span><span class="kwd">typename</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">iterator_traits </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">Iter</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="pln">iterator_category </span><span class="pun">{});</span><span class="pln">
    </span><span class="pun">}</span></pre>

<p>
	وسائط <code>‎std::XY_iterator_tag‎</code> الخاصّة بدوال <code>‎details::advance‎</code> ذات الأحمال الزائدة هي مُعامِلات غير مستخدمة، ذلك أن التطبيق الفعلي لا يهم لأنه فارغ تمامًا، والغرض الوحيد منها هو السماح للمصرّف باختيار التحميل الزائد بناءً على وسم الصنف <code>‎details::advance‎</code> الذي استُدعي معه.
</p>

<p>
	تستخدم <code>‎advance‎</code> في هذا المثال دالةَ <code>‎iterator_traits&lt;T&gt;::iterator_category‎</code> الوصفية، والتي تعيد أحد أصناف <code>‎iterator_tag‎</code> بناءً على نوع <code>‎Iter‎</code> الفعلي، ثم بعد ذلك يتيح كائن منشأ افتراضيًا من نوع <code>iterator_category&lt;Iter&gt;::type</code> للمصرِّف اختيار أحد تحميلات <code>details::advance</code> الزائدة. سيتجاوز المصرِّفُ على الأرجح معامِل الدالة ذاك بما أنه كائن منشأ افتراضيًا لِبُنيَة فارغة لم تستخدم.
</p>

<p>
	إرسال الوسوم يجعل الشيفرة أسهل في القراءة مقارنة بغيرها، وذلك باستخدام قاعدة "خطأ التعويض ليس خطأً" أو SFINAE اختصارًا بالإنجليزية، وكذلك استخدام <code>enable_if</code>.
</p>

<p>
	<strong>ملاحظة</strong>: رغم أنّ <code>if constexpr</code> قد تبسِّط تنفيذ <code>advance</code> بشكل خاص، فإنها -خلاف إرسال الوسوم- غير مناسبة للتطبيقات المفتوحة (open implementations).
</p>

<h2>
	التحقق من صحة تعبير ما
</h2>

<p>
	نستطيع التحقق إن كان يجوز استدعاء عامل (operator) أو دالة على نوع ما، كذلك يمكن التحقق إن كان صنف ما لديه تحميل زائد‏‏ على <code>std::hash</code>، وذلك كما يلي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3178_37" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;functional&gt;</span><span class="pln"> </span><span class="com">// for std::hash</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;type_traits&gt;</span><span class="pln"> </span><span class="com">// for std::false_type and std::true_type</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;utility&gt;</span><span class="pln"> </span><span class="com">// for std::declval</span><span class="pln">

</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">void</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> has_hash
</span><span class="pun">:</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">false_type
</span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> has_hash</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">hash</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;()(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">declval</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;()),</span><span class="pln"> </span><span class="kwd">void</span><span class="pun">())&gt;</span><span class="pln">
</span><span class="pun">:</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">true_type
</span><span class="pun">{};</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 17</strong>
</p>

<p>
	يمكن استخدام <code>‎std::void_t‎</code> لتبسيط هذا النوع من الإنشاءات منذ الإصدار C++‎ 17.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3178_39" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;functional&gt;</span><span class="pln"> </span><span class="com">// for std::hash</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;type_traits&gt;</span><span class="pln"> </span><span class="com">// for std::false_type, std::true_type, std::void_t</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;utility&gt;</span><span class="pln"> </span><span class="com">// for std::declval</span><span class="pln">

</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">void_t</span><span class="pun">&lt;&gt;</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> has_hash
</span><span class="pun">:</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">false_type
</span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> has_hash</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">void_t</span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">hash</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;()(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">declval</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;()))</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
</span><span class="pun">:</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">true_type
</span><span class="pun">{};</span></pre>

<p>
	حيث تٌعرَّف <code>‎std::void_t‎</code> على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3178_41" style="">
<span class="kwd">template</span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">...</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="kwd">using</span><span class="pln"> </span><span class="typ">void_t</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">void</span><span class="pun">;</span></pre>

<p>
	للتحقق مما إذا كان أحد العوامل مثل <code>‎operator&lt;‎</code> مُعرّفًا، فإن بنية الشيفرة تكون نفسها تقريبًا، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3178_43" style="">
<span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">void</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> has_less_than
</span><span class="pun">:</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">false_type
</span><span class="pun">{};</span><span class="pln">

</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> has_less_than</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">decltype</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">declval</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;()</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">declval</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;(),</span><span class="pln"> </span><span class="kwd">void</span><span class="pun">())&gt;</span><span class="pln">
</span><span class="pun">:</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">true_type
</span><span class="pun">{};</span></pre>

<p>
	يمكن الاستفادة مما سبق واستخدامه عند استخدام <code>‎std::unordered_map&lt;T&gt;‎</code> إن كان لـ <code>‎T‎</code> تحميل زائد على <code>‎std::hash‎</code>، لكن فيما سوى ذلك فاستخدام <code>‎std::map&lt;T&gt;‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3178_45" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> K</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> V</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> hash_invariant_map </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">conditional_t</span><span class="pun">&lt;</span><span class="pln">
has_hash</span><span class="pun">&lt;</span><span class="pln">K</span><span class="pun">&gt;::</span><span class="pln">value</span><span class="pun">,</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">unordered_map</span><span class="pun">&lt;</span><span class="pln">K</span><span class="pun">,</span><span class="pln"> V</span><span class="pun">&gt;,</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">map</span><span class="pun">&lt;</span><span class="pln">K</span><span class="pun">,</span><span class="pln">V</span><span class="pun">&gt;&gt;;</span></pre>

<h2>
	If-then-else
</h2>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	يستطيع نوعُ <code>‎std::conditional‎</code> الموجود في ترويسة المكتبة القياسية <type_traits> اختيارَ نوع ما استنادًا إلى قيمة بوليانية محدّدة وقتَ التصريف: </type_traits></p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3178_47" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">ValueOrPointer</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">typename</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">conditional </span><span class="pun">&lt;</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">sizeof</span><span class="pun">(</span><span class="pln">T</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="kwd">void</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="pun">)),</span><span class="pln"> T </span><span class="pun">*</span><span class="pln"> </span><span class="pun">,</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="pln">type vop</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">};</span></pre>

<p>
	تحتوي هذه البنية مؤشّرًا إلى <code>‎T‎</code> إن كان <code>‎T‎</code> أكبر من حجم المؤشّر، أو إلى <code>‎T‎</code> نفسه إذا كان أصغر أو يساوي حجم المؤشر، وعليه سيكون <code>‎sizeof(ValueOrPointer)‎</code> أصغر دائمًا من <code>‎sizeof(void*)‎</code>.
</p>

<h2>
	التمييز اليدوي للأنواع عند إعطائها أيَّ نوع T
</h2>

<p>
	عند تطبيق قاعدة SFINAE باستخدام <code>‎std::enable_if‎</code> يكون مفيدًا أن نصل إلى قوالب مساعِدةٍ (helper templates) تحدّدُ إذا كان نوع <code>‎T‎</code> المُعطى يطابق معايير معيّنة. وتوفّر المكتبة القياسيّة نوعين مشابهين لـ <code>‎true‎</code> و <code>‎false‎</code>، وهما <code>‎std::true_type‎</code> و <code>‎std::false_type‎</code>، واللذان يمكن استخدامُهما لتحقيق الغرض أعلاه.
</p>

<p>
	يوضّح المثال التالي كيفية التحقّق ممّا إذا كان نوع <code>‎T‎</code> مُؤشِّرًا (pointer) أم لا، ويحاكي قالبُ <code>‎is_pointer‎</code> سلوكَ دالة <code>‎std::is_pointer‎</code> المساعِدة القياسية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3178_49" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> is_pointer_</span><span class="pun">:</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">false_type </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> is_pointer_ </span><span class="pun">&lt;</span><span class="pln"> T </span><span class="pun">*</span><span class="pln"> </span><span class="pun">&gt;:</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">true_type </span><span class="pun">{};</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> is_pointer</span><span class="pun">:</span><span class="pln"> is_pointer_ </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">remove_cv </span><span class="pun">&lt;</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="pln">type </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">{}</span></pre>

<p>
	تتألّف الشيفرة أعلاه من ثلاث خطوات (قد لا نحتاج أكثر من خطوتين أحيانًا):
</p>

<ol>
<li>
		تصريح <code>‎is_pointer_‎</code> الأوّل هو الحالة الافتراضية، ويرث من <code>‎std::false_type‎</code>. يجب أن ترث الحالة الافتراضيّة دائمًا من <code>‎std::false_type‎</code> لأنّها تشبه "الشرط الخاطئ <code>‎false‎</code>".
	</li>
	<li>
		التصريح الثاني يخصّص القالب <code>‎is_pointer_‎</code> لأجل المؤشّر <code>‎T*‎</code> بغضِّ النظر عن ماهية <code>‎T‎</code>، وترث هذه النسخة من <code>‎std::true_type‎</code>.
	</li>
	<li>
		التصريح الثالث (وهو التصريح الحقيقي) يزيل أيّ معلومات غير ضروريّة من <code>‎T‎</code> (في هذه الحالة يزيل المؤهّليْن (qualifiers) ‏‏<code>‎const‎</code> و <code>‎volatile‎</code>) ثم يعود إلى أحد التصريحين السابقين.
	</li>
</ol>
<p>
	وبما أنّ <code>‎is_pointer&lt;T&gt;‎</code> هو صنفٌ فإننا نحتاج إلى التالي من أجل الوصول إلى قيمته:
</p>

<ul>
<li>
		استخدم <code>‎::value‎</code>، مثلًا: <code>‎is_pointer&lt;int&gt;::value‎</code>: القيمة <code>‎value‎</code> هو عضو صنفٍ ثابت (static class member) من النوع <code>‎bool‎</code> موروثٌ من <code>std::true_type</code> أو <code>std::false_type</code>.
	</li>
	<li>
		أنشئ كائنًا من هذا النوع، على سبيل المثال <code>‎is_pointer&lt;int&gt;{}‎</code>: ذلك مناسب لأنّ <code>‎std::is_pointer‎</code> ترث منشئها الافتراضي من <code>‎std::true_type‎</code> أو <code>‎std::false_type‎</code> (التي لها مُنشئات من نوع <code>‎constexpr‎</code>)، ولكلٍّ من <code>std::true_type</code> و <code>std::false_type</code> معاملاتُ تحويل من <code>constexpr</code> إلى <code>bool</code>.
	</li>
</ul>
<p>
	من الجيد توفير مساعِدات للقوالب المساعدة، تتيح الوصول المباشر إلى القيمة، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3178_51" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="kwd">typename</span><span class="pln"> T</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">constexpr</span><span class="pln"> </span><span class="kwd">bool</span><span class="pln"> is_pointer_v </span><span class="pun">=</span><span class="pln"> is_pointer</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;::</span><span class="pln">value</span><span class="pun">;</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 17</strong> توفر معظم قوالب المساعدة في إصدار C++ 17 وما بعده نسخةَ <code>‎_v‎</code>، انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3178_53" style="">
<span class="kwd">template</span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln"> </span><span class="kwd">constexpr</span><span class="pln"> </span><span class="kwd">bool</span><span class="pln"> is_pointer_v </span><span class="pun">=</span><span class="pln"> is_pointer</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;::</span><span class="pln">value</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">template</span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln"> </span><span class="kwd">constexpr</span><span class="pln"> </span><span class="kwd">bool</span><span class="pln"> is_reference_v </span><span class="pun">=</span><span class="pln"> is_reference</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;::</span><span class="pln">value</span><span class="pun">;</span></pre>

<h2>
	حساب القوة في C++‎ 11 وما بعدها
</h2>

<p>
	صارت العمليات الحسابية في وقت التصريف أيسر بكثير منذ إصدار C++‎ 11، فيمكن حساب قوة عدد معين في وقت التصريف مثلًا على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3178_55" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">constexpr</span><span class="pln"> T calculatePower</span><span class="pun">(</span><span class="pln">T value</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">unsigned</span><span class="pln"> power</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> power </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> value </span><span class="pun">*</span><span class="pln"> calculatePower</span><span class="pun">(</span><span class="pln">value</span><span class="pun">,</span><span class="pln"> power </span><span class="pun">-</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span></pre>

<p>
	وتكون الكلمة المفتاحية <code>‎constexpr‎</code> مسؤولة عن حساب الدالة في وقت التصريف عند استيفاء جميع المتطلّبات اللازمة، كأن تكون جميع الوسائط معروفة في وقت التصريف.
</p>

<p>
	<strong>ملاحظة</strong>: يجب أن تكون دوال التعبير الثابت (<code>‎constexpr‎</code>) في C++‎ 11 مكونة من تعليمة <code>return</code> واحدة فقط.
</p>

<p>
	عند مقارنة هذه الطريقة بالطريقة القياسية لحسابات وقت التصريف، فإن هذه الطريقة مفيدة أيضًا في حسابات وقت التشغيل، فإن كانت وسائط دالة ما مجهولةً وقتَ التصريف (مثل القيمة والقوة المعطاتيْن كمدخلات من قِبل المستخدم) فإن الدالة تُنفَّذ في وقت التصريف، فلا حاجة إذًا لتكرار الشيفرة كما كان في المعايير الأقدم من C++‎. انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3178_57" style="">
<span class="kwd">void</span><span class="pln"> useExample</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">constexpr</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> compileTimeCalculated </span><span class="pun">=</span><span class="pln"> calculatePower</span><span class="pun">(</span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">);</span><span class="pln"> </span><span class="com">//  الحساب وقت التصريف</span><span class="pln">
    </span><span class="com">// لأنّ كلا المُعاملين معروفان وقت التصريف ويُستخدم في تعبير ثابت</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> value</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cin </span><span class="pun">&gt;&gt;</span><span class="pln"> value</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> runtimeCalculated </span><span class="pun">=</span><span class="pln"> calculatePower</span><span class="pun">(</span><span class="pln">value</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">);</span><span class="pln"> </span><span class="com">// runtime calculated,</span><span class="pln">
    </span><span class="com">// لأنّ القيمة لن تكون معروفة حتى وقت التشغيل</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 17</strong>
</p>

<p>
	وهناك طريقة أخرى لحساب القوة في وقت التصريف تستخدم التعابير المطوية، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3178_59" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;utility&gt;</span><span class="pln">

</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> T V</span><span class="pun">,</span><span class="pln"> T N</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> I </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">make_integer_sequence</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> N</span><span class="pun">&gt;&gt;</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> power</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> T</span><span class="pun">,</span><span class="pln"> T V</span><span class="pun">,</span><span class="pln"> T N</span><span class="pun">,</span><span class="pln"> T</span><span class="pun">...</span><span class="pln"> </span><span class="typ">Is</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> power</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> V</span><span class="pun">,</span><span class="pln"> N</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">integer_sequence</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Is</span><span class="pun">...&gt;&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">constexpr</span><span class="pln"> T value </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">static_cast</span><span class="pun">&lt;</span><span class="pln">T</span><span class="pun">&gt;(</span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="pun">...</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="pun">(</span><span class="pln">V </span><span class="pun">*</span><span class="pln"> </span><span class="kwd">static_cast</span><span class="str">&lt;bool&gt;</span><span class="pun">(</span><span class="typ">Is</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)));</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> power </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="pln">value </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	دالة عامّة لتحديد القيم الصغرى والعظمى مع عدد وسائط متغير
</h2>

<p>
	<strong>الإصدار&gt; C++‎ 11</strong>
</p>

<p>
	من الممكن كتابة دالة عامة (على سبيل المثال دالة تحسب الحد الأدنى <code>‎min‎</code>) تقبل أنواعًا عدديّة مختلفة، وعدد وسائط عشوائي بواسطة قالَب برمجة وصفية. انظر المثال التالي حيث تصرّح الدالة عن دالة <code>‎min‎</code> تقبل وسيطين أو أكثر.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3178_61" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="kwd">typename</span><span class="pln"> T1</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T2</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> min</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> T1 </span><span class="pun">&amp;</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> T2 </span><span class="pun">&amp;</span><span class="pln">b</span><span class="pun">)</span><span class="pln">
</span><span class="pun">-&gt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">common_type</span><span class="pun">&lt;</span><span class="kwd">const</span><span class="pln"> T1</span><span class="pun">&amp;,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> T2</span><span class="pun">&amp;&gt;::</span><span class="pln">type
</span><span class="pun">{</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> a </span><span class="pun">&lt;</span><span class="pln"> b </span><span class="pun">?</span><span class="pln"> a </span><span class="pun">:</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="kwd">typename</span><span class="pln"> T1</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T2</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> </span><span class="pun">...</span><span class="pln"> </span><span class="typ">Args</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> min</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> T1 </span><span class="pun">&amp;</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> T2 </span><span class="pun">&amp;</span><span class="pln">b</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Args</span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">...</span><span class="pln"> args</span><span class="pun">)</span><span class="pln">
</span><span class="pun">-&gt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">common_type</span><span class="pun">&lt;</span><span class="kwd">const</span><span class="pln"> T1</span><span class="pun">&amp;,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> T2</span><span class="pun">&amp;,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Args</span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">...&gt;::</span><span class="pln">type
</span><span class="pun">{</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> min</span><span class="pun">(</span><span class="pln">min</span><span class="pun">(</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> b</span><span class="pun">),</span><span class="pln"> args</span><span class="pun">...);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">auto</span><span class="pln"> minimum </span><span class="pun">=</span><span class="pln"> min</span><span class="pun">(</span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5.8f</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1.8</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1.1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">9</span><span class="pun">);</span></pre>

<h2>
	حسابيات البرمجة الوصفية
</h2>

<p>
	فيما يلي أمثلة على استخدام برمجة القوالب الوصفية في C++‎ لإنجاز العمليات الحسابية في وقت التصريف.
</p>

<h3>
	حساب الأس ‎في (O(log n
</h3>

<p>
	يوضّح هذا المثال طريقة فعالة لحساب الأسّ باستخدام برمجة القوالب الوصفية.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3178_63" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="typ">int</span><span class="pln"> base</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">unsigned</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> exponent</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> power
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> halfvalue </span><span class="pun">=</span><span class="pln"> power</span><span class="pun">&lt;</span><span class="pln">base</span><span class="pun">,</span><span class="pln"> exponent </span><span class="pun">/</span><span class="pln"> </span><span class="lit">2</span><span class="pun">&gt;::</span><span class="pln">value</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> value </span><span class="pun">=</span><span class="pln"> halfvalue </span><span class="pun">*</span><span class="pln"> halfvalue </span><span class="pun">*</span><span class="pln"> power</span><span class="pun">&lt;</span><span class="pln">base</span><span class="pun">,</span><span class="pln"> exponent </span><span class="pun">%</span><span class="pln"> </span><span class="lit">2</span><span class="pun">&gt;::</span><span class="pln">value</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="typ">int</span><span class="pln"> base</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> power</span><span class="pun">&lt;</span><span class="pln">base</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">&gt;</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> value </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">static_assert</span><span class="pun">(</span><span class="pln">base </span><span class="pun">!=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="str">"power&lt;0, 0&gt; is not allowed"</span><span class="pun">);</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="typ">int</span><span class="pln"> base</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> power</span><span class="pun">&lt;</span><span class="pln">base</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">&gt;</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> value </span><span class="pun">=</span><span class="pln"> base</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	مثال تطبيقي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3178_65" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> power </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">9</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="pln">value</span><span class="pun">;</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 14</strong>
</p>

<p>
	هذا المثال يعالج الأسّ السلبيّ أيضًا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3178_67" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="typ">int</span><span class="pln"> base</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> exponent</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> powerDouble
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> exponentAbs </span><span class="pun">=</span><span class="pln"> exponent </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> </span><span class="pun">(-</span><span class="pln">exponent</span><span class="pun">)</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> exponent</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> halfvalue </span><span class="pun">=</span><span class="pln"> powerDouble</span><span class="pun">&lt;</span><span class="pln">base</span><span class="pun">,</span><span class="pln"> exponentAbs </span><span class="pun">/</span><span class="pln"> </span><span class="lit">2</span><span class="pun">&gt;::</span><span class="pln">intermediateValue</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> intermediateValue </span><span class="pun">=</span><span class="pln"> halfvalue </span><span class="pun">*</span><span class="pln"> halfvalue </span><span class="pun">*</span><span class="pln"> powerDouble</span><span class="pun">&lt;</span><span class="pln">base</span><span class="pun">,</span><span class="pln"> exponentAbs </span><span class="pun">%</span><span class="lit">2</span><span class="pun">&gt;::</span><span class="pln">intermediateValue</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">constexpr</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> value </span><span class="pun">=</span><span class="pln"> exponent </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> </span><span class="pun">(</span><span class="lit">1.0</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> intermediateValue</span><span class="pun">)</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> intermediateValue</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="typ">int</span><span class="pln"> base</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> powerDouble</span><span class="pun">&lt;</span><span class="pln">base</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">&gt;</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> intermediateValue </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">constexpr</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> value </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">static_assert</span><span class="pun">(</span><span class="pln">base </span><span class="pun">!=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="str">"powerDouble&lt;0, 0&gt; is not allowed"</span><span class="pun">);</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="typ">int</span><span class="pln"> base</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> powerDouble</span><span class="pun">&lt;</span><span class="pln">base</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">&gt;</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> intermediateValue </span><span class="pun">=</span><span class="pln"> base</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">constexpr</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> value </span><span class="pun">=</span><span class="pln"> base</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> powerDouble</span><span class="pun">&lt;</span><span class="lit">2</span><span class="pun">,-</span><span class="lit">3</span><span class="pun">&gt;::</span><span class="pln">value</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	هذا الدرس جزء من <a data-ss1617022549="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة دروس عن C++‎</a>.
</p>

<p>
	ترجمة -بتصرّف- للفصل Chapter 16: Metaprogramming والفصل Chapter 125: Arithmitic Metaprogramming من كتاب <a data-ss1617022549="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">897</guid><pubDate>Sun, 21 Jun 2020 18:07:00 +0000</pubDate></item><item><title>&#x628;&#x646;&#x649; &#x627;&#x644;&#x62A;&#x62D;&#x643;&#x645; (Flow Control) &#x641;&#x64A; Cpp</title><link>https://academy.hsoub.com/programming/cpp/%D8%A8%D9%86%D9%89-%D8%A7%D9%84%D8%AA%D8%AD%D9%83%D9%85-flow-control-%D9%81%D9%8A-cpp-r896/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_06/12.jpg.e55d90b603b07a723bf9fd909f6a2064.jpg" /></p>

<h2>
	case
</h2>

<p>
	تُدخِل كلمة <code>case</code> المفتاحية وسم حالة (case label) لتعليمة <code>switch</code>، وتنفّذ تعليمات معيّنة بناء على القيمة التي يساويها معامَلها. كذلك يجب أن يكون هذا المعامَل تعبيرًا ثابتًا ومطابقًا لشرط تعليمة <code>switch</code>. تنتقل تعليمة <code>switch</code> عند تنفيذها إلى وسم الحالة التي يساوي فيها المعامَلُ الشرطَ إن وُجِد. انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7248_7" style="">
<span class="kwd">char</span><span class="pln"> c </span><span class="pun">=</span><span class="pln"> getchar</span><span class="pun">();</span><span class="pln">
</span><span class="kwd">bool</span><span class="pln"> confirmed</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">switch</span><span class="pln"> </span><span class="pun">(</span><span class="pln">c</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">case</span><span class="pln"> </span><span class="str">'y'</span><span class="pun">:</span><span class="pln">
confirmed </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">case</span><span class="pln"> </span><span class="str">'n'</span><span class="pun">:</span><span class="pln">
confirmed </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">default</span><span class="pun">:</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"invalid response!\n"</span><span class="pun">;</span><span class="pln">
abort</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	switch
</h2>

<p>
	وفقًا لتوصيف C++‎، فإن تعليمة <code>switch</code> تحول التحكم إلى تعليمة برمجية او أكثر وفقًا لقيمة الشرط، وتُتبَع كلمة <code>‎switch‎</code> المفتاحية بقوسين يحتويان شرطًا ثم كتلة برمجية، والتي قد تحتوي على عناوين <code>‎case‎</code>، وعنوان <code>‎default‎</code> اختياري.
</p>

<p>
	عند تنفيذ تعليمة <code>switch</code> سيُنقَل التحكّم إلى عنوان <code>‎case‎</code> ذي القيمة المطابقة لقيمة الشّرط -إن وُجدت-، أو إلى العنوان <code>‎default‎</code> إن وُجد أيضًا.
</p>

<p>
	ويجب أن يكون الشرط تعبيرًا أو تصريحًا يحتوي على عدد صحيح، أو نوع عددي (enumeration type)، أو نوع صنف له دالة تحويل إلى عدد صحيح أو نوع عددي.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7248_9" style="">
<span class="kwd">char</span><span class="pln"> c </span><span class="pun">=</span><span class="pln"> getchar</span><span class="pun">();</span><span class="pln">
</span><span class="kwd">bool</span><span class="pln"> confirmed</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">switch</span><span class="pln"> </span><span class="pun">(</span><span class="pln">c</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">case</span><span class="pln"> </span><span class="str">'y'</span><span class="pun">:</span><span class="pln">
    confirmed </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">case</span><span class="pln"> </span><span class="str">'n'</span><span class="pun">:</span><span class="pln">
    confirmed </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">default</span><span class="pun">:</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"invalid response!\n"</span><span class="pun">;</span><span class="pln">
    abort</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	catch
</h2>

<p>
	تُدخِل كلمة <code>‎catch‎</code> المفتاحية معالج اعتراضات ينتقل التحكّم إلى كتلته عند إطلاق اعتراض (exception) من النّوع الموافق. وتُعقَب <code>‎catch‎</code> بقوسين يحتويان تصريحًا عن اعتراض، وذلك يشبه في هيئته تصريحات المُعامِلات في الدّوال، إذ يجوز حذف اسم المعامِل ويُسمح بالمقطع <code>‎...‎</code>، والذي يطابق أي نوع.
</p>

<p>
	مُعالجُ الاعتراض لن يُعالجَ الاعتراض إلّا إن كان تصريحه موافقًا لنوع الاعتراض. لمزيد من التفاصيل، انظر إمساك الاعتراضات.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7248_11" style="">
<span class="kwd">try</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> v</span><span class="pun">(</span><span class="pln">N</span><span class="pun">);</span><span class="pln">
    </span><span class="com">// افعل شيئا ما</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">bad_alloc </span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"failed to allocate memory for vector!"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">runtime_error </span><span class="pun">&amp;</span><span class="pln"> e</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"runtime error: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> e</span><span class="pun">.</span><span class="pln">what</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(...)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"unexpected exception!"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">throw</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	throw
</h2>

<ol>
<li>
		عندما تقع <code>‎throw‎</code> في تعبير ذي معامَل فإنّها تطلق اعتراضًا يكون نسخة من ذلك المعامَل:
	</li>
</ol>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7248_13" style="">
<span class="kwd">void</span><span class="pln"> print_asterisks</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> count</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">count </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">throw</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">invalid_argument</span><span class="pun">(</span><span class="str">"count cannot be negative!"</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">count</span><span class="pun">--)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        putchar</span><span class="pun">(</span><span class="str">'*'</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<ol start="2">
<li>
		عندما تقع <code>‎throw‎</code> في تعبير ليس له معامَل، فستعيد إطلاق الاعتراض الحالي، أما إن لم يكن ثمة اعتراض موجود فتُستدعى <code>‎std::terminate‎</code>.
	</li>
</ol>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7248_15" style="">
<span class="kwd">try</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// افعل شيئا ما</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">bad_alloc </span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cerr </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"out of memory"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(...)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cerr </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"unexpected exception"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// رجاء أن يعرف المستدعي كيفية معالجة هذا الاعتراض.</span><span class="pln">
    </span><span class="kwd">throw</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<ol start="3">
<li>
		عندما تقع <code>‎throw‎</code> في مُصرِّح دالة (function declarator)، فستقدّم توصيفًا للاعتراضات الديناميكية، والذي يسرد أنواع الاعتراضا التي يجوز للدّالة نشرها. انظر المثال التالي لدالة قد تنشر الاعتراض <code>std::runtime_error</code> مثلًا، لكن ليس <code>std::logic_error</code>:
	</li>
</ol>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7248_17" style="">
<span class="kwd">void</span><span class="pln"> risky</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">throw</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">runtime_error</span><span class="pun">);</span><span class="pln">
</span><span class="com">// هذه الدالة لا يمكنها نشر أيّ اعتراض.</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> safe</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">throw</span><span class="pun">();</span></pre>

<p>
	أُهملت توصيفات الاعتراض الديناميكية بدءًا من C++ 11.
</p>

<p>
	أول استخدامَين للعبارة <code>‎throw‎</code> المذكورة أعلاه هما تعبيران (expressions) وليسا تعليمتيْن (statements)، لاحظ أن نوع الاعتراض الذي أُطلِق هو <code>‎void‎</code>، هذا يجعل تداخلها ممكنًا في التعبيرات على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7248_19" style="">
<span class="kwd">unsigned</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> predecessor</span><span class="pun">(</span><span class="kwd">unsigned</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> x</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="pln">x </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> </span><span class="pun">(</span><span class="pln">x </span><span class="pun">-</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">throw</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">invalid_argument</span><span class="pun">(</span><span class="str">"0 has no predecessor"</span><span class="pun">));</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	default
</h2>

<p>
	تمثل <code>default</code> العنوان الذي سيقفز إليه البرنامج في تعليمة <code>switch</code>، إذا كانت قيمة الشرط لا تساوي أيًا من قيم عناوين <code>case</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7248_21" style="">
<span class="kwd">char</span><span class="pln"> c </span><span class="pun">=</span><span class="pln"> getchar</span><span class="pun">();</span><span class="pln">
</span><span class="kwd">bool</span><span class="pln"> confirmed</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">switch</span><span class="pln"> </span><span class="pun">(</span><span class="pln">c</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">case</span><span class="pln"> </span><span class="str">'y'</span><span class="pun">:</span><span class="pln">
    confirmed </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">case</span><span class="pln"> </span><span class="str">'n'</span><span class="pun">:</span><span class="pln">
    confirmed </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">default</span><span class="pun">:</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"invalid response!\n"</span><span class="pun">;</span><span class="pln">
    abort</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<strong>الإصدار ≥ C++11</strong>
</p>

<p>
	تُعرّف <code>default</code> مُنشِئًا افتراضيًا (default constructor) أو مُنشئ نسخ أو نقل، أو مُدمِّرًا (destructor)، أو عامل إسناد النّسخ (copy assignment operator)، أو عامل إسناد النقل (move assignment operator) ليكون هو السلوك الافتراضي. انظر المثال التالي حيث نريد أن نكون قادرين على محو الأصناف المشتقة عبر *Base، لكن نريد السلوك المعتاد لمدمر Base:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7248_23" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">virtual</span><span class="pun">~</span><span class="typ">Base</span><span class="pun">()</span><span class="pln"> </span><span class="pun">=</span><span class="pln">
        </span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span></pre>

<h2>
	try
</h2>

<p>
	تُتبَع الكلمة المفتاحية <code>‎try‎</code> بكتلة برمجية، أو قائمة تهيئة المُنشئ (constructor initializer list) ثمّ كتلة برمجية. وتُتبَع كتلة <code>try</code> بكتلة <code>catch</code> واحدة أو أكثر، وإذا انتشر اعتراض خارج كتلة <code>try</code> فإنّ كل كتل تعليمات <code>catch</code> الموجودة بعد كتلة <code>try</code> تستطيع معالجة الاعتراض إذا كانت الأنواع متطابقة. انظر المثال التالي حيث لن تمسك <code>catch</code> الاعتراض إن أُطلق بعد <code>std::vector</code> الأولى، لكنها ستمسكه إن أُطلق بعد الثانية التي داخل <code>try</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7248_25" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> v</span><span class="pun">(</span><span class="pln">N</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">try</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> v</span><span class="pun">(</span><span class="pln">N</span><span class="pun">);</span><span class="pln"> 
    </span><span class="com">// v افعل شيئا ما بـ</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">bad_alloc </span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// try من كتلة bad_alloc عالج اعتراض.</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	if
</h2>

<p>
	<code>if</code> هي تعليمة شَرْطية يجب أن تُتبَع بقوسين يضُمّان شرطًا يكون إمّا تعبيرًا أو تصريحًا، وإذا تحقّق ذلك الشّرط، فستُنفّذ العبارة الموجودة بعده. انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7248_27" style="">
<span class="typ">int</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Please enter a positive number."</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cin </span><span class="pun">&gt;&gt;</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">x </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"You didn't enter a positive number!"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    abort</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	else
</h2>

<p>
	قد تَتبع كلمة <code>else</code> المفتاحيةُ أولَ تعليمة فرعية لتعليمة <code>if</code>، وستُنفَّذ التعليمات الفرعية بعد <code>‎else‎</code> عند عدم تحقق شرط <code>if</code>، أي عندما لا تُنفّذ كتلة التعليمات الأولى. انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7248_29" style="">
<span class="typ">int</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cin </span><span class="pun">&gt;&gt;</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">x </span><span class="pun">%</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"The number is even\n"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"The number is odd\n"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	البُنى الشرطية: if و if..else
</h2>

<h3>
	if و else
</h3>

<p>
	تُستخدم لنعرف ما إن كان التعبير المُعطى يعيد <code>true</code> أو <code>false</code> ومن ثم تتصرف وفقها، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7248_31" style="">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">condition</span><span class="pun">)</span><span class="pln"> statement</span></pre>

<p>
	يمكن أن يكون الشّرط أيّ تعبير C++‎ صالح يُعيد شيئًا يمكن التحقق من صحته أو خطئه، انظر المثال التالي حيث تُنفَّذ الشيفرة بين القوسين لتحقق الشرط (أي true)، بينما لا تُنفَّذ الشيفرة في السطر الثاني لعدم تحققه (أي false):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7248_33" style="">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">true</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">/* الشيفرة المراد تنفيذها */</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">false</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">/* الشيفرة المراد تنفيذها */</span><span class="pln"> </span><span class="pun">}</span></pre>

<p>
	قد يكون الشرط دالة أو متغيرًا أو مقارنة أو غير ذلك، انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7248_35" style="">
<span class="com">// تنفَّذ الشيفرة إن تحققت الدالة</span><span class="pln">
</span><span class="kwd">if</span><span class="pun">(</span><span class="pln">istrue</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> 

</span><span class="com">// تقييم الدالة بعد تمرير المتغير إليها</span><span class="pln">
</span><span class="kwd">if</span><span class="pun">(</span><span class="pln">isTrue</span><span class="pun">(</span><span class="pln">var</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> 

</span><span class="com">// a يساوي  b ستُنفّذ الشيفرة المقابلة إن كان</span><span class="pln">
</span><span class="kwd">if</span><span class="pun">(</span><span class="pln">a </span><span class="pun">==</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> 

</span><span class="com">// قيمة بوليانية فستُقيّم بحسب قيمتها الفعلية a إن كانت</span><span class="pln">
</span><span class="com">// وإن كانت عددا، فإنّ أي قيمة غير صفرية فستُعد صحيحة </span><span class="pln">
</span><span class="kwd">if</span><span class="pun">(</span><span class="pln">a</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span></pre>

<p>
	تستطيع التحقق من عدة تعبيرات بإحدى طريقتين: <strong>استخدام العمليات الثنائية</strong>‎:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7248_37" style="">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">a </span><span class="pun">&amp;&amp;</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="com">// معًا a و b تتحقق في حال تحقق</span><span class="pln">
scope here
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">a </span><span class="pun">||</span><span class="pln"> b </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="com">// تتحقق إن تحقق أي منهما.</span></pre>

<p>
	<strong>استخدام if / ifelse / else</strong>: لإجراء تبديل بسيط، يمكنك استخدام إمّا if أو else:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7248_39" style="">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">a </span><span class="pun">==</span><span class="pln"> </span><span class="str">"test"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// "test" تساوي a ستُنفّذ في حال كانت </span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// تنفذ في حال لم تنفّذ العبارة الأولى</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	وفي حالة الخيارات المتعددة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7248_41" style="">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">a </span><span class="pun">==</span><span class="pln"> </span><span class="str">'a'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// 'a' حرفا يساوي a إن كانت</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">a </span><span class="pun">==</span><span class="pln"> </span><span class="str">'b'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">//  'b' حرفا يساوي a إن كانت</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">a </span><span class="pun">==</span><span class="pln"> </span><span class="str">'c'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">//  'c' حرفا يساوي a إن كانت</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// تُنفّذ إن لم يتحقق أي مما سبق</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يُفضّل استخدام "switch " بدلاً من الشيفرة السابقة ما دُمنا نتحقّق من قيمة نفس المتغير.
</p>

<h2>
	goto
</h2>

<p>
	تنتقل <code>goto</code> إلى التعليمة المعنونة (labelled statement)، والتي ينبغي أن تكون موجودة في الدالة الحاليّة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7248_43" style="">
<span class="kwd">bool</span><span class="pln"> f</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> arg</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">bool</span><span class="pln"> result </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
    hWidget widget </span><span class="pun">=</span><span class="pln"> get_widget</span><span class="pun">(</span><span class="pln">arg</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">g</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// لا يمكن أن نستمر، لكن لا زال علينا أن ننظف.</span><span class="pln">
        </span><span class="kwd">goto</span><span class="pln"> end</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="com">// ...</span><span class="pln">
    result </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
    end</span><span class="pun">:</span><span class="pln">
        release_widget</span><span class="pun">(</span><span class="pln">widget</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> result</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	عبارات القفز: break و continue و goto و exit
</h2>

<h3>
	التعليمة break
</h3>

<p>
	نستطيع مغادرة الحلقة التكرارية باستخدام <code>break</code> -انظر <a data-ss1617022357="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-9-%D8%A7%D9%84%D8%AD%D9%84%D9%82%D8%A7%D8%AA-%D8%A7%D9%84%D8%AA%D9%83%D8%B1%D8%A7%D8%B1%D9%8A%D8%A9-loops-%D9%81%D9%8A-cpp-r893/" rel="">الحلقات التكرارية</a>- حتى لو لم يتحقق شرط إنهائها، كما يمكن استخدامها مثلًا لإنهاء حلقة لا نهائية أو لإجبارها على التوقف قبل نهايتها الطبيعية. وتكون صيغتها كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7248_45" style="">
<span class="kwd">break</span><span class="pun">;</span></pre>

<p>
	على سبيل المثال: غالبًا ما نستخدم <code>‎break‎</code> في حالات <code>‎switch‎</code>، كأن تتحقق حالة في <code>switch</code> فتُنفَّذ شيفرة الشرط. انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7248_47" style="">
<span class="kwd">switch</span><span class="pln"> </span><span class="pun">(</span><span class="pln">conditon</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">case</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
    block1</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">case</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
    block2</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">case</span><span class="pln"> </span><span class="lit">3</span><span class="pun">:</span><span class="pln">
    block3</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">default</span><span class="pun">:</span><span class="pln">
    blockdefault</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	في الشيفرة السابقة، إن تحققت الحالة الأولى <code>case 1</code> فإن الكتلة <code>block 1</code> تُنفَّذ، ثم تُنفَّذ كتل الحالتين الثانية والثالثة رغم أن الحالة الأولى فقط هي المتحققة، وهي ما أردنا تنفيذ الشيفرة المقابلة لها فقط. ولتجنب تنفيذ الشيفرات للحالات التي لم تحقق فإننا نستخدم <code>break</code> في نهاية كل كتلة، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7248_49" style="">
<span class="kwd">switch</span><span class="pln"> </span><span class="pun">(</span><span class="pln">condition</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">case</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
    block1</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">case</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln">
    block2</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">case</span><span class="pln"> </span><span class="lit">3</span><span class="pun">:</span><span class="pln">
    block3</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">default</span><span class="pun">:</span><span class="pln">
    blockdefault</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لن تُعالَج الآن إلا كتلة واحدة فقط، وسينتقل التحكم إلى خارج حلقة <code>switch</code>، كذلك يمكن استخدام <code>break</code> في الحلقات الشرطية وغير الشرطية الأخرى، مثل <code>‎if‎</code> و <code>‎while‎</code> و <code>‎for‎</code> وغيرها؛ انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7248_51" style="">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">condition1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="pun">....</span><span class="pln">
    </span><span class="kwd">if</span><span class="pun">(</span><span class="pln">condition2</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="pun">.......</span><span class="pln">
            </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">...</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	التعليمة <code>continue</code>
</h3>

<p>
	تجعل التعليمة <code>continue</code> البرنامجَ يتخطّى بقيّة تعليمات الحلقة في التكرار الحالي ممّا يؤدّي إلى الانتقال إلى التكرار التالي في الحلقة، وتكون صيغتها كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7248_53" style="">
<span class="kwd">continue</span><span class="pun">;</span></pre>

<p>
	انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7248_55" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">i </span><span class="pun">%</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">continue</span><span class="pun">;</span><span class="pln">
    cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n @"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	الذي ينتج الخرج:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7248_57" style="">
<span class="pun">@</span><span class="lit">1</span><span class="pln">
</span><span class="pun">@</span><span class="lit">3</span><span class="pln">
</span><span class="pun">@</span><span class="lit">5</span><span class="pln">
</span><span class="pun">@</span><span class="lit">7</span><span class="pln">
</span><span class="pun">@</span><span class="lit">9</span></pre>

<p>
	في المثال السابق، كلمّا تحقّق الشرط <code>‎i%2==‎0‎</code> فستُنفّذ العبارة <code>‎continue‎</code>، مما يجعل المُصرّف يتخطّى كل الشيفرة المتبقيّة (طباعة @ و i)، ويعودَ لتنفيذ عبارة الزّيادة/الإنقاص (increment/decrement) في الحلقة.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="45436" data-ss1617022357="1" href="https://academy.hsoub.com/uploads/monthly_2020_06/Fbuep.jpg.493a23e6a504660c686183d33e6942d3.jpg" rel=""><img alt="Fbuep.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="45436" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_06/Fbuep.jpg.493a23e6a504660c686183d33e6942d3.jpg"></a>
</p>

<h3>
	التعليمة goto
</h3>

<p>
	تسمح <code>goto</code> بإجراء قفزة إلى نقطة أخرى في البرنامج. يجب عليك الحذر عند استخدام هذه الميزة لأنّ تنفيذها يتجاهل كلّ قيود التداخل (nesting).
</p>

<p>
	وتُحدَّد النقطة التي سينتقل إليها البرنامج بواسطة عنوان (label) يُمرَّر بعدها كوسيط لتعليمة <code>goto</code>، ويتألّف اسم ذلك العنوان من مُعرِّف صالح متبوع بنقطتين <code>:</code> على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7248_59" style="">
<span class="kwd">goto</span><span class="pln"> label</span><span class="pun">;</span><span class="pln">
</span><span class="pun">..</span><span class="pln">
</span><span class="pun">.</span><span class="pln">
label</span><span class="pun">:</span><span class="pln"> statement</span><span class="pun">;</span></pre>

<p>
	<strong>ملاحظة:</strong> يُوصى بتجنّب استخدام عبارة <code>goto</code> لأنها تصعّب تتبّع سير البرنامج ومن ثم فهمه وتعديله.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="45437" data-ss1617022357="1" href="https://academy.hsoub.com/uploads/monthly_2020_06/Li8ZR.jpg.560eb0feac1aad283f34571e074e94b8.jpg" rel=""><img alt="Li8ZR.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="45437" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_06/Li8ZR.jpg.560eb0feac1aad283f34571e074e94b8.jpg"></a>
</p>

<p>
	مثال:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7248_61" style="">
<span class="typ">int</span><span class="pln"> num </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
STEP</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">do</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">num </span><span class="pun">%</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            num </span><span class="pun">=</span><span class="pln"> num </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
            </span><span class="kwd">goto</span><span class="pln"> STEP</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">

        cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"value of num : "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> num </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">
        num </span><span class="pun">=</span><span class="pln"> num </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">num </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">10</span><span class="pun">);</span></pre>

<p>
	الناتج:
</p>

<p>
	pre widget
</p>

<pre class="ipsCode">
value of num : 1
value of num : 3
value of num : 5
value of num : 7
value of num : 9
</pre>

<p>
	تنقل <code>goto</code> تنفيذَ التحكم، عند تحقق شرط <code>‎num%2==‎0‎</code>، إلى بداية حلقة <code>do-while</code>
</p>

<h3>
	دالة exit
</h3>

<p>
	<code>‎exit‎</code> هي دالة مُعرَّفة في مكتبة <code>cstdlib</code>، والغرض منها هو إنهاء البرنامج الذي يتم تنفيذه برمز خروج محدّد يكون على الصورة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7248_63" style="">
<span class="kwd">void</span><span class="pln"> exit </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> exit code</span><span class="pun">);</span></pre>

<p>
	رمزا الخروج القياسيَّين <code>EXIT_SUCCESS</code> و <code>EXIT_FAILURE</code> مُعرَّفان في مكتبة <code>‎cstdlib‎</code>.
</p>

<h2>
	return
</h2>

<p>
	تعيد تعليمة <code>return</code> التحكمَ من الدالة إلى مُستدعيها، وإذا كان للتعليمة مُعامَل فسيُحوَّل إلى نوع القيمة المعادة الخاص بالدالة، ثم تُعاد القيمة المُحوّلة إلى المستدعي.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7248_65" style="">
<span class="typ">int</span><span class="pln"> f</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> f</span><span class="pun">();</span><span class="pln"> </span><span class="com">// x = 42</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> g</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">3.14</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> y </span><span class="pun">=</span><span class="pln"> g</span><span class="pun">();</span><span class="pln"> </span><span class="com">// x = 3</span></pre>

<p>
	إذا لم يكن للتعليمة <code>‎return‎</code> أيّ معامَل فينبغي أن يكون نوع القيمة المُعادة للدالة هو <code>‎void‎</code>. كذلك يمكن للدوال التي نوع قيمتها المعادة فارغ (<code>‎void‎</code>) أن تعيد تعبيرًا إن كان ذلك التعبير من النوع <code>‎void‎</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7248_67" style="">
<span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">x </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">return</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> sqrt</span><span class="pun">(</span><span class="pln">x</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> g</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> h</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> f</span><span class="pun">();</span><span class="pln"> </span><span class="com">// ثم العودة f استدعاء</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> g</span><span class="pun">();</span><span class="pln"> </span><span class="com">// غير صالحة</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تستدعي <code>main</code> دالة <code>‎std::exit‎</code> ضمنيًا مع القيمة التي تعيدها، وتعاد القيمة عندها إلى بيئة التنفيذ، غير أن الإعادة من <code>main</code> يدمر المتغيرات المحلية التلقائية في حين أن استدعاء <code>‎std::exit‎</code> مباشرة لا يفعل ذلك.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7248_69" style="">
<span class="typ">int</span><span class="pln"> main</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> argc</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> </span><span class="pun">**</span><span class="pln"> argv</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">argc </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">2</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Missing argument\n"</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> EXIT_FAILURE</span><span class="pun">;</span><span class="pln"> </span><span class="com">// exit(EXIT_FAILURE); يكافئ</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	هذا الدرس جزء من <a data-ss1617022357="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة دروس عن C++‎</a>.
</p>

<p>
	ترجمة -بتصرّف- للفصل Chapter 15: Flow Control من كتاب <a data-ss1617022357="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">896</guid><pubDate>Fri, 19 Jun 2020 18:02:00 +0000</pubDate></item><item><title>&#x62F;&#x62E;&#x644; &#x648;&#x62E;&#x631;&#x62C; &#x627;&#x644;&#x645;&#x644;&#x641;&#x627;&#x62A; (File I/O) &#x641;&#x64A; Cpp</title><link>https://academy.hsoub.com/programming/cpp/%D8%AF%D8%AE%D9%84-%D9%88%D8%AE%D8%B1%D8%AC-%D8%A7%D9%84%D9%85%D9%84%D9%81%D8%A7%D8%AA-file-io-%D9%81%D9%8A-cpp-r895/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_06/11.jpg.599b0c28d357b8badd1779481c5816d9.jpg" /></p>

<p>
	تستخدم لغة C++‎ <a data-ss1617022354="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-10-%D9%85%D8%AC%D8%A7%D8%B1%D9%8A-%D8%A7%D9%84%D8%AA%D8%AF%D9%81%D9%82-streams-%D9%88%D9%85%D8%B9%D8%A7%D9%84%D9%90%D8%AC%D8%A7%D8%AA%D9%87%D8%A7-%D9%81%D9%8A-cpp-r894/" rel="">مجاري التدفق</a> لإدارة دخل وخرج الملفات، إذ تستخدم:
</p>

<ul>
<li>
		<code>std::istream</code> لقراءة النص.
	</li>
	<li>
		<code>std::ostream</code> لكتابة النص.
	</li>
	<li>
		<code>std::streambuf</code> لقراءة أو كتابة المحارف.
	</li>
	<li>
		يستخدم الدَّخل المُنسّق (Formatted input) العاملَ‏‏ <code>‎operator&gt;&gt;‎</code>.
	</li>
	<li>
		يستخدم الخرج المنسّق العامل <code>‎operator&lt;&lt;‎</code>.
	</li>
</ul>
<p>
	تستخدم المجاري <code>‎std::locale‎</code> مثلًا للحصول على تفاصيل التنسيق والترجمة بين الترميزات الخارجية والترميز الداخلي.
</p>

<h2>
	الكتابة في الملفات
</h2>

<p>
	هناك عدة طرق للكتابة في ملف، لعل أسهلها هو استخدام مجرى خرج الملفّات <code>‎ofstream‎</code> مع عامل الإدارج في المجرى (<code>‎&lt;&lt;‎</code>)، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6545_7" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">ofstream os</span><span class="pun">(</span><span class="str">"foo.txt"</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">if</span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">is_open</span><span class="pun">()){</span><span class="pln">
os </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Hello World!"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تستطيع استخدام الدالة التابعة لمجرى خرج الملفّات <code>‎write()‎</code> بدلًا من <code>‎&lt;&lt;‎</code>، انظر المثال التالي حيث سنكتب ثلاثة محارف من <code>data</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6545_9" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">ofstream os</span><span class="pun">(</span><span class="str">"foo.txt"</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">is_open</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">char</span><span class="pln"> data</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Foo"</span><span class="pun">;</span><span class="pln">
    os</span><span class="pun">.</span><span class="pln">write</span><span class="pun">(</span><span class="pln">data</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يجب أن تتحقق دائمًا بعد الكتابة في المجرى من راية حالة الخطأ <code>badbit</code>، إذ أنها تشير إلى نجاح العملية أو فشلها، وتستطيع ذلك باستدعاء دالة تابع مجرى خَرْج الملف <code>‎bad()‎</code>، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6545_11" style="">
<span class="pln">os </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Hello Badbit!"</span><span class="pun">;</span><span class="pln"> </span><span class="com">// قد تفشل هذه العملية لسبب ما</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">os</span><span class="pun">.</span><span class="pln">bad</span><span class="pun">())</span><span class="pln">
</span><span class="com">// فشل في الكتابة</span></pre>

<h2>
	فتح ملف
</h2>

<p>
	تُفتح الملفات بنفس الطّريقة في جميع مجاري الملفات الثلاث (<code>‎ifstream‎</code>، <code>‎ofstream‎</code>، و<code>‎fstream‎</code>). يمكنك فتح الملف مباشرة في المُنشئ (constructor)، انظر المثال التالي حيث نفتح الملف foo.txt للقراءة فقط، ثم للكتابة فقط، ثم للقراءة والكتابة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6545_13" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">ifstream ifs</span><span class="pun">(</span><span class="str">"foo.txt"</span><span class="pun">);</span><span class="pln"> 
std</span><span class="pun">::</span><span class="pln">ofstream ofs</span><span class="pun">(</span><span class="str">"foo.txt"</span><span class="pun">);</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">fstream iofs</span><span class="pun">(</span><span class="str">"foo.txt"</span><span class="pun">);</span><span class="pln"> </span></pre>

<p>
	أو يمكنك استخدام دالة تابع مجرى الملف <code>‎open()‎</code> لتنفيذ نفس الشيء:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6545_15" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">ifstream ifs</span><span class="pun">;</span><span class="pln">
ifs</span><span class="pun">.</span><span class="pln">open</span><span class="pun">(</span><span class="str">"bar.txt"</span><span class="pun">);</span><span class="pln"> </span><span class="com">// للقراءة فقط  "bar.txt" فتح الملف</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">ofstream ofs</span><span class="pun">;</span><span class="pln">
ofs</span><span class="pun">.</span><span class="pln">open</span><span class="pun">(</span><span class="str">"bar.txt"</span><span class="pun">);</span><span class="pln"> </span><span class="com">// للكتابة فقط  "bar.txt" فتح الملف</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">fstream iofs</span><span class="pun">;</span><span class="pln">
iofs</span><span class="pun">.</span><span class="pln">open</span><span class="pun">(</span><span class="str">"bar.txt"</span><span class="pun">);</span><span class="pln"> </span><span class="com">// للقراءة والكتابة "bar.txt" فتح الملف</span></pre>

<p>
	يجب عليك التحقّق دائمًا ممّا إذا كان الملف قد فُتِح بنجاح (حتى أثناء الكتابة)، قد تفشل عملية الفتح لعدة أسباب، انظر بعضها فيما يلي:
</p>

<ul>
<li>
		عدم وجود الملف
	</li>
	<li>
		صلاحيات الوصول (access rights) غير صالحة.
	</li>
	<li>
		الملف قيد الاستخدام في الوقت الراهن.
	</li>
	<li>
		وقوع خطأ في القرص.
	</li>
	<li>
		فصل القرص من الحاسوب.
	</li>
	<li>
		…
	</li>
</ul>
<p>
	يمكن إجراء عملية التحقّق على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6545_17" style="">
<span class="com">// 'foo.txt' محاولة قراءة</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">ifstream ifs</span><span class="pun">(</span><span class="str">"fooo.txt"</span><span class="pun">);</span><span class="pln"> </span><span class="com">// خطأ في الكتابة، لا يمكن فتح الملف</span><span class="pln">

</span><span class="com">// التحقق مما إذا كان الملف قد فُتِح بنجاح</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">ifs</span><span class="pun">.</span><span class="pln">is_open</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// لم يُفتح الملف بعد، اتخاذ الإجراءات المناسبة</span><span class="pln">
    </span><span class="kwd">throw</span><span class="pln"> </span><span class="typ">CustomException</span><span class="pun">(</span><span class="pln">ifs</span><span class="pun">,</span><span class="pln"> </span><span class="str">"الملف لم يُفتح"</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	إن كان المسار يحتوي على شرطة مائلة عكسية <code>\</code> كما هو الحال في نظام Windows، فيجب أن تهربها بشكل سليم. انظر المثال التالي لفتح الملف foo.txt في ويندوز:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6545_19" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">ifstream ifs</span><span class="pun">(</span><span class="str">"c:\\\\folder\\\\foo.txt"</span><span class="pun">);</span><span class="pln"> </span><span class="com">// تهريب الشرطة المائلة العكسية</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	أو يمكنك استخدام القيم مصنفة النوع الخام (raw literal)، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6545_21" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">ifstream ifs</span><span class="pun">(</span><span class="pln">R</span><span class="str">"(c:\\folder\\foo.txt)"</span><span class="pun">);</span><span class="pln"> </span><span class="com">// استخدام  قيم مصنفة النوع خام</span></pre>

<p>
	أو استخدم شرطة مائلة <code>/</code> بدلاً من ذلك:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6545_23" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">ifstream ifs</span><span class="pun">(</span><span class="str">"c:/folder/foo.txt"</span><span class="pun">);</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	إن أردت أن تفتح ملفًّا يحتوي على محارف من غير ASCII في مسارٍ في Windows، فيمكنك حاليًا استخدام المَحرَف العام غير القياسي (non-standard wide character) في المسار، انظر المثال التالي حيث نضع كلمة "مثال" بالبلغارية في مسار الملف:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6545_25" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">ifstream ifs</span><span class="pun">(</span><span class="pln">LR</span><span class="str">"(пример\\foo.txt)"</span><span class="pun">);</span><span class="pln"> </span><span class="com">// استخدام محرف عام مع سلسلة نصية خام</span></pre>

<h2>
	القراءة من ملف
</h2>

<p>
	هناك عدة طرق لقراءة البيانات من ملف، فإن كنت تعرف تنسيق (format) البيانات فيمكنك استخدام عامل الاستخراج من المجرى - stream extraction operator‏‏ - (<code>‎&gt;&gt;‎</code>). دعنا نفرض أنّ لديك ملفّا يُسمّى foo.txt يحتوي على البيانات التالية:
</p>

<pre class="ipsCode">
John Doe 25 4 6 1987
Jane Doe 15 5 24 1976
</pre>

<p>
	فعندها يمكنك استخدام الشّيفرة أدناه لقراءة تلك البيانات من الملف، لاحظ أننا سنستخرج الاسم الأول <code>firstname</code> واسم العائلة <code>lastname</code> والعمر <code>age</code> وشهر الولادة <code>bmonth</code> ويوم الولادة <code>bday</code> وعام الولادة <code>byear</code>. أيضًا، انتبه إلى أن <code>‎&gt;&gt;‎</code> تعيد القيمة <code>false</code> إن بلغت نهاية الملف أو لم تتوافق بيانات الدخل مع نوع المتغير، فلا يمكن استخراج نص <code>foo</code> إلى متغير <code>int</code> مثلًا.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6545_27" style="">
<span class="com">// تعريف المتغيرات</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">ifstream is</span><span class="pun">(</span><span class="str">"foo.txt"</span><span class="pun">);</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">string firstname</span><span class="pun">,</span><span class="pln"> lastname</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> age</span><span class="pun">,</span><span class="pln"> bmonth</span><span class="pun">,</span><span class="pln"> bday</span><span class="pun">,</span><span class="pln"> byear</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">is </span><span class="pun">&gt;&gt;</span><span class="pln"> firstname </span><span class="pun">&gt;&gt;</span><span class="pln"> lastname </span><span class="pun">&gt;&gt;</span><span class="pln"> age </span><span class="pun">&gt;&gt;</span><span class="pln"> bmonth </span><span class="pun">&gt;&gt;</span><span class="pln"> bday </span><span class="pun">&gt;&gt;</span><span class="pln"> byear</span><span class="pun">)</span><span class="pln">
</span><span class="com">// معالجة البيانات المقروءة</span></pre>

<p>
	يستخرج العامل <code>‎&gt;&gt;‎</code> كل المحارف ويتوقف إذا وجد حرفًا لا يمكنه تخزينه أو محرفًا خاصًّا (special character):
</p>

<ul>
<li>
		بالنسبة للسًلاسل النصية، يتوقًف العامل عند المسافة الفارغة ()، أو عند السًطر الجديد (<code>‎\n‎</code>).
	</li>
	<li>
		بالنًسبة للأعداد، يتوقف العامل عند المحارف غير الرقمية.
	</li>
</ul>
<p>
	هذا يعني أنّ النُّسخ التالية من ملف <code>foo.txt</code> ستُقرأ بنجاح من قبل الشّيفرة السابقة:
</p>

<pre class="ipsCode">
John
Doe 25
4 6 1987
Jane
Doe
15 5
24
1976
</pre>

<p>
	يعيدُ عاملُ <code>‎&gt;&gt;‎</code> المجرى المُمرّرَ إليه، لهذا يمكن سَلْسَلةُ هذا العامل من أجل قراءة البيانات على التوالي. كذلك من الممكن استخدام المجرى كتعبير بولياني (كما هو مُوضّح في حلقة <code>‎while‎</code> في الشّيفرة السابقة)، ذلك أن أصناف المجرى بها عامل تحويل للنوع <code>‎bool‎</code>.
</p>

<p>
	سيعيد العامل <code>‎bool()‎</code> القيمة <code>‎true‎</code> طالما أنّ المجرى لا يحتوي على أخطاء، أما إن تغيّرت حالة المجرى إلى حالة خطأ (على سبيل المثال، إذا لم يكن من الممكن استخراج مزيد من البيانات)، فسوف يعيد العاملُ <code>‎bool()‎</code> القيمة<code>‎false‎</code>، وعليه فإن حلقة <code>‎while‎</code> في الشّيفرة السابقة ستُنهى بعد قراءة كامل الملف.
</p>

<p>
	إذا أردت قراءة كامل الملف كسلسلة نصّية، فيمكنك استخدام الشّيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6545_29" style="">
<span class="com">// 'foo.txt' فتح</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">ifstream is</span><span class="pun">(</span><span class="str">"foo.txt"</span><span class="pun">);</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">string whole_file</span><span class="pun">;</span><span class="pln">

</span><span class="com">// الذهاب إلى نهاية الملف</span><span class="pln">
is</span><span class="pun">.</span><span class="pln">seekg</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">ios</span><span class="pun">::</span><span class="pln">end</span><span class="pun">);</span><span class="pln">

</span><span class="com">// تخصيص ذاكرة للملف</span><span class="pln">
whole_file</span><span class="pun">.</span><span class="pln">reserve</span><span class="pun">(</span><span class="pln">is</span><span class="pun">.</span><span class="pln">tellg</span><span class="pun">());</span><span class="pln">

</span><span class="com">// الذهاب إلى بداية الملف</span><span class="pln">
is</span><span class="pun">.</span><span class="pln">seekg</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">ios</span><span class="pun">::</span><span class="pln">beg</span><span class="pun">);</span><span class="pln">

</span><span class="com">// 'whole_file' تعيين محتوى</span><span class="pln">
</span><span class="com">// إلى جميع محارف الملف</span><span class="pln">
whole_file</span><span class="pun">.</span><span class="pln">assign</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">istreambuf_iterator</span><span class="str">&lt;char&gt;</span><span class="pun">(</span><span class="pln">is</span><span class="pun">),</span><span class="pln">
   std</span><span class="pun">::</span><span class="pln">istreambuf_iterator</span><span class="str">&lt;char&gt;</span><span class="pun">());</span></pre>

<p>
	توفر هذه الشيفرة مساحة للسّلسلة النصية <code>‎string‎</code> من أجل الاقتصاد في الذاكرة. أما إن أردت قراءة الملف سطرًا سطرًا، فيمكنك استخدام الدالة <code>‎getline()‎</code>، انظر المثال التالي حيث تعيد هذه الدالة القيمة <code>false</code> إن لم يكن ثمة أسطر أخرى متبقية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6545_31" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">ifstream is</span><span class="pun">(</span><span class="str">"foo.txt"</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string str</span><span class="pun">;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">getline</span><span class="pun">(</span><span class="pln">is</span><span class="pun">,</span><span class="pln"> str</span><span class="pun">);)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// معالجة السّطر المقروء</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	إذا أردت قراءة عدد محدّد من المحارف فاستخدم دالة تابع المجرى <code>‎read()‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6545_33" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">ifstream is</span><span class="pun">(</span><span class="str">"foo.txt"</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">char</span><span class="pln"> str</span><span class="pun">[</span><span class="lit">4</span><span class="pun">];</span><span class="pln">
</span><span class="com">// قراءة أربعة حروف من الملف</span><span class="pln">
is</span><span class="pun">.</span><span class="pln">read</span><span class="pun">(</span><span class="pln">str</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">);</span></pre>

<p>
	يجب أن تتحقق دائمًا بعد تنفيذ أمر القراءة من راية حالة الخطأ <code>failbit</code> إذ أنها تشير إلى نجاح العملية أو فشلها، وتستطيع ذلك باستدعاء دالة تابع مجرى خَرْج الملف <code>‎fail()‎</code>، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6545_35" style="">
<span class="pln">is</span><span class="pun">.</span><span class="pln">read</span><span class="pun">(</span><span class="pln">str</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">);</span><span class="pln"> </span><span class="com">// قد تفشل هذه العملية لسبب ما</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">is</span><span class="pun">.</span><span class="pln">fail</span><span class="pun">())</span><span class="pln">
</span><span class="com">// فشل في القراءة!</span></pre>

<h2>
	أوضاع الفتح
</h2>

<p>
	يمكنك تحديد وضع الفتح عند إنشاء مجرى ملف، ووضع الفتح ما هو إلا إعداد للتّحكم في كيفيّة فتح المجرى للملف، تستطيع العثور على جميع الأوضاع في مجال اسم <code>‎std::ios‎</code>. يمكن تمرير وضع الفتح كمعامل ثاني إلى منشئ مجرى الملف أو إلى تابعه <code>‎open()‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6545_37" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">ofstream os</span><span class="pun">(</span><span class="str">"foo.txt"</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">ios</span><span class="pun">::</span><span class="pln">out </span><span class="pun">|</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">ios</span><span class="pun">::</span><span class="pln">trunc</span><span class="pun">);</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">ifstream is</span><span class="pun">;</span><span class="pln">
is</span><span class="pun">.</span><span class="pln">open</span><span class="pun">(</span><span class="str">"foo.txt"</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">ios</span><span class="pun">::</span><span class="pln">in </span><span class="pun">|</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">ios</span><span class="pun">::</span><span class="pln">binary</span><span class="pun">);</span></pre>

<p>
	تجدر الإشارة إلى أنّه يجب عليك تعيين معامِل الوضع الافتراضي <code>‎ios::in‎</code> أو <code>‎ios::out‎</code> إذا أردت تعيين قيم الرايات الأخرى، لأنها لا تٌعيّن ضمنيًا من قبل أعضاء مجرى الدّخل (iostream) رغم أنّ لديها قيمة افتراضية صحيحة.
</p>

<p>
	يُستخدم وضع الفتح الافتراضي أدناه إذا لم تحدِّد وضعًا للفتح:
</p>

<ul>
<li>
		ifstream - دخل
	</li>
	<li>
		ofstream - خرج
	</li>
	<li>
		fstream - دخل وخرج
	</li>
</ul>
<p>
	أوضاع الفتح التي تستطيع تحديدها هي:
</p>

<table>
<thead><tr>
<th>
				الوضع
			</th>
			<th>
				المعنى
			</th>
			<th>
				الغرض
			</th>
			<th>
				الوصف
			</th>
		</tr></thead>
<tbody>
<tr>
<td>
				app
			</td>
			<td>
				ألحِق (append)
			</td>
			<td>
				إخراج
			</td>
			<td>
				إضافة البيانات إلى نهاية الملف
			</td>
		</tr>
<tr>
<td>
				binary
			</td>
			<td>
				ثنائي/بِتِّي (Binary)
			</td>
			<td>
				إخراج/إدخال
			</td>
			<td>
				الإدخال والإخراج يحدث بالبتات
			</td>
		</tr>
<tr>
<td>
				in
			</td>
			<td>
				دخل (input)
			</td>
			<td>
				إدخال
			</td>
			<td>
				فتح الملف للقراءة
			</td>
		</tr>
<tr>
<td>
				out
			</td>
			<td>
				خرج (output)
			</td>
			<td>
				إخراج
			</td>
			<td>
				فتح الملف للكتابة
			</td>
		</tr>
<tr>
<td>
				trunc
			</td>
			<td>
				بتر (truncate)
			</td>
			<td>
				إخراج/إدخال
			</td>
			<td>
				حذف محتوى الملف عند الفتح
			</td>
		</tr>
<tr>
<td>
				ate
			</td>
			<td>
				عند النهاية (at end)
			</td>
			<td>
				إدخال
			</td>
			<td>
				الذهاب إلى نهاية الملف عند الفتح
			</td>
		</tr>
</tbody>
</table>
<style type="text/css">
table {
    width: 100%;
}

thead {
    vertical-align: middle;
    text-align: center;
}

td, th {
    border: 1px solid #dddddd;
    text-align: right;
    padding: 8px;
    text-align: inherit;

}
tr:nth-child(even) {
    background-color: #dddddd;
}</style>
<p>
	<strong>ملاحظة</strong>: في حال تعيين الوضع البتّي <code>‎binary‎</code>، فستُقرأ وتُكتب البيانات تمامًا كما هي؛ أما إن لم تُحدَّد فسيكون ممكنًا ترجمة محرف السّطر الجديد <code>‎'\n'‎</code> إلى نهاية السّطر المناسبة لنظام التشغيل المستخدم. على سبيل المثال، في نظام Windows، تسلسل نهاية السطر هو CRLF ‏‏(<code>‎"\r\n"‎</code>).
</p>

<ul>
<li>
		الكتابة:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6545_39" style="">
<span class="str">"\n"</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">"\r\n"</span></pre>

<ul>
<li>
		القراءة:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6545_41" style="">
<span class="str">"\r\n"</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">"\n"</span></pre>

<h2>
	قراءة ملف ASCII إلى مكتبة <code>std::string</code>
</h2>

<p>
	انظر المثال التالي، سيكون محتوى <code>file.txt</code> موجودًا في <code>buffer.str()‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6545_43" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">ifstream f</span><span class="pun">(</span><span class="str">"file.txt"</span><span class="pun">);</span><span class="pln">

</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">f</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">stringstream buffer</span><span class="pun">;</span><span class="pln">
    buffer </span><span class="pun">&lt;&lt;</span><span class="pln"> f</span><span class="pun">.</span><span class="pln">rdbuf</span><span class="pun">();</span><span class="pln">
    f</span><span class="pun">.</span><span class="pln">close</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يعيد التابع <code>‎rdbuf()‎</code> مؤشرًا إلى <code><a data-ss1617022354="1" href="https://en.cppreference.com/w/cpp/io/basic_streambuf" rel="external nofollow">‎streambuf‎</a></code>، والذي يمكن إضافته إلى المخزن المؤقّت <code>‎buffer‎</code> عبر دالة التابع <code>stringstream::operator&lt;&lt;‎</code>. هناك احتمال آخر (من اقتراح <a data-ss1617022354="1" href="https://www.aristeia.com/" rel="external nofollow">سكوت مايرز</a>):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6545_46" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">ifstream f</span><span class="pun">(</span><span class="str">"file.txt"</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">f</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">string str</span><span class="pun">((</span><span class="pln">std</span><span class="pun">::</span><span class="pln">istreambuf_iterator</span><span class="str">&lt;char&gt;</span><span class="pun">(</span><span class="pln">f</span><span class="pun">)),</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">istreambuf_iterator</span><span class="str">&lt;char&gt;</span><span class="pun">());</span><span class="pln">
</span><span class="com">// `str` عمليّات على</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	هذه الطّريقة لا تحتاج شيفرة كبيرة وتسمح بقراءة الملفّ مباشرة إلى أي حاوية مكتبة قياسيّة وليست قاصرة على السّلاسل النصية فقط، لكن قد تكون بطيئة إن كان الملف كبيرُا.
</p>

<p>
	<strong>ملاحظة</strong>: الأقواس الإضافية حول الوسيط الأول في مُنشئ السّلسلة النصية ضرورية لمنع حدوث مشكلة في التحليل (parsing).
</p>

<p>
	وأخيرًا وليس آخرًا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6545_48" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">ifstream f</span><span class="pun">(</span><span class="str">"file.txt"</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">f</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    f</span><span class="pun">.</span><span class="pln">seekg</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">ios</span><span class="pun">::</span><span class="pln">end</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> size </span><span class="pun">=</span><span class="pln"> f</span><span class="pun">.</span><span class="pln">tellg</span><span class="pun">();</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">string str</span><span class="pun">(</span><span class="pln">size</span><span class="pun">,</span><span class="pln"> </span><span class="str">' '</span><span class="pun">);</span><span class="pln">
    f</span><span class="pun">.</span><span class="pln">seekg</span><span class="pun">(</span><span class="lit">0</span><span class="pun">);</span><span class="pln">
    f</span><span class="pun">.</span><span class="pln">read</span><span class="pun">(</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> str</span><span class="pun">[</span><span class="lit">0</span><span class="pun">],</span><span class="pln"> size</span><span class="pun">);</span><span class="pln">
    f</span><span class="pun">.</span><span class="pln">close</span><span class="pun">();</span><span class="pln">
    </span><span class="com">// `str` عمليات على</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	وهو أسرع خيار من بين الخيارات الثلاثة المقترحة.
</p>

<h2>
	الكتابة في الملفات باستخدام إعدادات محليّة غير قياسية
</h2>

<p>
	استخدم <code>‎std::locale‎</code> و <code>‎std::basic_ios::imbue()‎</code> إن كنت بحاجة إلى الكتابة في ملف باستخدام إعدادات محليّة غير الإعدادات الافتراضية، واسترشد بالتوجيهات الآتية:
</p>

<ul>
<li>
		يجب عليك دائمًا تطبيق إعدادات محليّة على المجرى قبل فتح الملف.
	</li>
	<li>
		بمجرد أن تطعِّم المجرى بالإعدادات الجديدة، لا تغيّر الإعدادات المحليّة.
	</li>
</ul>
<p>
	أسباب تلك التوجيهات: تحويل مجرى ملف إلى إعدادات محليّة ستكون له تداعيات غير متوقّعه إذا لم تكن الإعدادات الحاليّة مستقلّة، أو إن لم تكن تشير إلى بداية الملف.
</p>

<p>
	مجاري UTF-8 وغيرها ليست مستقلة، كما أنّ مجاري الملفّات ذات الإعدادات المحليّة UTF-8 قد تحاول قراءة المِحرف BOM من الملف عند فتحه؛ لذلك فعليك أن تنتبه، فقراءة الملف بعد الفتح قد لا تكون من بدايته دائمًا.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6545_50" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;fstream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;locale&gt;</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"User-preferred locale setting is "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">locale</span><span class="pun">(</span><span class="str">""</span><span class="pun">).</span><span class="pln">name</span><span class="pun">().</span><span class="pln">c_str</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">

    </span><span class="com">// اكتب عدد عشري باستخدام الإعدادات المحليّة للمستخدم</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">ofstream ofs1</span><span class="pun">;</span><span class="pln">
    ofs1</span><span class="pun">.</span><span class="pln">imbue</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">locale</span><span class="pun">(</span><span class="str">""</span><span class="pun">));</span><span class="pln">
    ofs1</span><span class="pun">.</span><span class="pln">open</span><span class="pun">(</span><span class="str">"file1.txt"</span><span class="pun">);</span><span class="pln">
    ofs1 </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">78123.456</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// استخدم إعدادات محليّة محددة، الأسماء تختلف من نظام لآخر</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">ofstream ofs2</span><span class="pun">;</span><span class="pln">
    ofs2</span><span class="pun">.</span><span class="pln">imbue</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">locale</span><span class="pun">(</span><span class="str">"en_US.UTF-8"</span><span class="pun">));</span><span class="pln">
    ofs2</span><span class="pun">.</span><span class="pln">open</span><span class="pun">(</span><span class="str">"file2.txt"</span><span class="pun">);</span><span class="pln">
    ofs2 </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">78123.456</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// "C" التحوّل إلى الإعدادات المحليّة لـ</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">ofstream ofs3</span><span class="pun">;</span><span class="pln">
    ofs3</span><span class="pun">.</span><span class="pln">imbue</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">locale</span><span class="pun">::</span><span class="pln">classic</span><span class="pun">());</span><span class="pln">
    ofs3</span><span class="pun">.</span><span class="pln">open</span><span class="pun">(</span><span class="str">"file3.txt"</span><span class="pun">);</span><span class="pln">
    ofs3 </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">78123.456</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	التبديل إلى الإعدادات المحليّة التقليدية للغة "C" مفيد في حال كان البرنامج يستخدم لغة افتراضيّة مختلفة وكنت تريد توحيد معيار القراءة والكتابة. وإن استخدمنا الإعدادات المحليّة المفضّلة في "C"، فإنّ المثال أعلاه سيُكتب هكذا:
</p>

<pre class="ipsCode">
78,123.456
78,123.456
78123.456
</pre>

<p>
	على سبيل المثال، إذا كانت الإعدادات المحليّة المفضّلة هي اللغة الألمانية ومن ثم فإنها تستخدم تنسيقا مختلفًا للأرقام، فإنّ المثال سيُكتب هكذا:
</p>

<pre class="ipsCode">
78 123,456
78,123.456
78123.456
</pre>

<p>
	(لاحظ الفاصلة العشرية في السطر الأول).
</p>

<h2>
	تجنب التحقق من نهاية الملف داخل شرط الحلقة
</h2>

<p>
	لا تعيد <code>‎eof‎</code> القيمة <code>true</code> إلا بعد قراءة نهاية الملف، وهي لا تشير إلى أنّ القراءة التالية ستكون نهاية المجرى. انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6545_52" style="">
<span class="kwd">while</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">f</span><span class="pun">.</span><span class="pln">eof</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// هذا يبدو جيدًا</span><span class="pln">
    f </span><span class="pun">&gt;&gt;</span><span class="pln"> buffer</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// صحيحة eof هنا تصبح  </span><span class="pln">
    </span><span class="com">/* `buffer` استخدم */</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكن أن تكتب أيضًا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6545_54" style="">
<span class="kwd">while</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">f</span><span class="pun">.</span><span class="pln">eof</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    f </span><span class="pun">&gt;&gt;</span><span class="pln"> buffer </span><span class="pun">&gt;&gt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">ws</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">f</span><span class="pun">.</span><span class="pln">fail</span><span class="pun">())</span><span class="pln">
        </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
    </span><span class="com">/* `buffer` استخدم */</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لكنّ الشّيفرة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6545_56" style="">
<span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">f </span><span class="pun">&gt;&gt;</span><span class="pln"> buffer</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">/* `buffer` استخدم */</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	أبسط وأصحّ.
</p>

<p>
	مراجع أخرى:
</p>

<ul>
<li>
		<a data-ss1617022354="1" href="https://en.cppreference.com/w/cpp/io/manip/ws" rel="external nofollow"><code>std::ws</code></a>: تتجاهل المسافة البيضاء في بداية مجرى الدخل.
	</li>
	<li>
		<a data-ss1617022354="1" href="https://en.cppreference.com/w/cpp/io/basic_ios/fail" rel="external nofollow"><code>std::basic_ios::fail</code></a>: تعيد <code>true</code> إذا حدث خطأ في المجرى المرتبط بها.
	</li>
</ul>
<h2>
	تفريغ المجرى (Flushing a stream)
</h2>

<p>
	تقوم مجاري الملفات -إضافة إلى العديد من أنواع المجاري الأخرى- بالتخزين المؤقت (buffering) افتراضيًا، وذلك يعني أن الكتابة في المجرى قد لا تؤدي إلى تغير الملف المقابل فورًا، بل يجب أن تفرِّغ المجرى إن أردت ذلك، إما باستدعاء التابع <code>‎flush()‎</code> أو عبر معالج المجرى <code>‎std::flush‎</code>، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6545_58" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">ofstream os</span><span class="pun">(</span><span class="str">"foo.txt"</span><span class="pun">);</span><span class="pln">
os </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Hello World!"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">flush</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">char</span><span class="pln"> data</span><span class="pun">[</span><span class="lit">3</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Foo"</span><span class="pun">;</span><span class="pln">
os</span><span class="pun">.</span><span class="pln">write</span><span class="pun">(</span><span class="pln">data</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">);</span><span class="pln">
os</span><span class="pun">.</span><span class="pln">flush</span><span class="pun">();</span></pre>

<p>
	يجمع مُعالج المجرى <code>‎std::endl‎</code> بين كتابة سطر جديد وتفريغ المجرى، انظر الشيفرة التالية حيث ينفِّذ كلا السطران نفس الشيء:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6545_60" style="">
<span class="pln">os </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Hello World!\n"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">flush</span><span class="pun">;</span><span class="pln">
os </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Hello world!"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></pre>

<p>
	يحسّن التخزين المؤقّت (Buffering) أداء عمليات الكتابة في المجرى، لهذا يُفضّل أن تتجنّب التطبيقاتُ كثيرةُ الكتابةِ استخدام التفريع ما لم يكن لازمًا. لكن على العكس من ذلك، إذا لم يكن البرنامج يكثر من عمليات الدّخل والخرج (I/O)، فمن الأفضل الإكثار من التفريغ لتجنب تكدّس البيانات في كائن المجرى.
</p>

<h2>
	قراءة ملف في حاوية
</h2>

<p>
	في المثال التالي، سنستخدم <code>‎std::string‎</code> و <code>‎operator&gt;&gt;‎</code> لقراءة عناصر من ملف.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6545_62" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">ifstream file</span><span class="pun">(</span><span class="str">"file3.txt"</span><span class="pun">);</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&gt;</span><span class="pln"> v</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">string s</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">file </span><span class="pun">&gt;&gt;</span><span class="pln"> s</span><span class="pun">)</span><span class="pln"> </span><span class="com">// الاستمرار في القراءة حتى النهاية</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    v</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="pln">s</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	في المثال أعلاه، كرّرنا -من iterate- على الملف بقراءة "عنصر" واحد في كل مرّة باستخدام العامل <code>&lt;&lt;‎</code>. يمكن تحقيق الشّيء نفسه باستخدام <code>‎std::istream_iterator‎</code>، والذي هو مكرّر دخْلٍ يقرأ "عنصرًا" واحدًا في كل مرة من المجرى. كذلك يمكن إنشاء معظم الحاويات باستخدام مُكرِّرين كما يلي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6545_64" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">ifstream file</span><span class="pun">(</span><span class="str">"file3.txt"</span><span class="pun">);</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">&gt;</span><span class="pln">     v</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">istream_iterator</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">&gt;{</span><span class="pln">file</span><span class="pun">},</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">istream_iterator</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">&gt;{});</span></pre>

<p>
	يمكننا توسيع هذه الشّيفرة لقراءة أيّ نوع من الكائنات من خلال تمرير الكائن الذي نريد قراءته كمعامل قالب (template parameter) إلى <code>‎std::istream_iterator‎</code>. وهكذا، يمكننا توسيع الشّيفرة السّابقة لقراءة الأسطر (بدلاً من الكلمات). انظر المثال التالي، لاحظ أنه لعدم وجود نوع مضمّن يقرأ الأسطر باستخدام <code>&lt;&lt;</code> فإننا سنبني صنفًا مساعدًا لفعل ذلك، وسيقوم بعملية التحويل إلى سلسلة نصية (string) عند استخدامه في سياق نصي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6545_66" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Line</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// تخزين البيانات هنا</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">string data</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// تحويل الكائن إلى سلسلة نصية</span><span class="pln">
    </span><span class="kwd">operator</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string
    </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> data</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="com">// قراءة سطر من المجرى</span><span class="pln">
    </span><span class="kwd">friend</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">istream </span><span class="pun">&amp;</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">istream </span><span class="pun">&amp;</span><span class="pln"> stream</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Line</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> line</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">getline</span><span class="pun">(</span><span class="pln">stream</span><span class="pun">,</span><span class="pln"> line</span><span class="pun">.</span><span class="pln">data</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">

std</span><span class="pun">::</span><span class="pln">ifstream file</span><span class="pun">(</span><span class="str">"file3.txt"</span><span class="pun">);</span><span class="pln">

</span><span class="com">// قراءة أسطر الملف إلى حاوية</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="pun">&lt;</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">&gt;</span><span class="pln">     v</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">istream_iterator</span><span class="pun">&lt;</span><span class="typ">Line</span><span class="pun">&gt;{</span><span class="pln">file</span><span class="pun">},</span><span class="pln">
                   std</span><span class="pun">::</span><span class="pln">istream_iterator</span><span class="pun">&lt;</span><span class="typ">Line</span><span class="pun">&gt;{});</span></pre>

<h2>
	نسخ الملفات
</h2>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6545_68" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">ifstream  src</span><span class="pun">(</span><span class="str">"source_filename"</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">ios</span><span class="pun">::</span><span class="pln">binary</span><span class="pun">);</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">ofstream  dst</span><span class="pun">(</span><span class="str">"dest_filename"</span><span class="pun">,</span><span class="pln">   std</span><span class="pun">::</span><span class="pln">ios</span><span class="pun">::</span><span class="pln">binary</span><span class="pun">);</span><span class="pln">
dst </span><span class="pun">&lt;&lt;</span><span class="pln"> src</span><span class="pun">.</span><span class="pln">rdbuf</span><span class="pun">();</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 17</strong>
</p>

<p>
	الطريقة القياسيّة لنسخ ملف في C++‎ 17 هي تضمين التّرويسة <filesystem>، واستخدام <code>‎copy_file‎</code>، انظر:</filesystem></p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6545_70" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">fileystem</span><span class="pun">::</span><span class="pln">copy_file</span><span class="pun">(</span><span class="str">"source_filename"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"dest_filename"</span><span class="pun">);</span></pre>

<p>
	طُوِّرت المكتبة filesystem في البداية كوحدة ‎boost‏‏ (<code>‎boost.filesystem‎</code>)، تم دُمِجت بعد ذلك في التوصيف ISO C++‎ بدءًا من C++‎ 17.
</p>

<h2>
	إغلاق ملف
</h2>

<p>
	نادرًا ما يكون عليك إغلاق الملفات في C++‎، لأنّ المجرى سوف يغلق الملف المرتبط به تلقائيًا في المفكك (destructor) الخاص به. ومع ذلك يُفضّل أن تحُدّّ من عمر كائنات المجرى، حتى لا يبقى مِقبض (handle) الملفّ مفتوحًا لفترة أطول من اللازم.
</p>

<p>
	على سبيل المثال، يمكنك فعل ذلك عبر وضع جميع العمليّات المُنفّذة على الملف في نطاق خاص (<code>‎{}‎</code>)، لاحظ أن <code>ofstream</code> ستكون خارج النطاق بنهاية هذه الشيفرة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6545_72" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">string
</span><span class="kwd">const</span><span class="pln"> prepared_data </span><span class="pun">=</span><span class="pln"> prepare_data</span><span class="pun">();</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// فتح ملف للكتابة</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">ofstream output</span><span class="pun">(</span><span class="str">"foo.txt"</span><span class="pun">);</span><span class="pln">
    </span><span class="com">// كتابة البيانات</span><span class="pln">
    output </span><span class="pun">&lt;&lt;</span><span class="pln"> prepared_data</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="com">// سيتولى المدمر إغلاق الملف</span></pre>

<p>
	لا يكون استدعاء <code>‎close()‎</code> بشكل صريح ضروريًّا إلا إن أردت إعادة استخدام نفس كائن <code>‎fstream‎</code> لاحقًا لكنّك لم ترغب في إبقائه مفتوحًا إلى ذلك الحين، انظر المثال التالي الذي نجريه على ملف <code>foo.txt</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6545_74" style="">
<span class="com">// افتح الملف لأول مرة</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">ofstream output</span><span class="pun">(</span><span class="str">"foo.txt"</span><span class="pun">);</span><span class="pln">

</span><span class="com">// جهِّز بعض البيانات لتكتبها في الملف</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">string
</span><span class="kwd">const</span><span class="pln"> prepared_data </span><span class="pun">=</span><span class="pln"> prepare_data</span><span class="pun">();</span><span class="pln">

</span><span class="com">// اكتب البيانات إلى الملف</span><span class="pln">
output </span><span class="pun">&lt;&lt;</span><span class="pln"> prepared_data</span><span class="pun">;</span><span class="pln">

</span><span class="com">// أغلق الملف</span><span class="pln">
output</span><span class="pun">.</span><span class="pln">close</span><span class="pun">();</span><span class="pln">

</span><span class="com">// قد يستغرق تحضير البيانات وقتًا طويلًا</span><span class="pln">
</span><span class="com">// لذا لن نفتح مجرى خرج الملف حتى نكون جاهزين للكتابة فيه</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">string
</span><span class="kwd">const</span><span class="pln"> more_prepared_data </span><span class="pun">=</span><span class="pln"> prepare_complex_data</span><span class="pun">();</span><span class="pln">

</span><span class="com">// افتح الملف مرة أخرى بمجرد أن تكون جاهزًا للكتابة فيه</span><span class="pln">
output</span><span class="pun">.</span><span class="pln">open</span><span class="pun">(</span><span class="str">"foo.txt"</span><span class="pun">);</span><span class="pln">

</span><span class="com">// اكتب البيانات في الملف</span><span class="pln">
output </span><span class="pun">&lt;&lt;</span><span class="pln"> more_prepared_data</span><span class="pun">;</span><span class="pln">

</span><span class="com">// أغلق الملف مرة أخرى</span><span class="pln">
output</span><span class="pun">.</span><span class="pln">close</span><span class="pun">();</span></pre>

<h2>
	قراءة بُنية <code>struct</code> من ملف نصّي منسق
</h2>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong> انظر المثال التالي، سنحدد حملًا زائدًا للعامل <code>&lt;&lt;operator</code> على أنه دالة <code>friend</code> تمنح امتياز الوصول إلى البيانات الخاصة للأعضاء.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6545_76" style="">
<span class="kwd">struct</span><span class="pln"> info_type </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">string name</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> age</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">float</span><span class="pln"> height</span><span class="pun">;</span><span class="pln">

       </span><span class="kwd">friend</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">istream </span><span class="pun">&amp;</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">istream </span><span class="pun">&amp;</span><span class="pln"> is</span><span class="pun">,</span><span class="pln"> info_type </span><span class="pun">&amp;</span><span class="pln"> info</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// تجاوز المسافة البيضاء</span><span class="pln">
        is </span><span class="pun">&gt;&gt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">ws</span><span class="pun">;</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">getline</span><span class="pun">(</span><span class="pln">is</span><span class="pun">,</span><span class="pln"> info</span><span class="pun">.</span><span class="pln">name</span><span class="pun">);</span><span class="pln">
        is </span><span class="pun">&gt;&gt;</span><span class="pln"> info</span><span class="pun">.</span><span class="pln">age</span><span class="pun">;</span><span class="pln">
        is </span><span class="pun">&gt;&gt;</span><span class="pln"> info</span><span class="pun">.</span><span class="pln">height</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> is</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> func4</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> file </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">ifstream</span><span class="pun">(</span><span class="str">"file4.txt"</span><span class="pun">);</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> info_type </span><span class="pun">&gt;</span><span class="pln"> v</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">info_type info</span><span class="pun">;</span><span class="pln"> file </span><span class="pun">&gt;&gt;</span><span class="pln"> info</span><span class="pun">;)</span><span class="pln"> </span><span class="com">// اقرأ حتى النهاية</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// لن نصل إلى هنا إلا في حال نجاح عملية القراءة</span><span class="pln">
        v</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="pln">info</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> info</span><span class="pun">:</span><span class="pln"> v</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"  name: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> info</span><span class="pun">.</span><span class="pln">name </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"   age: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> info</span><span class="pun">.</span><span class="pln">age </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" years"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"height: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> info</span><span class="pun">.</span><span class="pln">height </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"lbs"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	ملف file4.txt
</h3>

<p>
	لنفرض أن البيانات التالية موجودة في ملفّ <code>file4.txt</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6545_78" style="">
<span class="typ">Wogger</span><span class="pln"> </span><span class="typ">Wabbit</span><span class="pln">
</span><span class="lit">2</span><span class="pln">
</span><span class="lit">6.2</span><span class="pln">
</span><span class="typ">Bilbo</span><span class="pln"> </span><span class="typ">Baggins</span><span class="pln">
</span><span class="lit">111</span><span class="pln">
</span><span class="lit">81.3</span><span class="pln">
</span><span class="typ">Mary</span><span class="pln"> </span><span class="typ">Poppins</span><span class="pln">
</span><span class="lit">29</span><span class="pln">
</span><span class="lit">154.8</span></pre>

<p>
	إذًا يكون الخرج ما يلي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6545_80" style="">
<span class="pln">name</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Wogger</span><span class="pln"> </span><span class="typ">Wabbit</span><span class="pln">
age</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> years
height</span><span class="pun">:</span><span class="pln"> </span><span class="lit">6.2lbs</span><span class="pln">
name</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Bilbo</span><span class="pln"> </span><span class="typ">Baggins</span><span class="pln">
age</span><span class="pun">:</span><span class="pln"> </span><span class="lit">111</span><span class="pln"> years
height</span><span class="pun">:</span><span class="pln"> </span><span class="lit">81.3lbs</span><span class="pln">
name</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Mary</span><span class="pln"> </span><span class="typ">Poppins</span><span class="pln">
age</span><span class="pun">:</span><span class="pln"> </span><span class="lit">29</span><span class="pln"> years
height</span><span class="pun">:</span><span class="pln"> </span><span class="lit">154.8lbs</span></pre>

<p>
	هذا الدرس جزء من <a data-ss1617022354="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة دروس عن C++‎</a>.
</p>

<p>
	ترجمة -بتصرّف- للفصل Chapter 12: File I/O‎ من كتاب <a data-ss1617022354="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">895</guid><pubDate>Wed, 17 Jun 2020 18:01:00 +0000</pubDate></item><item><title>&#x645;&#x62C;&#x627;&#x631;&#x64A; &#x627;&#x644;&#x62A;&#x62F;&#x641;&#x642; (Streams) &#x648;&#x645;&#x639;&#x627;&#x644;&#x650;&#x62C;&#x627;&#x62A;&#x647;&#x627; &#x641;&#x64A; Cpp</title><link>https://academy.hsoub.com/programming/cpp/%D9%85%D8%AC%D8%A7%D8%B1%D9%8A-%D8%A7%D9%84%D8%AA%D8%AF%D9%81%D9%82-streams-%D9%88%D9%85%D8%B9%D8%A7%D9%84%D9%90%D8%AC%D8%A7%D8%AA%D9%87%D8%A7-%D9%81%D9%8A-cpp-r894/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_06/10.png.693ddc4bc5158a566f40f86d9b07e9c4.png" /></p>

<h2>
	مجرى الدخل الخاص بالمستخدم ومجرى الخرج القياسي (user input and standard output)
</h2>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1600_7" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> value</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Enter a value: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cin </span><span class="pun">&gt;&gt;</span><span class="pln"> value</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"The square of entered value is: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> value </span><span class="pun">*</span><span class="pln"> value </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	مجاري التدفق النصية (String streams)
</h2>

<p>
	<code>std::ostringstream</code> هو صنف كائناته تبدو كمجرى خرْج (output stream)، أي يمكنك الكتابة فيه عبر العامل <code>‎operator&lt;&lt;‎</code>، ولكنّه في الواقع يخزّن نتائج الكتابة، ويُتيحها على هيئة مجرى.
</p>

<p>
	انظر هذا المثال:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1600_9" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;sstream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;string&gt;</span><span class="pln">

</span><span class="kwd">using</span><span class="pln"> </span><span class="kwd">namespace</span><span class="pln"> std</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    ostringstream ss</span><span class="pun">;</span><span class="pln">
    ss </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"the answer to everything is "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> string result </span><span class="pun">=</span><span class="pln"> ss</span><span class="pun">.</span><span class="pln">str</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ينشئ <code>;ostringstream ss</code> كائنًا مثل هذا الكائن، ويُعامل الكائن أولًا كمجرى عادي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1600_11" style="">
<span class="pln">ss </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"the answer to everything is "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span></pre>

<p>
	ثم يمكن الحصول على المجرى الناتج كما يلي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1600_13" style="">
<span class="kwd">const</span><span class="pln"> string result </span><span class="pun">=</span><span class="pln"> ss</span><span class="pun">.</span><span class="pln">str</span><span class="pun">();</span></pre>

<p>
	(السّلسلة النصّية <code>‎result‎</code> ستساوي <code>‎"the answer to everything is 42"‎</code>). ذلك مفيد في حال أردنا التمثيل النصّي لصنف سبق تعريف تسلسلِ مجراه (stream serialization). على سبيل المثال، لنفترض أنّ لدينا الصنف التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1600_15" style="">
<span class="kwd">class</span><span class="pln"> foo </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// التعليمات والأوامر البرمجية ستكون هنا.</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
ostream </span><span class="pun">&amp;</span><span class="kwd">operator</span><span class="pun">&lt;&lt;(</span><span class="pln">ostream </span><span class="pun">&amp;</span><span class="pln">os</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> foo </span><span class="pun">&amp;</span><span class="pln">f</span><span class="pun">);</span></pre>

<p>
	للحصول على التمثيل النصي للكائن <code>‎foo‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1600_17" style="">
<span class="pln">foo f</span><span class="pun">;</span></pre>

<p>
	يمكننا استخدام:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1600_19" style="">
<span class="pln">ostringstream ss</span><span class="pun">;</span><span class="pln">
ss </span><span class="pun">&lt;&lt;</span><span class="pln"> f</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> string result </span><span class="pun">=</span><span class="pln"> ss</span><span class="pun">.</span><span class="pln">str</span><span class="pun">();</span></pre>

<p>
	وعليه ستحتوي <code>‎result‎</code> التمثيل النصّي للكائن <code>‎foo‎</code>.
</p>

<h2>
	طباعة المجموعات باستخدام iostream
</h2>

<h3>
	الطباعة الأساسية (Basic printing)
</h3>

<p>
	تتيح <code>std::ostream_iterator</code> طباعة محتويات حاويات مكتبة القوالب القياسية STL في أيّ مَجرى خرج دون الحاجة إلى استخدام الحلقات، والوسيط الثاني المُمرَّر إلى مُنشِئ <code>‎std::ostream_iterator‎</code> يعين المحدِّد (delimiter). انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1600_21" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">1</span><span class="pun">,</span><span class="lit">2</span><span class="pun">,</span><span class="lit">3</span><span class="pun">,</span><span class="lit">4</span><span class="pun">};</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">copy</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">ostream_iterator</span><span class="str">&lt;int&gt;</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">cout</span><span class="pun">,</span><span class="pln"> </span><span class="str">" ! "</span><span class="pun">));</span></pre>

<p>
	سوف يطبع:
</p>

<pre class="ipsCode">
1 ! 2 ! 3 ! 4 !
</pre>

<h3>
	التحويل الضمني للأنواع (Implicit type cast)
</h3>

<p>
	تتيح <code>std::ostream_iterator</code>تحويل (casting) نوع محتوى الحاوية ضمنيًا. في المثال التالي، ستطبع <code>std::cout</code> أعدادًا عشريّة ذات ثلاث منازل عشرية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1600_23" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setprecision</span><span class="pun">(</span><span class="lit">3</span><span class="pun">);</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">fixed</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">cout</span><span class="pun">);</span></pre>

<p>
	وستستنسخ‏‏ <code>‎std::ostream_iterator‎</code> باستخدام النوع <code>‎float‎</code>، بينما ستظلّ القيم المُضمّنة قيمًا عددية صحيحة (<code>‎int‎</code>):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1600_30" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">1</span><span class="pun">,</span><span class="lit">2</span><span class="pun">,</span><span class="lit">3</span><span class="pun">,</span><span class="lit">4</span><span class="pun">};</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">copy</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">ostream_iterator</span><span class="str">&lt;float&gt;</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">cout</span><span class="pun">,</span><span class="pln"> </span><span class="str">" ! "</span><span class="pun">));</span></pre>

<p>
	تعيد الشّيفرة أعلاه النتيجة التالية على الرغم من أنّ المتجهة (<code>‎std::vector‎</code>) تحتوي أعدادًا صحيحة.
</p>

<pre class="ipsCode">
1.000 ! 2.000 ! 3.000 ! 4.000 !
</pre>

<h3>
	التوليد والتحويل
</h3>

<p>
	تشكّل دّوال <code>std::generate</code> و <code>std::generate_n</code> و <code>std::transform</code> أداة فعّالة لمعالجة البيانات، فمثلًا، انظر المتجهة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1600_28" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">1</span><span class="pun">,</span><span class="lit">2</span><span class="pun">,</span><span class="lit">3</span><span class="pun">,</span><span class="lit">4</span><span class="pun">,</span><span class="lit">8</span><span class="pun">,</span><span class="lit">16</span><span class="pun">};</span></pre>

<p>
	نستطيع باستخدامها أن نطبع القيمة البوليانية لتعليمة <code>x is even</code> للأعداد الزوجية بسهولة، كما يلي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1600_26" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">boolalpha</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">cout</span><span class="pun">);</span><span class="pln"> </span><span class="com">// طباعة القيم البوليانية أبجديًا</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">transform</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">ostream_iterator</span><span class="str">&lt;bool&gt;</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">cout</span><span class="pun">,</span><span class="pln"> </span><span class="str">" "</span><span class="pun">),</span><span class="pln">
    </span><span class="pun">[](</span><span class="typ">int</span><span class="pln"> val</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="pln">val </span><span class="pun">%</span><span class="pln"> </span><span class="lit">2</span><span class="pun">)</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">});</span></pre>

<p>
	أو طباعة مربعات العناصر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1600_32" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">transform</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">ostream_iterator</span><span class="str">&lt;int&gt;</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">cout</span><span class="pun">,</span><span class="pln"> </span><span class="str">" "</span><span class="pun">),</span><span class="pln">
    </span><span class="pun">[](</span><span class="typ">int</span><span class="pln"> val</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> val </span><span class="pun">*</span><span class="pln"> val</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">});</span></pre>

<p>
	أو طباعة N عدد عشوائي تفصلهم مسافة فارغة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1600_34" style="">
<span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> N </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">generate_n</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">ostream_iterator</span><span class="str">&lt;int&gt;</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">cout</span><span class="pun">,</span><span class="pln"> </span><span class="str">" "</span><span class="pun">),</span><span class="pln"> N</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">rand</span><span class="pun">);</span></pre>

<h3>
	المصفوفات
</h3>

<p>
	يمكن تطبيق جميع هذه الاعتبارات تقريبًا على <a data-ss1617022352="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-7-%D8%A7%D9%84%D9%85%D8%B5%D9%81%D9%88%D9%81%D8%A7%D8%AA-%D9%81%D9%8A-cpp-r891/" rel="">المصفوفات</a> الأصلية، تمامًا كما هو الحال في القسم الخاص بقراءة الملفات النصية. انظر المثال التالي حيث نطبع القيم التربيعيّة لعناصِر مصفوفة أصلية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1600_36" style="">
<span class="typ">int</span><span class="pln"> v</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">1</span><span class="pun">,</span><span class="lit">2</span><span class="pun">,</span><span class="lit">3</span><span class="pun">,</span><span class="lit">4</span><span class="pun">,</span><span class="lit">8</span><span class="pun">,</span><span class="lit">16</span><span class="pun">};</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">transform</span><span class="pun">(</span><span class="pln">v</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">end</span><span class="pun">(</span><span class="pln">v</span><span class="pun">),</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">ostream_iterator</span><span class="str">&lt;int&gt;</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">cout</span><span class="pun">,</span><span class="pln"> </span><span class="str">" "</span><span class="pun">),</span><span class="pln">
    </span><span class="pun">[](</span><span class="typ">int</span><span class="pln"> val</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> val </span><span class="pun">*</span><span class="pln"> val</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">});</span></pre>

<h2>
	معالِجات مجاري التدفق
</h2>

<p>
	معالِجات مجاري التدفق (Stream manipulators) هي دوال خاصّة مساعِدة للتحكّم في مجاري الدخل والخرج باستخدام العاملين <code>‎operator &gt;&gt;‎</code> و <code>‎operator&lt;&lt;‎</code>. ويمكن تضمينها عبر <code>‎#include &lt;iomanip&gt;‎</code>. تُبادِل <code>std::boolalpha</code> و <code>std::noboolalpha</code> بين التمثيل النصي والعددي للقيَم البوليانية. انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1600_38" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">boolalpha </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
</span><span class="com">// true الخرج</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">noboolalpha </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
</span><span class="com">// 0 الخرج</span><span class="pln">
</span><span class="kwd">bool</span><span class="pln"> boolValue</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cin </span><span class="pun">&gt;&gt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">boolalpha </span><span class="pun">&gt;&gt;</span><span class="pln"> boolValue</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Value \""</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">boolalpha </span><span class="pun">&lt;&lt;</span><span class="pln"> boolValue </span><span class="pun">&lt;&lt;</span><span class="pln">
    </span><span class="str">"\" was parsed as "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">noboolalpha </span><span class="pun">&lt;&lt;</span><span class="pln"> boolValue</span><span class="pun">;</span><span class="pln">
</span><span class="com">// true الدخل</span><span class="pln">
</span><span class="com">// تحليل قيمة الدخل على أنها 0</span></pre>

<ul>
<li>
		تحدد كل من <code>std::showbase</code> و <code>std::noshowbase</code> إن تم استخدام السابقة (Prefix) التي تشير إلى الأساس العادي.
	</li>
	<li>
		تُستخدم كل من <code>std::dec</code> (عشري) و <code>std::hex</code> (ست عشري) و <code>std::oct</code> (ثماني) من أجل تغيير الأساس العددي للأعداد الصحيحة.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1600_40" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;sstream&gt;</span><span class="pln">

std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">dec </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">29</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">' - '</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">hex </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">29</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">' - '</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">showbase </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">oct </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">29</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">' - '</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">noshowbase </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">29</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> number</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">istringstream</span><span class="pun">(</span><span class="str">"3B"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&gt;&gt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">hex </span><span class="pun">&gt;&gt;</span><span class="pln"> number</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">dec </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln">
</span><span class="com">// الخرج</span><span class="pln">
</span><span class="com">// 22 - 1D - 35 - 035</span><span class="pln">
</span><span class="com">// 59</span></pre>

<p>
	القيم الافتراضية هي <code>‎std::ios_base::noshowbase‎</code> و <code>‎std::ios_base::dec‎</code>. يمكنك معرفة المزيد حول <code>‎std::istringstream‎</code> من الترويسة <code><a data-ss1617022352="1" href="https://en.cppreference.com/w/cpp/header/sstream" rel="external nofollow">&lt;sstream&gt;</a></code>
</p>

<ul>
<li>
		تحدد كل من <code>std::uppercase</code> و <code>std::nouppercase</code> ما إذا كانت الأحرف الكبيرة ستُستخدم في خرْج الأعداد العشريّة والأعداد الست عشرية، وليس لها أيّ تأثير على مجاري الدخل.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1600_43" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">hex </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">showbase </span><span class="pun">&lt;&lt;</span><span class="pln">
    </span><span class="str">"0x2a with nouppercase: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">nouppercase </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">0x2a</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln">
    </span><span class="str">"1e-10 with uppercase: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">uppercase </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">1e-10</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="com">// الخرج:</span><span class="pln">
</span><span class="com">// 0x2a with nouppercase: 0x2a</span><span class="pln">
</span><span class="com">// 1e-10 with uppercase: 1E-10</span></pre>

<p>
	القيمة الافتراضيّة هي <code>std::nouppercase</code>.
</p>

<ul>
<li>
		تغيّر <code>std::setw(n)‎</code> - عرض (width) حقل الدخل/الخرج التالي إلى القيمة <code>‎n‎</code>، وتتم إعادة تعيين خاصية العرض <code>‎n‎</code> إلى <code>‎0‎</code> عند استدعاء بعض الدّوال (انظر <a data-ss1617022352="1" href="https://en.cppreference.com/w/cpp/io/manip/setw" rel="external nofollow">القائمة الكاملة</a>).
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1600_45" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"no setw:"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">51</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"setw(7): "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setw</span><span class="pun">(</span><span class="lit">7</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">51</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"setw(7), more output: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">13</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setw</span><span class="pun">(</span><span class="lit">7</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setfill</span><span class="pun">(</span><span class="str">'*'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">67</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">' '</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">94</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">char</span><span class="pun">*</span><span class="pln"> input </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Hello, world!"</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">char</span><span class="pln"> arr</span><span class="pun">[</span><span class="lit">10</span><span class="pun">];</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cin </span><span class="pun">&gt;&gt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setw</span><span class="pun">(</span><span class="lit">6</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&gt;&gt;</span><span class="pln"> arr</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Input from \"Hello, world!\" with setw(6) gave \""</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> arr </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\"\n"</span><span class="pun">;</span><span class="pln">

</span><span class="com">// الخرج:</span><span class="pln">
</span><span class="com">// 51</span><span class="pln">
</span><span class="com">// setw(7):      51</span><span class="pln">
</span><span class="com">// setw(7): more output: 13*****67 94</span><span class="pln">

</span><span class="com">// Hello, world! :الدخل</span><span class="pln">
</span><span class="com">// "Hello" تعيد  setw(6) حيث "Hello, world!" الخرج: الدخل من </span></pre>

<p>
	لاحظ أن الخرج في الشيفرة السابقة سيكون ("Input from "Hello, world!" with setw(6) gave "Hello). وتكون القيمة الافتراضية <code>std::setw(0)‎</code>.
</p>

<ul>
<li>
		تُعدِّل كل من <code>std::left</code> و <code>std::right</code> و <code>std::internal</code> الموضعَ الافتراضي لمحارف الملء (fill characters) من خلال ضبط <code>std::ios_base::adjustfield</code> إلى<code>std::ios_base::left</code>و <code>std::ios_base::right</code> و <code>std::ios_base::internal</code> على الترتيب. كذلك، تُطبَّق <code>std::left</code> و <code>std::right</code> على أيّ خرج، كما تُطبّق <code>std::internal</code> على الأعداد الصحيحة والعشرية والنقديّة، وليس لها أيّ تأثير على مجاري الدخل.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1600_47" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;locale&gt;</span><span class="pln">
</span><span class="pun">...</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">left </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">showbase </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setfill</span><span class="pun">(</span><span class="str">'*'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"flt: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setw</span><span class="pun">(</span><span class="lit">15</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">-</span><span class="lit">9.87</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"hex: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setw</span><span class="pun">(</span><span class="lit">15</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">41</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" $: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setw</span><span class="pun">(</span><span class="lit">15</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">put_money</span><span class="pun">(</span><span class="lit">367</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"usd: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setw</span><span class="pun">(</span><span class="lit">15</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">put_money</span><span class="pun">(</span><span class="lit">367</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"usd: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setw</span><span class="pun">(</span><span class="lit">15</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setfill</span><span class="pun">(</span><span class="str">' '</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">put_money</span><span class="pun">(</span><span class="lit">367</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="com">// :الخرج</span><span class="pln">
</span><span class="com">// flt: -9.87**********</span><span class="pln">
</span><span class="com">// hex: 41*************</span><span class="pln">
</span><span class="com">//   $: $3.67**********</span><span class="pln">
</span><span class="com">// usd: USD *3.67******</span><span class="pln">
</span><span class="com">// usd: $3.67</span><span class="pln">

std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">internal </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">showbase </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setfill</span><span class="pun">(</span><span class="str">'*'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"flt: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setw</span><span class="pun">(</span><span class="lit">15</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">-</span><span class="lit">9.87</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"hex: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setw</span><span class="pun">(</span><span class="lit">15</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">41</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" $: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setw</span><span class="pun">(</span><span class="lit">15</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">put_money</span><span class="pun">(</span><span class="lit">367</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"usd: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setw</span><span class="pun">(</span><span class="lit">15</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">put_money</span><span class="pun">(</span><span class="lit">367</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"usd: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setw</span><span class="pun">(</span><span class="lit">15</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setfill</span><span class="pun">(</span><span class="str">' '</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">put_money</span><span class="pun">(</span><span class="lit">367</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="com">// الخرج</span><span class="pln">
</span><span class="com">// flt: -**********9.87</span><span class="pln">
</span><span class="com">// hex: *************41</span><span class="pln">
</span><span class="com">//   $: $3.67**********</span><span class="pln">
</span><span class="com">// usd: USD *******3.67</span><span class="pln">
</span><span class="com">// usd: USD        3.67</span><span class="pln">

std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">right </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">showbase </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setfill</span><span class="pun">(</span><span class="str">'*'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"flt: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setw</span><span class="pun">(</span><span class="lit">15</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">-</span><span class="lit">9.87</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"hex: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setw</span><span class="pun">(</span><span class="lit">15</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">41</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" $: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setw</span><span class="pun">(</span><span class="lit">15</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">put_money</span><span class="pun">(</span><span class="lit">367</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"usd: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setw</span><span class="pun">(</span><span class="lit">15</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">put_money</span><span class="pun">(</span><span class="lit">367</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"usd: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setw</span><span class="pun">(</span><span class="lit">15</span><span class="pun">)</span><span class="pln">
     </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setfill</span><span class="pun">(</span><span class="str">' '</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">put_money</span><span class="pun">(</span><span class="lit">367</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="com">// الخرج</span><span class="pln">
</span><span class="com">// flt: **********-9.87</span><span class="pln">
</span><span class="com">// hex: *************41</span><span class="pln">
</span><span class="com">//   $: **********$3.67</span><span class="pln">
</span><span class="com">// usd: ******USD *3.67</span><span class="pln">
</span><span class="com">// usd:       USD  3.67</span></pre>

<p>
	القيمة الافتراضية هي <code>‎std::left‎</code>.
</p>

<ul>
<li>
		تغير كل من <a data-ss1617022352="1" href="http://en.cppreference.com/w/cpp/io/manip/fixed" rel="external nofollow"><code>std::fixed</code></a> و <a data-ss1617022352="1" href="http://en.cppreference.com/w/cpp/io/manip/fixed" rel="external nofollow"><code>std::scientific</code></a> و <a data-ss1617022352="1" href="http://en.cppreference.com/w/cpp/io/manip/fixed" rel="external nofollow"><code>std::hexfloat</code></a> ‏‏[C++11] و <a data-ss1617022352="1" href="http://en.cppreference.com/w/cpp/io/manip/fixed" rel="external nofollow"><code>std::defaultfloat</code></a> ‏‏[C++11] تنسيقَ الدخل والخرج للأعداد العشريّة.
	</li>
	<li>
		<code>std::fixed</code> تعيّن <a data-ss1617022352="1" href="http://en.cppreference.com/w/cpp/io/ios_base/fmtflags" rel="external nofollow"><code>std::ios_base::floatfield</code></a> إلى <a data-ss1617022352="1" href="http://en.cppreference.com/w/cpp/io/ios_base/fmtflags" rel="external nofollow"><code>std::ios_base::fixed</code></a>.
	</li>
	<li>
		تعيّن <code>std::scientific</code> إلى <a data-ss1617022352="1" href="http://en.cppreference.com/w/cpp/io/ios_base/fmtflags" rel="external nofollow"><code>std::ios_base::scientific</code></a>.
	</li>
	<li>
		تعيّن <code>std::hexfloat</code> إلى <code>‎‎std::ios_base::fixed | std::ios_base::scientific</code> وتعيّن <code>std::defaultfloat</code> إلى <code>std::ios_base::fmtflags(0)‎</code>.
	</li>
</ul>
<p>
	إليك الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1600_49" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;sstream&gt;</span><span class="pln">
</span><span class="pun">...</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln">
</span><span class="str">"The number 0.07 in fixed:      "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">fixed </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">0.01</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln">
</span><span class="str">"The number 0.07 in scientific: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">scientific </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">0.01</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln">
</span><span class="str">"The number 0.07 in hexfloat:   "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">hexfloat </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">0.01</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln">
</span><span class="str">"The number 0.07 in default:    "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">defaultfloat </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">0.01</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">double</span><span class="pln"> f</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">istringstream is</span><span class="pun">(</span><span class="str">"0x1P-1022"</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">double</span><span class="pln"> f </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">strtod</span><span class="pun">(</span><span class="pln">is</span><span class="pun">.</span><span class="pln">str</span><span class="pun">().</span><span class="pln">c_str</span><span class="pun">(),</span><span class="pln"> NULL</span><span class="pun">);</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Parsing 0x1P-1022 as hex gives "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> f </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">

</span><span class="com">// الخرج</span><span class="pln">
</span><span class="com">// 0.070000</span><span class="pln">
</span><span class="com">// 7.000000e-02</span><span class="pln">
</span><span class="com">// 0x1.1eb851eb851ecp-4</span><span class="pln">
</span><span class="com">// 0.07</span><span class="pln">
</span><span class="com">// 2.22507e-308</span></pre>

<p>
	القيمة الافتراضية هي <a data-ss1617022352="1" href="https://en.cppreference.com/w/cpp/io/ios_base/fmtflags" rel="external nofollow">‎ <code>‎‎std::ios_base::fmtflags(0)‎</code>‎</a>.
</p>

<p>
	هناك خلل في بعض المصرّفات يؤدي إلى النتيجة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1600_51" style="">
<span class="kwd">double</span><span class="pln"> f</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">istringstream</span><span class="pun">(</span><span class="str">"0x1P-1022"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&gt;&gt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">hexfloat </span><span class="pun">&gt;&gt;</span><span class="pln"> f</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Parsing 0x1P-1022 as hex gives "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> f </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="com">// الخرج:</span><span class="pln">
</span><span class="com">//  Parsing 0x1P-1022 as hex gives 0</span></pre>

<ul>
<li>
		تتحكم كل من <a data-ss1617022352="1" href="http://en.cppreference.com/w/cpp/io/manip/showpoint" rel="external nofollow"><code>std::showpoint</code></a> و <a data-ss1617022352="1" href="http://en.cppreference.com/w/cpp/io/manip/showpoint" rel="external nofollow"><code>std::noshowpoint</code></a> فيما إذا كانت الفاصلة العشرية ستُضمَّن دائمًا في تمثيل الفاصلة العائمة (ﬂoating-point representation)، وهما ليس لهما أي تأثير على مجاري الدخل.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1600_53" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"7.0 with showpoint: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">showpoint </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">7.0</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"7.0 with noshowpoint: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">noshowpoint </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">7.0</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span></pre>

<p>
	النّاتج سيكون:
</p>

<pre class="ipsCode">
1.0 with showpoint: 7.00000
1.0 with noshowpoint: 7
</pre>

<p>
	القيمة الافتراضية هي <code>std::showpoint</code>.
</p>

<ul>
<li>
		تتحكم كل من <a data-ss1617022352="1" href="http://en.cppreference.com/w/cpp/io/manip/showpos" rel="external nofollow"><code>std::showpos</code></a> و <a data-ss1617022352="1" href="http://en.cppreference.com/w/cpp/io/manip/showpos" rel="external nofollow"><code>std::noshowpos</code></a> فيما إذا كانت العلامة <code>‎+‎</code> ستُعرض في الخرج عند عرض الأعداد الموجبة، وهما كذلك ليس لهما أيّ تأثير على مجاري الدخل.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1600_55" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">cout     </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"With showpos: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">showpos
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">' '</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">-</span><span class="lit">2.718</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">' '</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">17</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Without showpos: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">noshowpos
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">' '</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">-</span><span class="lit">2.718</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">' '</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">17</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="com">// الخرج:</span><span class="pln">
</span><span class="com">// With showpos: +0 -2.718 +17</span><span class="pln">
</span><span class="com">// Without showpos: 0 -2.718 17</span></pre>

<p>
	القيمة الافتراضية <code>‎std::noshowpos‎</code>.
</p>

<ul>
<li>
		تتحكم كل من <a data-ss1617022352="1" href="http://en.cppreference.com/w/cpp/io/manip/unitbuf" rel="external nofollow"><code>std::unitbuf</code></a> و <a data-ss1617022352="1" href="http://en.cppreference.com/w/cpp/io/manip/unitbuf" rel="external nofollow"><code>std::nounitbuf</code></a> في تفريغ مجرى الخرج بعد كل عملية، وهما كذلك ليس لهما أي تأثير على مجاري الدخل. تنفّذ <code>‎std::unitbuf‎</code> عمليّة التفريغ.
	</li>
	<li>
		يحدّد <a data-ss1617022352="1" href="http://en.cppreference.com/w/cpp/io/manip/setbase" rel="external nofollow"><code>std::setbase(base)‎</code></a> الأساس العددي (numeric base) للمجرى.
	</li>
	<li>
		<code>std::setbase(8)‎</code> تكافئ تعيين <code>std::ios_base::basefield</code> إلى ‎<code>std::ios_base::oct</code>‎ وتعيين <code>std::setbase(16)‎</code> إلى <code>std::ios_base::hex</code> وتعيين <code>std::setbase(10)‎</code> إلى ‎<code>std::ios_base::dec</code>‎.
	</li>
</ul>
<p>
	إن كان الأساس العدديّ مخالفًا لـ 8 و10 و 16، فستُعيَّن <code>std::ios_base::basefield</code> إلى <code>std::ios_base::fmtflags(0)‎</code>، وذلك يعني أنّ الخرج سيكون عشريًا، أمّا الدخل فسيتعلّق بالأساس العددي (preﬁx-dependent).
</p>

<p>
	القيمة الافتراضيّة لـ <code>‎std::ios_base::basefield‎</code> هي <code>‎std::ios_base::dec‎</code>، لذلك، فافتراضيًا سيكون لدينا الأساس العشري <code>‎std::setbase(10)‎</code>
</p>

<ul>
<li>
		تغيّر <a data-ss1617022352="1" href="http://en.cppreference.com/w/cpp/io/manip/setprecision" rel="external nofollow"><code>std::setprecision(n)‎</code></a> دقةَ الأعداد العشرية.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1600_57" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;cmath&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;limits&gt;</span><span class="pln">
</span><span class="pun">...</span><span class="pln">
</span><span class="kwd">typedef</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">numeric_limits </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> ld</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> pi </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">acos</span><span class="pun">(-</span><span class="lit">1.</span><span class="pln"> L</span><span class="pun">);</span><span class="pln">

std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"default precision (6): pi: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> pi </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" 10pi: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">10</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> pi </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"std::setprecision(4): 10pi: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setprecision</span><span class="pun">(</span><span class="lit">4</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">10</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> pi </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" 10000pi: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">10000</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> pi </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"std::fixed: 10000pi: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">fixed </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">10000</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> pi </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">defaultfloat </span><span class="pun">&lt;&lt;</span><span class="pln">
</span><span class="str">'\n'</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"std::setprecision(10): pi: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setprecision</span><span class="pun">(</span><span class="lit">10</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> pi </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"max-1 radix precicion: pi: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setprecision</span><span class="pun">(</span><span class="pln">ld</span><span class="pun">::</span><span class="pln">digits </span><span class="pun">-</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> pi </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"max+1 radix precision: pi: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setprecision</span><span class="pun">(</span><span class="pln">ld</span><span class="pun">::</span><span class="pln">digits </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> pi </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"significant digits prec: pi: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setprecision</span><span class="pun">(</span><span class="pln">ld</span><span class="pun">::</span><span class="pln">digits10</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> pi </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="com">// الخرج</span><span class="pln">
</span><span class="com">// pi: 3.14159</span><span class="pln">
</span><span class="com">// 10pi: 31.4159</span><span class="pln">
</span><span class="com">// 10pi: 31.42</span><span class="pln">
</span><span class="com">// 10000pi: 3.142e+04</span><span class="pln">
</span><span class="com">// std::fixed:         10000pi: 31415.9265</span><span class="pln">
</span><span class="com">// std::setprecision(10):   pi: 3.141592654</span><span class="pln">
</span><span class="com">// max-1 radix precicion:   pi: 3.14159265358979323851280895940618620443274267017841339111328125</span><span class="pln">
</span><span class="com">// max+1 radix precision:   pi: 3.14159265358979323851280895940618620443274267017841339111328125</span><span class="pln">
</span><span class="com">// pi: 3.14159265358979324</span></pre>

<p>
	القيمة الافتراضية هي <code>‎std::setprecision(6)‎</code>.
</p>

<ul>
<li>
		تعين كل من <a data-ss1617022352="1" href="http://en.cppreference.com/w/cpp/io/manip/setiosflags" rel="external nofollow"><code>std::setiosflags(mask)‎</code></a> و <a data-ss1617022352="1" href="http://en.cppreference.com/w/cpp/io/manip/resetiosflags" rel="external nofollow"><code>std::resetiosflags(mask)‎</code></a> - الرايات (ﬂags) المحدّدة في العنصر <code>‎mask‎</code> ذي النّوع <code>std::ios_base::fmtflags</code>، وتمسحها كذلك.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1600_59" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;sstream&gt;</span><span class="pln">
</span><span class="pun">...</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">istringstream in</span><span class="pun">(</span><span class="str">"10 010 10 010 10 010"</span><span class="pun">);</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> num1</span><span class="pun">,</span><span class="pln"> num2</span><span class="pun">;</span><span class="pln">

in </span><span class="pun">&gt;&gt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">oct </span><span class="pun">&gt;&gt;</span><span class="pln"> num1 </span><span class="pun">&gt;&gt;</span><span class="pln"> num2</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Parsing \"10 010\" with std::oct gives: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> num1 </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">' '</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> num2 </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">

</span><span class="com">// الخرج:</span><span class="pln">
</span><span class="com">// Parsing "10 010" with std::oct gives: 8 8</span><span class="pln">

in </span><span class="pun">&gt;&gt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">dec </span><span class="pun">&gt;&gt;</span><span class="pln"> num1 </span><span class="pun">&gt;&gt;</span><span class="pln"> num2</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Parsing \"10 010\" with std::dec gives:   "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> num1 </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">' '</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> num2 </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="com">// الخرج:</span><span class="pln">
</span><span class="com">// Parsing "10 010" with std::oct gives: 10 10</span><span class="pln">

in </span><span class="pun">&gt;&gt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">resetiosflags</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">ios_base</span><span class="pun">::</span><span class="pln">basefield</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&gt;&gt;</span><span class="pln"> num1 </span><span class="pun">&gt;&gt;</span><span class="pln"> num2</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Parsing \"10 010\" with autodetect gives: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> num1 </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">' '</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> num2 </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="com">// الخرج:</span><span class="pln">
</span><span class="com">// Parsing "10 010" with std::oct gives: 10 8</span><span class="pln">

std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setiosflags</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">ios_base</span><span class="pun">::</span><span class="pln">hex </span><span class="pun">|</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">ios_base</span><span class="pun">::</span><span class="pln">uppercase </span><span class="pun">|</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">ios_base</span><span class="pun">::</span><span class="pln">showbase</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">42</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="com">// الخرج: OX2A</span></pre>

<ul>
<li>
		تحدد كل من <a data-ss1617022352="1" href="http://en.cppreference.com/w/cpp/io/manip/skipws" rel="external nofollow"><code>std::skipws</code></a> و <a data-ss1617022352="1" href="http://en.cppreference.com/w/cpp/io/manip/skipws" rel="external nofollow"><code>std::noskipws</code></a> ما إذا كانت دوال الدّخل المُنسّق (formatted input functions) ستتجاوز المسافة البادئة الفارغة. وليس لهما أي تأثير على مجاري الخرج.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1600_61" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;sstream&gt;</span><span class="pln">
</span><span class="pun">...</span><span class="pln">
</span><span class="kwd">char</span><span class="pln"> c1</span><span class="pun">,</span><span class="pln"> c2</span><span class="pun">,</span><span class="pln"> c3</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">istringstream</span><span class="pun">(</span><span class="str">"a b c"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&gt;&gt;</span><span class="pln"> c1 </span><span class="pun">&gt;&gt;</span><span class="pln"> c2 </span><span class="pun">&gt;&gt;</span><span class="pln"> c3</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Default behavior: c1 = "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> c1 </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" c2 = "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> c2 </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" c3 = "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> c3 </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">istringstream</span><span class="pun">(</span><span class="str">"a b c"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&gt;&gt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">noskipws </span><span class="pun">&gt;&gt;</span><span class="pln"> c1 </span><span class="pun">&gt;&gt;</span><span class="pln"> c2 </span><span class="pun">&gt;&gt;</span><span class="pln"> c3</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"noskipws behavior: c1 = "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> c1 </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" c2 = "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> c2 </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" c3 = "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> c3 </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="com">//  الخرج:</span><span class="pln">
</span><span class="com">// Default behaviour: c1 = a  c2 = b  c3 = c</span><span class="pln">
</span><span class="com">// noskipws behavior: c1 = a  c2 =    c3 = b</span></pre>

<p>
	القيمة الافتراضية هي <a data-ss1617022352="1" href="http://en.cppreference.com/w/cpp/io/ios_base/fmtflags" rel="external nofollow"><code>‎std::ios_base::skipws‎</code></a>.
</p>

<ul>
<li>
		<a data-ss1617022352="1" href="http://en.cppreference.com/w/cpp/io/manip/quoted" rel="external nofollow"><code>std::quoted(s[, delim[, escape]])</code></a>‎‏ [C++14] تدرج أو تستخرج السّلاسل النصية المُقتبسة (quoted) ذات المسافات الفارغة المُدمجة.
	</li>
	<li>
		<code>s</code> - السّلسلة النصية المرادُ إدراجها أو استخلاصها.
	</li>
	<li>
		<code>delim</code> - المحرف المراد استخدامه كمحدّد (delimiter)، القيمة الافتراضية هي <code>"</code>.
	</li>
	<li>
		<code>escape</code> - المحرف المستخدم كحرف تهريب (escape character) ، القيمة الافتراضيّة هي <code>\</code>.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1600_63" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;sstream&gt;</span><span class="pln">
</span><span class="pun">...</span><span class="pln">

std</span><span class="pun">::</span><span class="pln">stringstream ss</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">string in </span><span class="pun">=</span><span class="pln"> </span><span class="str">"String with spaces, and embedded \"quotes\" too"</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">string out</span><span class="pun">;</span><span class="pln">

ss </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">quoted</span><span class="pun">(</span><span class="pln"> in </span><span class="pun">);</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout    </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"read in     ["</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> in </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"]\n"</span><span class="pln"> 
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"stored as   ["</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> ss</span><span class="pun">.</span><span class="pln">str</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"]\n"</span><span class="pun">;</span><span class="pln">

ss </span><span class="pun">&gt;&gt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">quoted</span><span class="pun">(</span><span class="pln">out</span><span class="pun">);</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"written out ["</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> out </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"]\n"</span><span class="pun">;</span><span class="pln">
</span><span class="com">// الخرج</span><span class="pln">
</span><span class="com">//    [String with spaces, and embedded "quotes" too] تُقرأ كـ</span><span class="pln">
</span><span class="com">//   ["String with spaces, and embedded \"quotes\" too"] تُخزّن كـ</span><span class="pln">
</span><span class="com">//  [String with spaces, and embedded "quotes" too] تُكتب كـ</span></pre>

<h2>
	معالِجات مجاري الخرج
</h2>

<ul>
<li>
		<code>std::ends</code> - تُدرج محرفًا فارغًا '‎\0' في مجرى الخرْج. تبدو الصيغة الرسمية لهذا المعالِج كالتالي:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1600_65" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> charT</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> traits</span><span class="pun">&gt;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">basic_ostream</span><span class="pun">&lt;</span><span class="pln">charT</span><span class="pun">,</span><span class="pln"> traits</span><span class="pun">&gt;&amp;</span><span class="pln"> ends</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">basic_ostream</span><span class="pun">&lt;</span><span class="pln">charT</span><span class="pun">,</span><span class="pln"> traits</span><span class="pun">&gt;&amp;</span><span class="pln"> os</span><span class="pun">);</span></pre>

<p>
	هذا المعالِجُ يُدرج المحرفَ الفارغَ عبر استدعاء <code>‎os.put(charT())‎</code> عند استخدامه في تعبير <code>‎os &lt;&lt; std::ends;‎</code>
</p>

<ul>
<li>
		يفرِّغ كلا من <a data-ss1617022352="1" href="http://en.cppreference.com/w/cpp/io/manip/endl" rel="external nofollow"><code>std::endl</code></a> و <a data-ss1617022352="1" href="http://en.cppreference.com/w/cpp/io/manip/flush" rel="external nofollow"><code>std::flush</code></a> مجرى الإخراج <code>‎out‎</code> عن طريق استدعاء <code>out.flush()‎</code>، ممّا يؤدّي إلى عرض الخرج على الفور. لكنّ <code>‎std::endl‎</code> تدرج رمز نهاية السّطر <code>‎'\n'‎</code> قبل التفريغ. انظر:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1600_67" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">cout    </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"First line."</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Second line. "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">flush
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Still second line."</span><span class="pun">;</span></pre>

<p>
	الناتج:
</p>

<pre class="ipsCode">
First line.
Second line. Still second line.
</pre>

<ul>
<li>
		<code><a data-ss1617022352="1" href="http://(http://en.cppreference.com/w/cpp/io/manip/setfill" rel="external nofollow">std::setfill(c)‎</a></code> - تغيّر محرف الملء (ﬁll character) إلى <code>‎c‎</code>، تُستخدم غالبًا مع <code>std::setw</code>.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1600_71" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">cout    </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\nDefault fill: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setw</span><span class="pun">(</span><span class="lit">10</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">79</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"setfill('#'): "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setfill</span><span class="pun">(</span><span class="str">'#'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">setw</span><span class="pun">(</span><span class="lit">10</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">42</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="com">// الخرج:</span><span class="pln">
</span><span class="com">// Default fill:         79</span><span class="pln">
</span><span class="com">// setfill('#'): ########79</span></pre>

<ul>
<li>
		<a data-ss1617022352="1" href="http://en.cppreference.com/w/cpp/io/manip/put_money" rel="external nofollow"><code>std::put_money(mon[, intl])‎</code></a>‏‏ [C++11] - تُحوِّل القيمة النقدية <code>‎mon‎</code> (من النوع <code>‎long double‎</code> أو <code>‎std::basic_string‎</code> ) في التعبير <code>‎out &lt;&lt; std::put_money(mon, intl)‎</code> إلى تمثيلها المحرفيّ كما هو محدد في <a data-ss1617022352="1" href="http://en.cppreference.com/w/cpp/locale/money_put" rel="external nofollow"><code>std::money_put</code></a> في الإعدادات المحلّية الخاصّة بالعملة الموجودة في <code>‎out‎</code>. استخدم سلاسل العملات الدولية إذا كانت <code>‎intl‎</code> تساوي <code>true</code> وإلا فاستخدم رموز العملات.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1600_73" style="">
<span class="kwd">long</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> money </span><span class="pun">=</span><span class="pln"> </span><span class="lit">123.45</span><span class="pun">;</span><span class="pln">
</span><span class="com">// std::string money = "123.45"; :أو</span><span class="pln">

std</span><span class="pun">::</span><span class="pln">cout</span><span class="pun">.</span><span class="pln">imbue</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">locale</span><span class="pun">(</span><span class="str">"en_US.utf8"</span><span class="pun">));</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout    </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">showbase </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"en_US: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">put_money</span><span class="pun">(</span><span class="pln">money</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" or "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">put_money</span><span class="pun">(</span><span class="pln">money</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="com">// en_US: $1.23 or USD  1.23 :الخرج</span><span class="pln">

std</span><span class="pun">::</span><span class="pln">cout</span><span class="pun">.</span><span class="pln">imbue</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">locale</span><span class="pun">(</span><span class="str">"ru_RU.utf8"</span><span class="pun">));</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout    </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"ru_RU: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">put_money</span><span class="pun">(</span><span class="pln">money</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" or "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">put_money</span><span class="pun">(</span><span class="pln">money</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="com">// ru_RU: 1.23 руб or 1.23 RUB :الخرج</span><span class="pln">

std</span><span class="pun">::</span><span class="pln">cout</span><span class="pun">.</span><span class="pln">imbue</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">locale</span><span class="pun">(</span><span class="str">"ja_JP.utf8"</span><span class="pun">));</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout    </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"ja_JP: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">put_money</span><span class="pun">(</span><span class="pln">money</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" or "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">put_money</span><span class="pun">(</span><span class="pln">money</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="com">// ja_JP: ￥123 or JPY  123 :الخرج</span></pre>

<ul>
<li>
		<a data-ss1617022352="1" href="http://en.cppreference.com/w/cpp/io/manip/put_time" rel="external nofollow"><code>std::put_time(tmb, fmt)‎</code></a>‏‏ [C++11] - تُنسّق وتُخرِج قيمة تقويم تاريخ/وقت إلى <code>std::tm</code> بحسب تنسيق <code>fmt</code>.
	</li>
	<li>
		<code>tmb</code> - مؤشّر إلى بنية التقويم (calendar time structure)‏‏ <code>const std::tm*‎</code> كما أعادته <code>localtime()‎</code> أو <code>gmtime()‎</code>.
	</li>
	<li>
		<code>fmt</code> - مؤشّر إلى سلسلة نصّية منتهية بقيمة فارغة <code>const CharT*‎</code> تمثّل تنسيق التحويل.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1600_75" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;ctime&gt;</span><span class="pln">
</span><span class="pun">...</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">time_t</span><span class="pln"> t </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">time</span><span class="pun">(</span><span class="kwd">nullptr</span><span class="pun">);</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">tm tm </span><span class="pun">=</span><span class="pln"> </span><span class="pun">*</span><span class="pln">std</span><span class="pun">::</span><span class="pln">localtime</span><span class="pun">(&amp;</span><span class="pln">t</span><span class="pun">);</span><span class="pln">

std</span><span class="pun">::</span><span class="pln">cout</span><span class="pun">.</span><span class="pln">imbue</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">locale</span><span class="pun">(</span><span class="str">"ru_RU.utf8"</span><span class="pun">));</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\nru_RU: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">put_time</span><span class="pun">(&amp;</span><span class="pln">tm</span><span class="pun">,</span><span class="pln"> </span><span class="str">"%c %Z"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="com">// الخرج الممكن</span><span class="pln">
</span><span class="com">// ru_RU: Вт 04 июл 2017 15:08:35 UTC</span></pre>

<h2>
	معالِجات مجاري الدخل (Input stream manipulators)
</h2>

<ul>
<li>
		تستهلك <a data-ss1617022352="1" href="http://en.cppreference.com/w/cpp/io/manip/ws" rel="external nofollow"><code>std::ws</code></a> المسافات البادئة في مجرى الدخل، وهي مختلفة عن <code>std::skipws</code>.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1600_77" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;sstream&gt;</span><span class="pln">
</span><span class="pun">...</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">string str</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">istringstream</span><span class="pun">(</span><span class="str">"  \v\n\r\t    Wow!There   is no whitespaces!"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&gt;&gt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">ws </span><span class="pun">&gt;&gt;</span><span class="pln"> str</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> str</span><span class="pun">;</span><span class="pln">

</span><span class="com">// الخرج</span><span class="pln">
</span><span class="com">// Wow!There   is no whitespaces!</span></pre>

<ul>
<li>
		<a data-ss1617022352="1" href="http://en.cppreference.com/w/cpp/io/manip/get_money" rel="external nofollow"><code>std::get_money(mon[, intl])</code></a>‎‏ [C++11] - في تعبير <code>in &gt;&gt; std::get_money(mon, intl)‎</code>، تحلّل دخل المحارف كقيمة نقديّة كما هو محدّد بواسطة <a data-ss1617022352="1" href="http://en.cppreference.com/w/cpp/locale/money_get" rel="external nofollow"><code>std::money_get</code></a> في الإعدادات المحلية في <code>in</code>، وتخزّن القيمة في <code>mon</code> (من نوع <code>long double</code> أو <code>std::basic_string</code>). سيتوقّع المعالِج سلاسل العملات الدوليّة المطلوبة إذا كانت <code>intl</code> تساوي <code>true</code>، وإلا فسَيتوقع رموز عملات اختيارية.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1600_79" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;sstream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;locale&gt;</span><span class="pln">
</span><span class="pun">...</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">istringstream in</span><span class="pun">(</span><span class="str">"$1,234.56 2.22 USD 3.33"</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">long</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> v1</span><span class="pun">,</span><span class="pln"> v2</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">string v3</span><span class="pun">;</span><span class="pln">

in</span><span class="pun">.</span><span class="pln">imbue</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">locale</span><span class="pun">(</span><span class="str">"en_US.UTF-8"</span><span class="pun">));</span><span class="pln">
in </span><span class="pun">&gt;&gt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">get_money</span><span class="pun">(</span><span class="pln">v1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&gt;&gt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">get_money</span><span class="pun">(</span><span class="pln">v2</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&gt;&gt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">get_money</span><span class="pun">(</span><span class="pln">v3</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">if</span><span class="pln">    </span><span class="pun">(</span><span class="pln">in</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout    </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">quoted</span><span class="pun">(</span><span class="pln">in</span><span class="pun">.</span><span class="pln">str</span><span class="pun">())</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" parsed as: "</span><span class="pln">
</span><span class="pun">&lt;&lt;</span><span class="pln"> v1 </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> v2 </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> v3 </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="com">// الخرج</span><span class="pln">
</span><span class="com">// "$1,234.56 2.22 USD  3.33" parsed as: 123456, 222, 333</span></pre>

<ul>
<li>
		تحلّل <a data-ss1617022352="1" href="http://en.cppreference.com/w/cpp/io/manip/get_time" rel="external nofollow"><code>std::get_time(tmb, fmt)‎</code></a> ‏‏[C++11] قيمة التاريخ/الوقت المُخزّنة في <code>‎tmb‎</code> بتنسيق <code>‎fmt‎</code> المحدد.
	</li>
	<li>
		<code>‎tmb‎</code> - مؤشّر صالح للكائن <code>const std::tm*‎</code> حيث ستُخزَّن النتيجة.
	</li>
	<li>
		<code>‎fmt‎</code> - مؤشّر إلى سلسلة نصيّة منتهية بقيمة فارغة <code>const CharT*‎</code> تمثّل تنسيق التحويل.
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1600_81" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;sstream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;locale&gt;</span><span class="pln">
</span><span class="pun">...</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">tm t </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{};</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">istringstream ss</span><span class="pun">(</span><span class="str">"2011-Februar-18 23:12:34"</span><span class="pun">);</span><span class="pln">
ss</span><span class="pun">.</span><span class="pln">imbue</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">locale</span><span class="pun">(</span><span class="str">"de_DE.utf-8"</span><span class="pun">));</span><span class="pln">
ss </span><span class="pun">&gt;&gt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">get_time</span><span class="pun">(&amp;</span><span class="pln">t</span><span class="pun">,</span><span class="pln"> </span><span class="str">"%Y-%b-%d %H:%M:%S"</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">ss</span><span class="pun">.</span><span class="pln">fail</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Parse failed\n"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">put_time</span><span class="pun">(&amp;</span><span class="pln">t</span><span class="pun">,</span><span class="pln"> </span><span class="str">"%c"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="com">// الخرج</span><span class="pln">
</span><span class="com">// Sun Feb 18 23:12:34 2011</span></pre>

<p>
	هذا الدرس جزء من <a data-ss1617022352="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة مقالات عن C++‎</a>.
</p>

<p>
	ترجمة -بتصرّف- للفصل Chapter 13: C++ Streams والفصل Chapter 14: Stream manipulators من كتاب <a data-ss1617022352="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">894</guid><pubDate>Sun, 14 Jun 2020 18:01:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x62D;&#x644;&#x642;&#x627;&#x62A; &#x627;&#x644;&#x62A;&#x643;&#x631;&#x627;&#x631;&#x64A;&#x629; Loops &#x641;&#x64A; Cpp</title><link>https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AD%D9%84%D9%82%D8%A7%D8%AA-%D8%A7%D9%84%D8%AA%D9%83%D8%B1%D8%A7%D8%B1%D9%8A%D8%A9-loops-%D9%81%D9%8A-cpp-r893/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_06/9.png.9c946bf63ae7aed7b0693e87e0dfde0d.png" /></p>

<p>
	تنفذ الحلقات التكرارية مجموعة من التعليمات إلى حين استيفاء شرط معين، وهناك ثلاثة أنواع من تلك الحلقات التكرارية في لغة C++: <code>for</code> و <code>while</code> و <code>do…while</code>.
</p>

<h2>
	حلقة <code>for</code> النطاقية (Range-Based For)
</h2>

<p>
	<strong>الإصدار ≥ C++‎ 11</strong>
</p>

<p>
	يمكن استخدام حلقات <code>for</code> للتكرار على عناصر نطاق تكراري (iterator-based range) دون الحاجة إلى استخدام الفهارس العددية أو الوصول بشكل مباشر إلى المكررات:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3307_7" style="">
<span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">float</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> v </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="lit">0.4</span><span class="pln"> f</span><span class="pun">,</span><span class="pln">
    </span><span class="lit">12.5</span><span class="pln"> f</span><span class="pun">,</span><span class="pln">
    </span><span class="lit">16.234</span><span class="pln"> f
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln"> val</span><span class="pun">:</span><span class="pln"> v</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> val </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" "</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></pre>

<p>
	ستكرّر الشيفرة السابقة تعليمة <code>std::cout &lt;&lt; val &lt;&lt; " ";‎</code> على كل عناصر <code>v</code>، وستحصل <code>val</code> على قيمة العنصر الحالي. الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3307_9" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">for</span><span class="pun">-</span><span class="pln">range</span><span class="pun">-</span><span class="pln">declaration </span><span class="pun">:</span><span class="pln"> </span><span class="kwd">for</span><span class="pun">-</span><span class="pln">range</span><span class="pun">-</span><span class="pln">initializer </span><span class="pun">)</span><span class="pln"> statement</span></pre>

<p>
	ستكون مكافئة لما يلي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3307_19" style="">
<span class="pun">{</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pun">&amp;&amp;</span><span class="pln"> __range </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">for</span><span class="pun">-</span><span class="pln">range</span><span class="pun">-</span><span class="pln">initializer</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> __begin </span><span class="pun">=</span><span class="pln"> begin</span><span class="pun">-</span><span class="pln">expr</span><span class="pun">,</span><span class="pln"> __end </span><span class="pun">=</span><span class="pln"> end</span><span class="pun">-</span><span class="pln">expr</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(;</span><span class="pln"> __begin </span><span class="pun">!=</span><span class="pln"> __end</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">__begin</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">for</span><span class="pun">-</span><span class="pln">range</span><span class="pun">-</span><span class="pln">declaration </span><span class="pun">=</span><span class="pln"> </span><span class="pun">*</span><span class="pln">__begin</span><span class="pun">;</span><span class="pln">
statement
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<strong>الإصدار ≥ C++‎ 17</strong>
</p>

<p>
	من الممكن أن تكون <code>end</code> من نوع مختلف عن <code>begin</code> في C++17، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3307_13" style="">
<span class="pun">{</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pun">&amp;&amp;</span><span class="pln"> __range </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">for</span><span class="pun">-</span><span class="pln">range</span><span class="pun">-</span><span class="pln">initializer</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> __begin </span><span class="pun">=</span><span class="pln"> begin</span><span class="pun">-</span><span class="pln">expr</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> __end </span><span class="pun">=</span><span class="pln"> end</span><span class="pun">-</span><span class="pln">expr</span><span class="pun">;</span><span class="pln">  
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(;</span><span class="pln"> __begin </span><span class="pun">!=</span><span class="pln"> __end</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">__begin</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">for</span><span class="pun">-</span><span class="pln">range</span><span class="pun">-</span><span class="pln">declaration </span><span class="pun">=</span><span class="pln"> </span><span class="pun">*</span><span class="pln">__begin</span><span class="pun">;</span><span class="pln"> 
        statement
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	قُدِّم هذا التغيير في C++‎ لأجل التمهيد لدعم معيار النطاقات Ranges TS في الإصدار C++‎ 20، وعليه فإن الحلقة في هذه الحالة ستكون مكافئة لما يلي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3307_15" style="">
<span class="pun">{</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln">__range </span><span class="pun">=</span><span class="pln"> v</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> __begin </span><span class="pun">=</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> __end </span><span class="pun">=</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">();</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(;</span><span class="pln"> __begin </span><span class="pun">!=</span><span class="pln"> __end</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">__begin</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">auto</span><span class="pln"> val </span><span class="pun">=</span><span class="pln"> </span><span class="pun">*</span><span class="pln">__begin</span><span class="pun">;</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> val </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" "</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لاحظ أن التعليمة <code>auto val</code> تصرح عن نوع القيمة التي ستكون نسخة من القيمة المخزنة داخل النطاق – سنهيئه استنساخًا أثناء تنفيذ البرنامج-، وإن كانت عملية نسخ القيم المخزنة في النطاق مكلفة فربما تود استخدام <code>const auto &amp;val</code>.
</p>

<p>
	كذلك لست مضطرًا لاستخدام <code>auto</code> ، بل تستطيع استخدام أي اسم نوع <code>typename</code> طالما أنه قابل للتحويل من نوع قيمة النطاق. واعلم أن حلقة <code>for</code> النطاقية غير مناسبة في حال احتجت للوصول إلى المُكرّر، أو ستحتاج مجهودًا كبيرًا.
</p>

<p>
	إن أردت الإشارة للمكرِّر، فيمكنك ذلك بما يلي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3307_23" style="">
<span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">float</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">v </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">0.4f</span><span class="pun">,</span><span class="pln"> </span><span class="lit">12.5f</span><span class="pun">,</span><span class="pln"> </span><span class="lit">16.234f</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">for</span><span class="pun">(</span><span class="typ">float</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">val</span><span class="pun">:</span><span class="pln"> v</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> val </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" "</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	كذلك يمكنك التكرار على مرجع <code>const</code> إذا كان لديك حاوية <code>const</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3307_25" style="">
<span class="kwd">const</span><span class="pln"> </span><span class="typ">vector</span><span class="str">&lt;float&gt;</span><span class="pln"> v </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">0.4f</span><span class="pun">,</span><span class="pln"> </span><span class="lit">12.5f</span><span class="pun">,</span><span class="pln"> </span><span class="lit">16.234f</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">for</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">float</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">val</span><span class="pun">:</span><span class="pln"> v</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
 std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> val </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" "</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكنك استخدام مراجع إعادة التوجيه (forwarding references) في حال أعاد مُكرّر التسلسل كائنًا وكيلًا (proxy object) وكنت بحاجة إلى إجراء عمليات يمكن أن تغيّر قيمة الكائن. لكن بالمقابل، من المحتمل أن تربك من يقرأ شيفرتك إن استخدمت هذه الطريقة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3307_27" style="">
<span class="typ">vector</span><span class="str">&lt;bool&gt;</span><span class="pln"> v</span><span class="pun">(</span><span class="lit">10</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln">val </span><span class="pun">:</span><span class="pln"> v</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    val </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكن أن يكون نوع "النطاق" المقدم إلى حلقة <code>for</code> النطاقية أحد الخيارات التالية:
</p>

<ul>
<li>
		المصفوفات:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3307_30" style="">
<span class="typ">float</span><span class="pln"> arr</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">0.4f</span><span class="pun">,</span><span class="pln"> </span><span class="lit">12.5f</span><span class="pun">,</span><span class="pln"> </span><span class="lit">16.234f</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln"> val </span><span class="pun">:</span><span class="pln"> arr</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> val </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" "</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لاحظ أنّ تخصيص المصفوفات الديناميكية لا يُحسب:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3307_34" style="">
<span class="typ">float</span><span class="pln"> </span><span class="pun">*</span><span class="pln">arr </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">float</span><span class="pun">[</span><span class="lit">3</span><span class="pun">]{</span><span class="lit">0.4f</span><span class="pun">,</span><span class="pln"> </span><span class="lit">12.5f</span><span class="pun">,</span><span class="pln"> </span><span class="lit">16.234f</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln"> val </span><span class="pun">:</span><span class="pln"> arr</span><span class="pun">)</span><span class="pln"> </span><span class="com">// خطأ تصريفي</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> val </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" "</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<ul>
<li>
		أي نوع يحتوي على دوال <code>begin()‎</code> و <code>end()‎</code> تابعةٍ، يعيدُ مكرّرات إلى عناصر من ذلك النوع، ويمكنك استخدام حاويات المكتبات القياسية إضافة إلى استخدام الأنواع التي يحددها المستخدم (User-Defined)، انظر:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3307_36" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Rng</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">float</span><span class="pln"> arr</span><span class="pun">[</span><span class="lit">3</span><span class="pun">];</span><span class="pln">
    </span><span class="com">// المؤشرات ما هي إلا مكرّرات</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">float</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> begin</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">arr</span><span class="pun">[</span><span class="lit">0</span><span class="pun">];</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">float</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> end</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">arr</span><span class="pun">[</span><span class="lit">3</span><span class="pun">];</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="typ">float</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> begin</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">arr</span><span class="pun">[</span><span class="lit">0</span><span class="pun">];</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="typ">float</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> end</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">arr</span><span class="pun">[</span><span class="lit">3</span><span class="pun">];</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Rng</span><span class="pln"> rng </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="lit">0.4f</span><span class="pun">,</span><span class="pln"> </span><span class="lit">12.5f</span><span class="pun">,</span><span class="pln"> </span><span class="lit">16.234f</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln"> val</span><span class="pun">:</span><span class="pln"> rng</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> val </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" "</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<ul>
<li>
		أيّ نوع لديه دوال <code>begin(type)‎</code> و <code>end(type)‎</code> غير تابعة (non-member)، يمكن إيجاده من خلال البحث بالوسائط (Arguments) استنادًا للنوع <code>type</code>، هذا مفيد في إنشاء نوع نطاقٍ (range type) دون الحاجة إلى تعديل نوع الصنف نفسه، انظر:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3307_38" style="">
<span class="kwd">namespace</span><span class="pln"> </span><span class="typ">Mine</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">Rng</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">float</span><span class="pln"> arr</span><span class="pun">[</span><span class="lit">3</span><span class="pun">];</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
    </span><span class="com">// المؤشرات ما هي إلا مكررات</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">float</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> begin</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Rng</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> rng</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">rng</span><span class="pun">.</span><span class="pln">arr</span><span class="pun">[</span><span class="lit">0</span><span class="pun">];</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> </span><span class="typ">float</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> end</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">Rng</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> rng</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">rng</span><span class="pun">.</span><span class="pln">arr</span><span class="pun">[</span><span class="lit">3</span><span class="pun">];</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="typ">float</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> begin</span><span class="pun">(</span><span class="typ">Rng</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> rng</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">rng</span><span class="pun">.</span><span class="pln">arr</span><span class="pun">[</span><span class="lit">0</span><span class="pun">];</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="typ">float</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> end</span><span class="pun">(</span><span class="typ">Rng</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> rng</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">rng</span><span class="pun">.</span><span class="pln">arr</span><span class="pun">[</span><span class="lit">3</span><span class="pun">];</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">Mine</span><span class="pun">::</span><span class="typ">Rng</span><span class="pln"> rng </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
            </span><span class="lit">0.4f</span><span class="pun">,</span><span class="pln"> </span><span class="lit">12.5f</span><span class="pun">,</span><span class="pln"> </span><span class="lit">16.234f</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln"> val</span><span class="pun">:</span><span class="pln"> rng</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> val </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" "</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	حلقة <code>for</code> التكرارية
</h2>

<p>
	تنفّذ الحلقة <code>for</code> التعليمات الموجودة في متن الحلقة <code>loop body</code> ما دامَ شَرط الحلقة <code>condition</code> صحيحًا، وتُنفَّذ <code>initialization statement</code> مرة واحدة قبل تنفيذ الحلقة التكرارية، ثم تُنفّذ التعليمة <code>iteration execution</code> بعد كل تكرار.
</p>

<p>
	تٌعرَّف حلقة <code>for</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3307_40" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="com">/*initialization statement*/</span><span class="pun">;</span><span class="pln"> </span><span class="com">/*condition*/</span><span class="pun">;</span><span class="pln"> </span><span class="com">/*iteration execution*/</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// متن الحلقة</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	شرح الصيغة السابقة:
</p>

<ul>
<li>
		تُنفَّذ تعليمة <code>initialization statement</code> مرة واحدة فقط في بداية حلقة <code>for</code>، وتستطيع هنا أن تصرِّح عن عدة متغيرات من نفس النوع، مثل <code>int i = 0, a = 2, b = 3</code>. لا تكون تلك المتغيرات صالحة إلا في نطاق الحلقة، وأما المتغيرات التي لها نفس الاسم وعُرِّفّت قبل تنفيذ الحلقة فإنها تُخفى أثناء تنفيذ الحلقة.
	</li>
	<li>
		تُقيَّم تعليمة <code>condition</code> قبل كل مرة يُنفَّذ فيها متن الحلقة (loop body) كي تُوقف الحلقة إن أعادت القيمة <code>false</code>.
	</li>
	<li>
		تُنفَّذ تعليمة <code>iteration execution</code> بعد تنفيذ متن الحلقة وقبل تقييم الشرط التالي إلا إن أُوقِفت حلقة <code>for</code> في المتن بواسطة <code>break</code> أو <code>goto</code> أو <code>return</code>، أو في حالة رفع اعتراض (throwing an exception). تستطيع وضع عدة تعليمات في الجزء <code>iteration execution</code> مثل <code>a++, b+=10, c=b+a</code>.
	</li>
</ul>
<p>
	تكافئ الشيفرةُ التالية حلقةَ <code>for</code> في حال كتابتها كحلقة <code>while</code>، حيث تنتقل الحلقة إلى جزء تنفيذ التكرار <code>/*iteration execution*/</code> عند استخدام <code>continue</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3307_42" style="">
<span class="com">/*initialization*/</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln"> </span><span class="com">/*condition*/</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> 
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// متن الحلقة </span><span class="pln">
    </span><span class="com">/*iteration execution*/</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	غالبًا ما تُستخدم الحلقة <code>for</code> لتنفيذ تعليمات برمجية معيّنة عددًا محدّدًا من المرات. على سبيل المثال:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3307_44" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> i </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	أو:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3307_46" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pun">,</span><span class="pln"> c </span><span class="pun">=</span><span class="pln"> </span><span class="lit">20</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">(</span><span class="pln">a </span><span class="pun">+</span><span class="pln"> b </span><span class="pun">+</span><span class="pln"> c </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">100</span><span class="pun">);</span><span class="pln"> c</span><span class="pun">--,</span><span class="pln"> b</span><span class="pun">++,</span><span class="pln"> a </span><span class="pun">+=</span><span class="pln"> c</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> a </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> b </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> c </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	هذا مثال يوضّح إخفاء المتغيرات المُصرّح عنها قبل الحلقة، حيث نصرح في السطر الثاني عن المتغير <code>i</code> الذي ستتغير قيمته بين 0 و 9 أثناء تنفيذ الحلقة، ثم نستطيع يعود إلى قيمته الأصلية <code>99</code> بعد انتهاء تنفيذها.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3307_48" style="">
<span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">99</span><span class="pun">;</span><span class="pln"> </span><span class="com">//i = 99</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">    </span><span class="com">// i التصريح عن متغير جديد</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ولكن إن كنت تريد استخدام المتغيرات المُصرّحة سلفًا وعدم إخفائها، فاحذف التصريح. انظر المثال التالي إذ نستخدم متغير <code>i</code> المصرَّح عنه من قبل، والذي تتغير قيمته بين 0 و 9 أثناء تنفيذ الحلقة، لكن هذه المرة ستكون قيمته بعد تنفيذها <code>10</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3307_50" style="">
<span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">99</span><span class="pun">;</span><span class="pln"> </span><span class="com">//i = 99</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="com">// i سنستخدم المتغير المُعرّف مسبقا</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<strong>ملاحظات</strong>:
</p>

<ul>
<li>
		يمكن لتعليمات التهيئة (initialization) والزيادة (increment) إجراء عمليات لا تتعلق بتعليمة شرط الحلقة، بل قد تكون فارغة تمامًا إن شئت ذلك، لكن من الأفضل أن نجري عمليات لها علاقة مباشرة بالحلقة لجعل الشيفرة أسهل في القراءة والفهم.
	</li>
	<li>
		لا يُرى المتغير الذي صُرِّح عنه في تعليمة التهيئة إلا داخل نطاق حلقة <code>for</code>، ويُحذف بمجرد إنهائها.
	</li>
	<li>
		لا تنس أنّ المتغير الذي تم التصريح عنها في <code>initialization statement</code> يمكن أثناء الحلقة، وكذلك المتغير المُحدّد في الشرط <code>condition</code>.
	</li>
</ul>
<p>
	انظر المثال التالي لحلقة تَعُدُّ من 0 إلى 10:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3307_52" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> counter </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> counter </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">counter</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> counter </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="com">// counter لا يمكن الوصول هنا إلى</span></pre>

<p>
	شرح الشيفرة السابقة:
</p>

<ul>
<li>
		التعليمة <code>int counter = 0</code> تهيّئ المتغير <code>counter</code> عند القيمة 0. لا يمكن استخدام هذا المتغير إلا داخل حلقة <code>for</code>.
	</li>
	<li>
		التعليمة <code>‎</code>counter &lt;= 10 هي شرط بولياني يتحقق ممّا إذا كان <code>counter</code> أصغر من أو يساوي 10. إذا كان الشرط صحيحًا (true) فستُنفّذ الحلقة. وإن كان <code>false</code> فستُنهى.
	</li>
	<li>
		<code>counter++</code>‎ هي عملية زيادة (increment) تزيد قيمة العدَّاد بـ 1 قبل التحقق من الشرط التالي.
	</li>
</ul>
<p>
	إن تركت جميع التعليمات فارغة، فستحصل على حلقة لا نهائية (inﬁnite loop):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3307_54" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(;;)</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Never ending!\n"</span><span class="pun">;</span></pre>

<p>
	حلقة <code>while</code> اللانهائية التي تكافئ حلقة <code>for</code> السابقة هي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3307_56" style="">
<span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">true</span><span class="pun">)</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Never ending!\n"</span><span class="pun">;</span></pre>

<p>
	لكن على أي حال، يمكن إيقاف الحلقات اللانهائية باستخدام تعليمات <code>break</code> أو <code>goto</code> أو <code>return</code>، أو عبر رفع اعتراض (throwing an exception).
</p>

<p>
	انظر المثال التالي الذي يوضح التكرار على عناصر مجموعة من المكتبة القياسية STL (مثل <code>vector</code>) دون استخدام الترويسة <algorithm>: </algorithm></p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3307_58" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&gt;</span><span class="pln"> names </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="str">"Albert Einstein"</span><span class="pun">,</span><span class="pln">
    </span><span class="str">"Stephen Hawking"</span><span class="pun">,</span><span class="pln">
    </span><span class="str">"Michael Ellis"</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">string </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">::</span><span class="typ">iterator</span><span class="pln"> it </span><span class="pun">=</span><span class="pln"> names</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">();</span><span class="pln"> it </span><span class="pun">!=</span><span class="pln"> names</span><span class="pun">.</span><span class="pln">end</span><span class="pun">();</span><span class="pln"> </span><span class="pun">++</span><span class="pln">it</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> it </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	حلقة While
</h2>

<p>
	تكرِّر حلقة <code>while</code> تنفيذ تعليمات معيّنة طالما كان شرطها صحيحًا، تُستخدم هذه الحلقة إن لم تكن تعرف عدد مرات تنفيذ جزء من الشيفرة بشكل مسبق. فمثلأ، لطباعة جميع الأعداد من 0 إلى 9، يمكن استخدام الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3307_60" style="">
<span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">10</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> i </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" "</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">++</span><span class="pln">i</span><span class="pun">;</span><span class="pln"> </span><span class="com">// عداد الزيادة</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></pre>

<p>
	تُطبع الأعداد من 0 إلى 9 مع نهاية السطر الأخير. لاحظ أن دمج التعليمتيْن الأوليين صار ممكنًا منذ الإصدار C++ 17، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3307_63" style="">
<span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">10</span><span class="pun">)</span><span class="pln">
</span><span class="com">//... بقية الشيفرة هي نفسها</span></pre>

<p>
	يمكن استخدام الشيفرة التالية لإنشاء حلقة لا نهائية، وتستطيع إيقاف الحلقة عبر تعليمة <code>break</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3307_65" style="">
<span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">true</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// أدخل هنا أي شيء تريد فعله بلا نهاية</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	هناك صورة آخرى لحلقات <code>while</code>، وهي <code>do...while</code>. وهي موضوع الفقرة التالية.
</p>

<h2>
	حلقة <code>do-while</code>
</h2>

<p>
	الحلقتان التكراريتان <code>do-while</code> و <code>while</code> متشابهتان، إلا أن الأولى تتحقق من الشرط في نهاية كل تكرار، وليس في بدايته، وعليه فإنّ الحلقة ستُنفّذ مرة واحدة على الأقل. ستطبع الشيفرة التالية العدد <code>0</code> إذ سيكون تقييمُ الشرط <code>false</code> في نهاية التكرار الأول:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3307_67" style="">
<span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">do</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">++</span><span class="pln">i</span><span class="pun">;</span><span class="pln"> </span><span class="com">// عداد الزيادة</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">);</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln"> </span><span class="com">// يطبع صفرًا </span></pre>

<p>
	<strong>تنبيه</strong>: لا تنس الفاصلة المنقوطة في نهاية <code>while(condition);‎</code>، فهي إلزامية في بنية <code>do-while</code>. على النقيض من الحلقة <code>do-while</code>، فإن الشيفرة التالية لن تطبع شيئًا لأنّ شرط الحلقة لم يتحقق في بداية التكرار الأول:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3307_69" style="">
<span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">++</span><span class="pln">i</span><span class="pun">;</span><span class="pln"> </span><span class="com">// عداد الزيادة</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln"> </span><span class="com">// لن يُطبع أيّ شيء</span></pre>

<p>
	<strong>تنبيه</strong>: يمكن إنهاء الحلقة <code>while</code> حتى لو لم يصبح الشرط خاطئًا باستخدام أي من التعليمات الآتية: <code>break</code> أو <code>goto</code> أو <code>return</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3307_71" style="">
<span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">do</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">++</span><span class="pln">i</span><span class="pun">;</span><span class="pln"> </span><span class="com">// عداد الزيادة</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">i </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">5</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">true</span><span class="pun">);</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln"> </span><span class="com">// يطبع الأعداد من صفر إلى خمسة</span></pre>

<p>
	تُستخدم الحلقة <code>do-while</code> أحيانًا لكتابة وحدات الماكرو (macros) التي تتطلّب نطاقًا خاصًّا بها (في هذه الحالة، يتمّ حذف الفاصلة المنقوطة الزائدة من تعريف الماكرو، ويُطلب من المستخدم توفيرها):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3307_73" style="">
<span class="com">#define</span><span class="pln"> BAD_MACRO</span><span class="pun">(</span><span class="pln">x</span><span class="pun">)</span><span class="pln"> f1</span><span class="pun">(</span><span class="pln">x</span><span class="pun">);</span><span class="pln"> f2</span><span class="pun">(</span><span class="pln">x</span><span class="pun">);</span><span class="pln"> f3</span><span class="pun">(</span><span class="pln">x</span><span class="pun">);</span><span class="pln">

</span><span class="com">// f1 الشرط لا يحمي هنا إلا استدعاء</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">cond</span><span class="pun">)</span><span class="pln"> BAD_MACRO</span><span class="pun">(</span><span class="pln">var</span><span class="pun">);</span><span class="pln">

</span><span class="com">#define</span><span class="pln"> GOOD_MACRO</span><span class="pun">(</span><span class="pln">x</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">do</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> f1</span><span class="pun">(</span><span class="pln">x</span><span class="pun">);</span><span class="pln"> f2</span><span class="pun">(</span><span class="pln">x</span><span class="pun">);</span><span class="pln"> f3</span><span class="pun">(</span><span class="pln">x</span><span class="pun">);</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">while</span><span class="pun">(</span><span class="lit">0</span><span class="pun">)</span><span class="pln">

</span><span class="com">// كل الاستدعاءات محميّة هنا</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">cond</span><span class="pun">)</span><span class="pln"> GOOD_MACRO</span><span class="pun">(</span><span class="pln">var</span><span class="pun">);</span></pre>

<h2>
	تعليمات التحكم في الحلقات: <code>break</code> و <code>continue</code>
</h2>

<p>
	تُستخدم عبارتَا التحكم <code>break</code> و <code>continue</code> لتغيير مسار التنفيذ من تسلسله المعتاد، فتُدمَّر جميع الكائنات الآلية (automatic objects) التي أنشئت داخل نطاق ما بمجرد ترك تنفيذٍ لذلك النطاق. وتنهي التعليمة <code>break</code> الحلقة فورًا دون النظر لأي عوامل أخرى.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3307_75" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">i </span><span class="pun">==</span><span class="pln"> </span><span class="lit">4</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">break</span><span class="pun">;</span><span class="pln"> </span><span class="com">// إنهاء الحلقة فورا</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> i </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تكون النتيجة ما يلي:
</p>

<pre class="ipsCode">
1
2
3
</pre>

<p>
	أما التّعليمة <code>continue</code> لا توقف الحلقة على الفور، بل تتخطّى بقيّة التعليمات الموجودة في متن الحلقة وتذهب إلى بداية الحلقة (بما في ذلك تعليمة التحقّق من الشّرط). انظر المثال التالي حيث تقيَّم <code>(if (i % 2 == 0</code> إلى <code>true</code> إن كان العدد زوجيًا، وتذهب <code>continue</code> فورًا إلى بداية الحلقة، لكن لا يُنتَقَل إلى التعليمة التالية إن لم تُنفَّذ.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3307_77" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">6</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">i </span><span class="pun">%</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">continue</span><span class="pun">;</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> i </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" is an odd number\n"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تكون النتيجة ما يلي:
</p>

<pre class="ipsCode">
1 is an odd number
3 is an odd number
5 is an odd number
</pre>

<p>
	لا تُستخدم <code>break</code> و <code>continue</code> إلا نادرًا، ذلك أنه يصعب معهما قراءة الشيفرة وفهمها، وتُستخدم أساليب أخرى أبسط بدلًا منهما.فمثلًا يمكن إعادة كتابة الحلقة <code>for</code> الأولى التي تستخدم <code>break</code> على النّحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3307_79" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">4</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> i </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	وبالمثل، يمكن إعادة كتابة المثال الثّاني الذي يحتوي <code>continue</code> كالتالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3307_81" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">6</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">i </span><span class="pun">%</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">!=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> i </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" is an odd number\n"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	التصريح عن المتغيرات في العبارات الشَّرطية
</h2>

<p>
	يسمح بالتصريح عن كائن في شرط حلقات <code>for</code> أو <code>while</code>، وسيُدرَج ذلك الكائن في النّطاق حتى نهاية الحلقة، وسيكون متاحًا خلال كل تكرارات الحلقة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3307_83" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    do_something</span><span class="pun">(</span><span class="pln">i</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="com">// لم يعد في النطاق i</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pun">&amp;</span><span class="pln"> a </span><span class="pun">:</span><span class="pln"> some_container</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    a</span><span class="pun">.</span><span class="pln">do_something</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="com">// لم يعد في النطاق a</span><span class="pln">
</span><span class="kwd">while</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">shared_ptr</span><span class="pun">&lt;</span><span class="typ">Object</span><span class="pun">&gt;</span><span class="pln"> p </span><span class="pun">=</span><span class="pln"> get_object</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    p</span><span class="pun">-&gt;</span><span class="pln"> do_something</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="com">// لم يعد في النطاق p</span></pre>

<p>
	لا يمكنك فعل الشيء نفسه مع حلقة <code>do...while</code>؛ إذ عليك التصريح عن المتغير قبل الحلقة، ثمّ وضع المتغير والحلقة داخل نطاق محلّي (local scope) إن أردت أن يُحذَف المتغير بعد انتهاء الحلقة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3307_85" style="">
<span class="com">// هذه الشّيفرة لن تُصرّف</span><span class="pln">
</span><span class="kwd">do</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    s </span><span class="pun">=</span><span class="pln"> do_something</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">short</span><span class="pln"> s </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">);</span><span class="pln">
</span><span class="com">// جيّد</span><span class="pln">
</span><span class="kwd">short</span><span class="pln"> s</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">do</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    s </span><span class="pun">=</span><span class="pln"> do_something</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">s </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">);</span></pre>

<p>
	وذلك لأنّ متن الحلقة <code>do...while</code> يقيَّم قبل الوصول إلى الجزء (<code>while</code>)، وعليه فإن التصاريح الموضوعة في ذلك الجزء لن تكون مرئيّة أثناء التّكرار الأول للحلقة.
</p>

<h2>
	تكرار حلقة <code>for</code> على نطاق فرعي
</h2>

<p>
	تستطيع التكرار على جزء فرعي من حاوية أو نطاق ما باستخدام الحلقات النطاقية (range-base loops)، وذلك من خلال إنشاء كائن وكيل (proxy object).
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3307_87" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Iterator</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Sentinel</span><span class="pun">=</span><span class="typ">Iterator</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> </span><span class="typ">range_t</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Iterator</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
        </span><span class="typ">Sentinel</span><span class="pln"> e</span><span class="pun">;</span><span class="pln">
        </span><span class="typ">Iterator</span><span class="pln"> begin</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="typ">Sentinel</span><span class="pln"> end</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> e</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="kwd">bool</span><span class="pln"> empty</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> begin</span><span class="pun">()</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> end</span><span class="pun">();</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="typ">range_t</span><span class="pln"> without_front</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> count </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
           </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_same</span><span class="pun">&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">random_access_iterator_tag</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">iterator_traits</span><span class="pun">&lt;</span><span class="typ">Iterator</span><span class="pun">&gt;::</span><span class="pln">iterator_category </span><span class="pun">&gt;{}</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                count </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">min</span><span class="pun">)(</span><span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">distance</span><span class="pun">(</span><span class="pln">b</span><span class="pun">,</span><span class="pln"> e</span><span class="pun">)),</span><span class="pln"> count</span><span class="pun">);</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                std</span><span class="pun">::</span><span class="pln">next</span><span class="pun">(</span><span class="pln">b</span><span class="pun">,</span><span class="pln"> count</span><span class="pun">),</span><span class="pln">
                e
            </span><span class="pun">};</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="typ">range_t</span><span class="pln"> without_back</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pln"> count </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">is_same</span><span class="pun">&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">random_access_iterator_tag</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">iterator_traits</span><span class="pun">&lt;</span><span class="typ">Iterator</span><span class="pun">&gt;::</span><span class="pln">iterator_category </span><span class="pun">&gt;{}</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                count </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">min</span><span class="pun">)(</span><span class="pln">std</span><span class="pun">::</span><span class="typ">size_t</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">distance</span><span class="pun">(</span><span class="pln">b</span><span class="pun">,</span><span class="pln"> e</span><span class="pun">)),</span><span class="pln"> count</span><span class="pun">);</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                b</span><span class="pun">,</span><span class="pln">
                std</span><span class="pun">::</span><span class="pln">prev</span><span class="pun">(</span><span class="pln">e</span><span class="pun">,</span><span class="pln"> count</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">};</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Iterator</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Sentinel</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="typ">range_t</span><span class="pun">&lt;</span><span class="typ">Iterator</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Sentinel</span><span class="pun">&gt;</span><span class="pln"> range</span><span class="pun">(</span><span class="pln"> </span><span class="typ">Iterator</span><span class="pln"> b</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Sentinal</span><span class="pln"> e </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            b</span><span class="pun">,</span><span class="pln">
            e
        </span><span class="pun">};</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Iterable</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> range</span><span class="pun">(</span><span class="typ">Iterable</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> r</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">using</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">begin</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">using</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">end</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> range</span><span class="pun">(</span><span class="pln">begin</span><span class="pun">(</span><span class="pln">r</span><span class="pun">),</span><span class="pln"> end</span><span class="pun">(</span><span class="pln">r</span><span class="pun">));</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> C </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">auto</span><span class="pln"> except_first</span><span class="pun">(</span><span class="pln">C </span><span class="pun">&amp;</span><span class="pln"> c</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">auto</span><span class="pln"> r </span><span class="pun">=</span><span class="pln"> range</span><span class="pun">(</span><span class="pln">c</span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">r</span><span class="pun">.</span><span class="pln">empty</span><span class="pun">())</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> r</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> r</span><span class="pun">.</span><span class="pln">without_front</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span></pre>

<p>
	نستطيع الآن فعل ما يلي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3307_89" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> v </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">};</span><span class="pln">

</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln"> i</span><span class="pun">:</span><span class="pln"> except_first</span><span class="pun">(</span><span class="pln">v</span><span class="pun">))</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> i </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span></pre>

<p>
	يكون الناتج:
</p>

<pre class="ipsCode">
2
3
4
</pre>

<p>
	يجب أن تتذكّر أنّ الكائنات الوسيطة (intermediate objects) المُنشأة في الجزء <code>for(:range_expression)‎</code> من حلقة <code>for</code> ستُحذف عند بدء تنفيذ الحلقة.
</p>

<p>
	هذ الدرس جزء من <a data-ss1617022349="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة دروس عن C++‎</a>.
</p>

<p>
	ترجمة -بتصرّف- للفصل Chapter 11: Loops‎ من الكتاب <a data-ss1617022349="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">893</guid><pubDate>Fri, 12 Jun 2020 18:02:00 +0000</pubDate></item></channel></rss>
