سی‌پلاس‌پلاس/سی‌ال‌آی (به انگلیسی: C++/CLI) که همان سی‌پلاس‌پلاسِ تغییریافته برای زیرساخت زبان مشترک است، یک تصریح زبان ساخته‌شده توسط مایکروسافت است که جایگزینی برای ام‌سی‌پلاس‌پلاس است. این زبان یک بازنویسی کامل جهت ساده‌سازی نحو (Syntax) ام‌سی‌پلاس‌پلاس، که امروزه منسوخ شده‌است، می‌باشد و قابلیت همکاری با زبان‌های دات‌نت مایکروسافت همانند سی‌شارپ را دارد. این زبان توسط اکما (Ecma) استانداردسازی شده‌است و هم‌اکنون در تمامی نسخه‌های ویژوال استودیو از سال ۲۰۰۵ تا ۲۰۲۲، حتی در نسخه‌های فشرده، موجود است.

تغییرات نحوی
------------

سی‌پلاس‌پلاس/سی‌ال‌آی باید به خودی خود یک زبان در نظر گرفته شود (با، برای مثال، یک سری کلمات کلیدی جدید) و جایگزینی برای ام‌سی‌پلاس‌پلاس؛ (که کلمات کلیدی غیراستانداردش به شکل `gc__` یا `value__` بودند) به همین دلیل، تغییرات نحوی عمده‌ای در آن به‌خصوص در زمینه‌ی حذف کردن شمارنده‌های دارای ابهام و اضافه کردن قابلیت‌های دات‌نتی، وجود دارد. بسیاری از جمله‌های دارای تناقض با یکدیگر، مانند اشکال مختلف عملگر `()new` در ام‌سی‌پلاس‌پلاس، از هم متمایز شده‌اند. در سی‌پلاس‌پلاس/سی‌ال‌آی اشیای دات‌نتی با کلمهٔ کلیدی جدید `gcnew` (که در واقع ()garbage collected new است)، ساخته می‌شوند. همین‌طور مفاهیم عام‌ها (Generics) نیز از دات‌نت معرفی شده‌اند (به‌طور کلی، بسیار مشابه الگوهای سی‌پلاس‌پلاس استاندارد ولی با پیاده‌سازی متفاوت).

#### هندل‌ها (Handles)

در ام‌سی‌پلاس‌پلاس دو نوع اشاره‌گر وجود داشت: اشاره‌گرهای `nogc__` که اشاره‌گرهای معمولی سی‌پلاس‌پلاس بودند و `gc__` که مخصوص ارجاع‌های دات‌نتی بودند. در حالی که در این زبان اشاره‌گر تنها همان اشاره‌گر معمولی سی‌پلاس‌پلاس است و ارجاع‌های دات‌نتی از طریق مفهوم جدید «هندل»، با استفاده از `^ClassName` (به جای `*ClassName`) قابل انجام هستند. این ساختار به ویژه زمانی مفید است که در کد سی‌پلاس‌پلاس و ام‌سی‌پلاس‌پلاس با هم ترکیب شده باشند؛ زیرا مشخص می‌شود کدام اشیا تحت بازیافت حافظهٔ خودکار دات‌نت از بین خواهند رفت و کدامشان باید توسط خود برنامه‌نویس از بین بروند.

##### ارجاع ردیاب (Tracking Reference)

یک ارجاع ردیاب در این زبان، یک هندل برای یک متغیر پاس داده شده با ارجاع است. مفهوم آن مانند استفاده از `&*` در زبان سی‌پلاس‌پلاس (ارجاع به یک اشاره‌گر) و معادل کلمهٔ کلیدی `ref` در سی‌شارپ یا `ByRef` در ویژوال بیسیک دات‌نت است. این زبان از `%^` برای نشان دادن یک ارجاع ردیاب استفاده می‌کند.

کد پایین یک نمونه از کاربرد ارجاع ردیاب است. جایگزینی ارجاع ردیاب با یک هندل متغیر هندل معمولی باعث مقدار ندادن به ۱۰ هندل رشته‌ای (String) در آرایهٔ نهایی رشته‌ها می‌شود؛ زیرا تنها کپی‌هایی از هندل‌های رشته‌ای در آرایه جاگذاری خواهند شد از آنجایی که با مقدار پاس داده شده‌اند و نه با آدرس:

```
int main()
{
 array<String^> ^arr = gcnew array<String^>(10);
 int i = 0;

 for each(String^% s in arr) {
 s = i++.ToString();
 }

 return 0;
}

```
دقت کنید که این عمل در سی‌شارپ مجاز نیست؛ زیرا در آنجا پاس دادن با مقدار به وسیله حلقهٔ `foreach` میسر نیست.

#### پایان‌دهنده‌ها (Finalizers) و متغیرهای خودکار

یک تغییر دیگر در سی‌پلاس‌پلاس/سی‌ال‌آی معرفی پایان‌دهنده‌ها تحت `()ClassName!` است. این‌ها یک نوع تخریبگر (Destructor)های تصمیم‌ناپذیر هستند که طی روند بازیافت حافظه اجرا می‌شوند. `()ClassName~` که تخریبگر سی‌پلاس‌پلاس است نیز برای اشیای تحت کنترل موجود و نمایندهٔ بهتری برای روندهای لغوی تخریب‌سازی تصمیم‌پذیر سی‌پلاس‌پلاس «سنتی» (خوانده شدن توسط کد کاربر با کلمهٔ کلیدی `delete`) است.

از نقطه نظر دات‌نت خام، روش تخریب‌سازی تصمیم‌ناپذیر، تابع `Finalize` حفاظت‌شده را برای کلاس `Object` ریشه بازنویسی می‌کند، در حالی که روش تصمیم‌پذیر به وسیلهٔ تابع `foreach` از واسط `IDisposable` پیاده‌سازی می‌شود (که کامپایلر سی‌پلاس‌پلاس/سی‌ال‌آی تخریبگر را به آن تبدیل می‌کند).

اشیایی از کد سی‌شارپ یا ویژوال بیسیک دات‌نت که تابع را بازنویسی می‌کنند، می‌توانند به‌طور دستی به وسیله `delete` دور انداخته شوند؛ درست مثل کلاس‌های دات‌نتی در سی‌پلاس‌پلاس/سی‌ال‌آی.

```
// C++/CLI
ref class MyClass
{
public:
 MyClass(); // constructor
 ~MyClass(); // (deterministic) destructor (implemented as IDisposable.Dispose())
protected:
 !MyClass(); // finalizer (non-deterministic destructor) (implemented as Finalize())

public:
 static void Test()
 {
 MyClass automatic; // Not a handle, no initialization: compiler calls constructor here

 MyClass ^user = gcnew MyClass();
 delete user;

 // Compiler calls automatic's destructor when automatic goes out of scope
 }
};

```

سرریزی بار عملگرها (Operator Overloading)
-----------------------------------------

این عمل در این زبان مانند سی‌پلاس‌پلاس استاندارد انجام می‌شود. هر \* تبدیل به ^ و هر & تبدیل به % می‌شود اما بقیه آن به جز یک مورد مهم بدون تغییر می‌ماند: برای کلاس‌های دات‌نت، سرریزی بار عملگرها نه تنها برای خود کلاس‌ها بلکه برای ارجاع‌های به آن کلاس‌ها نیز ممکن است. این قابلیت برای مجهز کردن کلاس ref از لحاظ لغوی ضروری است.

برای مثال، مقایسهٔ دو ارجاع رشته‌ای مجزا با عملگر == مقدار صحیح می‌گیرد، هرگاه که دو رشته برابر باشند. سرریزی بار عملگرها ایستا است. از این رو کست کردن به Object^ روند لغوی سرریزی را کنار می‌گذارد.

```
//effects of reference operator overloading
String ^s1 = "abc";
String ^s2 = "ab" + "c";
Object ^o1 = s1;
Object ^o2 = s2;
s1 == s2; // true
o1 == o2; // false

```

قابلیت همکاری با سی‌پلاس‌پلاس و سی‌شارپ
---------------------------------------

این زبان به سی‌پلاس‌پلاس اجازه می‌دهد از برنامه‌های سی‌شارپ در فایل‌های dll اش استفاده کند. در اینجا کلمهٔ کلیدی using# نشان می‌دهد که فایل dll در کجا قرار دارد. این مثال ساده به صف‌آرایی نیز نیازی ندارد.

```
#include "stdafx.h"
using namespace System;
#using "...MyCS.dll"

int main(array<System::String ^> ^args) {
 double x = MyCS::Class1::add(40.1, 1.9);
 return 0;
}

```

محتوای کد منبع سی‌شارپ برای MyCS.DLL:

```
namespace MyCS {
 public class Class1 {
 public static double add(double a, double b) {
 return a + b;
 }
 }
}

```

این مثال نشان می‌دهد که چطور رشته‌ها از رشته‌های سی‌پلاس‌پلاس به رشته‌های قابل صدا زدن از سی‌شارپ صف‌آرایی می‌شوند و سپس دوباره به رشته‌های سی‌پلاس‌پلاس برمی‌گردند. صف‌آرایی رشته‌ها محتوای رشته‌ها را به اشکالی که در محیط‌های مختلف نیز قابل استفاده باشند، کپی می‌کند.

```
#include <string>
#include <iostream>
#include <msclr\marshal\_cppstd.h>
#include "stdafx.h"
using namespace System;
using namespace std;
#using "..MyCS.dll"

int main() {
string s = "I am cat";
String^ clrString = msclr::interop::marshal\_as<System::String^>(s); // string usable from C#
String^ t = MyCS::Class1::process(clrString); // call C# function
string cppString = msclr::interop::marshal\_as<std::string>(t); // string usable from C++
cout << "Hello, C++/C# Interop!" << std::endl;
cout << cppString << std::endl;
return 0;
}

```

کد سی‌شارپ از وجود کدی به سی‌پلاس‌پلاس خبر ندارد.

```
namespace MyCS {
 public class Class1 {
 public static string process(string a) {
 return a.Replace("cat", "dog") + "with a tail";
 }
 }
}

```

این قابلیت همکاری، دسترسی آسانی برای سی‌پلاس‌پلاس به تمامی قابلیت‌های دات‌نت فراهم می‌سازد.

سی‌پلاس‌پلاس/سی‌اکس
-------------------

سی‌پلاس‌پلاس/سی‌اکس با هدف‌گذاری روی ویندوز رانتایم، با وجود این که کدی تماماً غیرقابل کنترل تولید می‌کند، از ویژگی ref و ^ برای اجزایی از ویندوز رانتایم که با آدرس شمرده می‌شوند، استفاده می‌کند که مشابه اشیای مدل شیء مؤلفه است.

منابع
-----

1. ↑  Managed Extensions for C++ Syntax Upgrade Checklist - MSDN Library
2. ↑  Using C++ Interop (Implicit PInvoke)
3. ↑  Inside the C++/CX Design - Visual C++ Team Blog - Site Home - MSDN Blogs