پرچمداران
-
در پست ها
- همه بخش ها
- فایل
- دیدگاه فایل
- نقد و بررسی فایل
- مقالات
- مقاله دیدگاه
- مقاله نقد و بررسی
- صفحات استاتیک
- صفحه دیدگاه
- صفحه نقد و بررسی
- کتابخانهها
- کتابخانه دیدگاه
- کتابخانه نقد و بررسی
- رویداد
- دیدگاه های رویداد
- بازبینی رویدادها
- تصاویر
- دیدگاه های تصویر
- نقد های تصویر
- آلبوم ها
- نظر های آلبوم
- نقد های آلبوم
- پست ها
- نوشتههای وبلاگ
- دیدگاه های وبلاگ
- بروزرسانی وضعیت
- پاسخ های دیدگاه ها
-
همه زمان ها
-
همه زمان ها
4 خرداد 1397 - 15 آذر 1402
-
سال
16 آذر 1401 - 15 آذر 1402
-
ماه
16 آبان 1402 - 15 آذر 1402
-
هفته
9 آذر 1402 - 15 آذر 1402
-
امروز
16 آذر 1402 - 15 آذر 1402
- تاریخ سفارشی
-
همه زمان ها
مطالب محبوب
در حال نمایش مطالب دارای بیشترین امتیاز از زمان جمعه, 4 خرداد 1397 در پست ها
-
22 امتیازمراحل ساخت برنامه در زبان سیپلاسپلاس پیش نویس ۰.۶ قبل از هر چیز به اینفوگرافی زیر توجه کنید که مراحل ساخت برنامه در سیپلاسپلاس را نشان میدهد. مقدمهای بر همگردانی (کامپایل) و اتصال (لینک کردن) این سند مرور مختصری در رابطه با مراحل را برای شما فراهم میکند تا به شما در درک دستورات مختلف برای تبدیل و اجرای برنامهٔ خودتان کمک کند. تبدیل مجموعهای از فایلهای منبع و هدر در سیپلاسپلاس به یک فایل خروجی و اجرایی در چندین گام (به طور معمول در چهار گام) پیشپردازنده (Preprocessors)، کامپایل و گردآوری (Compilation)، اسمبلر (Assmbler) و پیوند دهنده (Linker) تقسیم میشود. قبل از هر چیز اگر در محیط توسعهٔ Qt Creator داخل فایل .pro مقدار زیر را وارد کنید، تا بتوانید فایلهای ساخته شدهٔ موقت در زمان کامپایل را مشاهده کنید. QMAKE_CXXFLAGS += -save-temps این دستور اجازهٔ آن را خواهد داد تا فایلهایی با پسوند .ii و .s در شاخهٔ بیلد پروژه تولید شوند که در ادامه به آنها اشاره شده است. تعریف پیشپردازنده پیشپردازندهها (Preprocessors) درواقع دستوراتی هستند که اجازه میدهند تا کامپایلر قبل از آغاز کردن مراحل کامپایل دستوراتی را دریافت کند. پیشپردازندهها توسط هشتگ (#) مشخص میشوند این نماد در سی++ مشخص میکند که دستور فوق از نوع پیشپردازنده میباشد که نتیجهٔ آن در قالب ماکرو (Macro) در دسترس خواهد بود. برای مثال ماکروی __DATE__ توسط پیشپردازندهها از قبل تعریف شده است که مقدار تاریخ و زمان را بازگشت میدهد. بنابراین هرکجا که از آن استفاده شود کامپایلر آن را جایگزین متن خواهد کرد. در شکل زیر مرحلهای که از پیشپردازندهها استفاده میشود آمده است: پیشپردازنده، کامپایل (گردآوری کردن)، لینک (پیوند کردن) و ساخت برنامه اجرایی فرایند تبدیل مجموعهای از فایلهای متنی هِدر و سورس سی++ را «ساخت» یا همان Building میگویند. از آنجایی که ممکن است کُد پروژه در بسیاری از فایلها هدر و سورس سی++ توسعه و گسترش یابدمراحل ساخت در چند گام کوچک صورت میگیرد. یکی از رایجترین موارد در مراحل گردآوری (ترجمهٔ یک کد سیپلاسپلاس به دستورالعملهای قابل فهم ماشین) است. اما گامهای دیگری نیز وجود دارد، پیشپردازنده و لینک (پیوندها) این بخش به طور خلاصه توضیح میدهد که چه اتفاقی در هر یک از مراحل رُخ میدهد. یک کامپایلر یک برنامهٔ خاص است که پردازش اظهارات (دستورات) نوشته شده در یک زبان برنامهنویسی خاص را به یک زبان ماشین که قابل فهم برای پردازنده میباشد تبدیل کند. به طور معمول یک برنامهنویس با استفاده از یک ویرایشگر که به محیط توسعهٔ یکپارچهٔ نرمافزار (IDE) مشهور است توسط زبان برنامهنویسی مانند ++C دستورات (اظهارات) را مینویسد. فایل ایجاد شده با نام (filename.cpp در زبان برنامهنویسی سیپلاسپلاس) شامل محتوایی است که معمولاً به عنوان دستورات برنامهنویسی سطح بالا نامیده میشود. سپس برنامهنویس کامپایلرِ مناسب برای زبان برنامهنویسی مانند سی++ را اجرا میکند و نام فایلهایی که حاوی دستورات هستند را برای کامپایل مشخص میکند که این انتخاب و مشخص سازی توسط IDE به راحتی قابل مدیریت است. پس از آن، کار کامپایلر این است که فایلهای منبع .cpp را جمع آوری کرده و پیشپردازندهها را بررسی کند تا دستورات احتمالی را اجرا نماید که نتیجهٔ این مرحله در فایلی با پسوند .ii ر قالب filename.ii تولید میشود که در این فرایند نیز خط به خط کُدهای موجود در آنها را بررسی میکند تا خطاهای احتمالی نحو (سینتکس - Syntax) بررسی میشود و آنها را به طور ترتیبی به دستورالعملهای سطح ماشین تبدیل کند. توجه داشته باشید که هر نوع پردازندهٔ کامپیوتر دارای مجموعهای از دستورالعملهایِ ماشین خودش است. بنابراین کامپایلر تنها برای سی++ نیست، بلکه برای اهداف و مقاصد خاص هر پلتفرم است. پس کدهایی که توسط پیشپردازنده سیپلاسپلاس به زبان اسمبلی برای معماری مورد نظر در پلتفرم مقصدترجمه شدهاند نتایج آن در فایلی با پسوند .ss در قالب filename.ss قابل نمایش هستند که در حالت عادی قابل رویت نیست. توجه داشته باشید که باید در این مرحله باید مشخص شود برنامه قرار است توسط چه نوع پردازندهای تحتِ چه نوع معماری مونتاژ (اسمبل) شود. برای مثال پردازندهها با انواع معماریهای مختلف وجود دارند که برخی از آنها به صورت x86-x64، x64، ARMv7، aarch64 غیره ... میباشند. شکل یک (کامپایل یک فایل منبع ++C) مرحلهٔ سوم را در نظر داشته باشید که عمل کامپایل فایل سیپلاسپلاس در دو مرحله قبلی یک فایل اجرایی را تولید نمیکند. برنامهای که توصیف شده است، احتمالاً توابعی را در رابطهای برنامهنویسی (API) و یا توابع ریاضی یا توابع مرتبط با I/O را فراخوانی کند که ممکن است شامل فایلهای هدر مانند iostream یا fstream و حتی ماژولهای دیگری که در زبان تعبیه شدهاند را داشته باشد که فایل تولید شده توسط کامپایلر در این مرحله یک فایل شیء نامیده میشود که با پسوند .o به صورت filename.o تولید خواهد شد که علاوه بر دستورالعملهای تبدیل شده به کد ماشین، شامل توابع و دستورالعملهای خارجی نیز میباشد. هرچند در این مرحله دستورات تبدیل به دستورالعملهای قابل فهم توسط پردازنده شدهاند اما فعلاً قابل اجرا نیستند چرا که باید این توابع خارجی افزوده شده را به آن لینک کرد که در مرحلهٔ بعد یعنی مرحلهٔ چهارم اتفاق میافتد. در نهایت مرحلهٔ چهارم فایل با پسوند .o که شامل کدهای تولید شده توسط کامپایلر به زبان ماشین است که پردازندهها میتوانند این دستورات را درک کنند که همراه با کدهای تولید شدهٔ هر کتابخانهٔ دیگری که مورد نیاز است توسط لینکر (لینک شده) و در نهایت جهت تولید یک فایل اجرایی مورد استفاده قرار میگیرند که نوع آن فایل از نوع اجرایی یا در واقع Executable File خواهد بود. شرح کامل فرایند ساخت فایل اجرایی اکثر پروژهها دارای مجموعهای از فایلهای هدر سی++ هستند، که امکان ماژولار شدن در آن را فراهم میکند و مجموعهای از آن میتواند به عنوان بخشهای کوچکی از برنامه محسوب شوند. برای ساخت چنین پروژههایی هر فایل سیپلاسپلاس باید کامپایل شود و سپس فایلهای ساخته شده در قالب شیء (آبجکت) باید همراه توابع و کتابخانههای دیگر لینک (پیوند) شوند. البته هر گام از مراحل کامپایل شامل یک مرحله پیشپردازنده است که دستورالعمل # عمل تغییرات و اصلاحیهها را در فایل متن اعمال میکند. شکل زیر فرایند ساخت چند فایل به صورت همزمان را نشان میدهد: در ادامهٔ این مقاله، مطلبی مرتبط با تنظیمات بیشتر از کامپایلر آمده است که میتوانید آن را مورد مطالعه قرار دهید.
-
12 امتیازآیا این واقعاً امکانپذیر است؟ پاسخ : بله! من میدانم که ممکن است این مبحث تحت سی++ بسیار پیچیده و یک کار بیهودهای باشد! اما واقعیت این است که تکنیکهای پنهان بسیاری وجود دارد که ممکن است همه از آن باخبر نباشند! من قبلاً در مورد اینکه تحت ++C وبسایت میشه طراحی کرد یا خیر تحقیقاتی انجام داده بودم، از لحاظ امکان بودنش جواب مثبت بود اما اینکه به راحتی طراحی تحت Php یا دیگر زبانهای برنامهنویسی باشه خیر! خُب طبیعیه چون شما بسیار راحت یه اسکریپت رو مینویسی و روی سرور اجراش میکنی و سایت شما به خوبی و خوشی بالا میاد! ممکن است در همین قسمت از موضوع شما به این نتیجه رسیده باشید که خُب نیازی به ادامهٔ بحث نداریم! وقتی کار سختیه پس منطقی نیست و شما احتمالاً دیوانهای!!! ? واقعیت جریان این است بر خلاف آن چیزی که تصور کردهایم طراحی وبسایت با سیپلاسپلاس نه تنها بسیار راحت است بلکه بسیار هم جذاب خواهد بود! اما در نگاه اول ممکن است یک سری محدودیتهارا داشته باشد که همهٔ این موارد با کمی تأمل و بررسی قابل حل هستند به قدری که وقتی درگیر این جریان باشید شیفتهٔ آن خواهید شد. مزایای یک وبسایت تحت سیپلاسپلاس نسبت به دیگر زبانهای رایج سرعت خارقالعاده و غیر قابل مقایسه با زبانهای رایج امنیت بهتر کدهای شما مدیریت سادهتر و انعطافپذیری بالا مصرف بسیار بهینه و غیر قابل تصور از منابع سرور دسترسی نامحدود به کتابخانهها عدم محدودیت در دسترسی به برنامهنویسی سطح پایین عدم محدودیت در استفاده از توابع سیستمعامل عدم محدودیت در مدیریت سیستم و هر ویژگی دیگری که در زبانهای اسکریپتی اگر به آن نیاز داشته باشید مجبور هستید تا به صورت اکستنشن آن را تحت سیپلاسپلاس باز نویسی کنید. سیستم راهانداز وبسرور چگونه است؟ در هر سروری CGI به شما امکان این را میدهد که بتوانید تحت پروتکلهای استاندارد برنامههای تحت وب را اجرا کنید. شما میتوانید تحت آن و یا موارد دیگری مانند FastCGI و WSGI و دیگر موارد بهینه شدهٔ آن برنامهٔ تحت وب را بر روی سرور خود اجرا کنید. طراحی قالب هماهنگی با HTML, JavaScript, Css در سیپلاسپلاس چگونه خواهد بود؟ همهٔ گزینههای مربوط به وب را شما بدون هیچ محدودیتی در اختیار خواهید داشت. شما هیچ محدودیتی در استفاده از ویژگیهای HTML5 یا CSS3 و یا JavaScript و دیگر فریمورکها و کتابخانههای کارآمدی چون Angular.JS را نخواهید داشت. بنابراین از نظر طراحی رابط یک وبسایت همانند دیگر زبانهای رایج میتوانید روی آن حساب کنید. طراحی هسته و بکاِند وبسایت چگونه خواهد بود؟ همانند زبانها و فریمورکهای رایج تحت وب شما در سیپلاسپلاس میتوانید هستهٔ وبسایت یا سیستم وبسایت خود را تحت استاندارد سیپلاسپلاس و هر کتابخانهای که میپسندید و یا به آن تسلط دارید پیاده سازی کنید! به شرطی که قابلیتهای آن کتابخانه پاسخگوی نیازهای شما باشد. با این حساب شما میتوانید حتی سیستم مدیریت محتوای (CMS) خود را طراحی کنید! ? بله سیستم مدیریت محتوا تحت سیپلاسپلاس! کاملاً جدی هستیم ? قبل از هر چیز یک مزیت بسیار بزرگ در کنار مزیتهای دیگر این است که یک CMS تحت سیپلاسپلاس میتواند داشته باشد مصرف بهینه از منابع سرور خواهد بود. برای مثال در یک مقایسهٔ ساده و آزمایشی نتیجهٔ بسیار جالبی ارائه شده است. همانطور که میدانید Wordpress به عنوان یک سیستم مدیریت محتوای (بلاگ) شناخته شده و تحت Php توسعه یافته است. نسخهٔ سریعتر و بهینهتر آن با نام Ghost تحت Node.JS توسعه یافته است که ما نسخهٔ توسعه یافتهٔ آن را با یک عمل مشابه در C++1z مورد بررسی قرار داده ایم که نتایج آن بسیار جالب است! مصرف حافظه سیستم مدیریت محتوای Tegra ۳۵۰۰ درخواست در هر ثانیه 3.6 مگابایت سیستم مدیریت محتوای Ghost 100 درخواست در ثانیه 120 مگابایت پشتیبانی از پایگاههای داده به لطف کتابخانههای عظیم سیپلاسپلاس امکان مدیریت یک وبسایت تحت پایگاههای داده مختلفی ممکن است. برای مثال تحت Qt شما میتوانید به رایجترین درایورهای بانکاطلاعاتی دسترسی داشته و سیستم خود را به آنها مجهز کنید. نکته: احتمالاً در برنامهنویسی با نود جیاس و پیاچپی شناختی با کتابخانههای OpenSSL, Libcurl و موارد این چنینی داشته اید! کتابخانههای فوق عضو لیست کتابخانههای C و ++C هستند. بنابراین شما علاوه بر دسترسی مستقیم بر آنها به هزاران و شاید میلیونها کتابخانه در دنیا سیپلاسپلاس خواهید داشت. نمونهٔ اولیه اما شوقآور برای اثبات امکان طراحی وبسایت تحت سیپلاسپلاس چندی پیش من تصمیم گرفتم تا سیستم وبسایتی را تحت Php7 برای یکی از استارتآپها طراحی و پیاده سازی کنم که در این پست به آن اشاره شده است. از آنجایی که به لطف کتابخانهٔ Qt برنامههای سمت کاربر را توسط سیپلاسپلاس پیاده سازی کرده بودم به این فکر افتادم چرا سمت سرور و بخش وبسایت هم با آن هماهنگ نشود!؟ اینگونه هماهنگی بین برنامهها و پرفرمنس همهٔ آنها بسیار افزایش خواهد یافت در اولین نگاه این تفکر بسیار ناشیانه و بسیار ناممکن بود! تنها روشی که به کار گرفته بودم ارسال اطلاعات از طرف کاربر به سمت سرور و مدیریت آنها تحت معماری Restful Api بود که در قالب JSon آنها را تجزیه و مدیریت میکردم. با کمی تحقیق در مورد ویژگیهای سمت وب تحت Fast-CGI, uWSGI, DJango, ClearSilver و موارد مرتبط با آنها سعی کردم تا صفحهٔ بسیار سادهای از HTML را توسط سیپلاسپلاس هندل کنم. این کار نتایج بسیار موفقیت آمیزی را در بر داشت تا نتیجهٔ آن تبدیل به یک پروژهٔ سیستم مدیریت محتوا تحت ++C شد. من پروژهای با نام مفهومی Tegra که نام پروژهٔ قبلی تحت Php بود را در محیط Qt Creator با C++17 و کتابخانهٔ Qt باز سازی کرده و هستهٔ اولیهٔ آن را برای اجرای چند صفحه از یک وبسایت، احراز هویت، بازخوانی و نمایش لیستی از خبرها و مدیریت متا تگها و آدرس صفحات مربوط به هر صفحه را ایجاد کردم. سعی کرده ام در کمترین زمان ممکن برای آزمایش یک سری ویژگیهای اولیه از یک وبسایت آنها را مورد بررسی قرار بدم که عبارتند از هماهنگی با فریمورکهای طراحی مانند BootStrap و یا Angular.JS که خوشبختانه همهچیز بسیار خوب در کنار همدیگه کار میکنند. هستهٔ سیستم به صورت جدا و معماری طراحی آن بر پایهٔ MVC مورد آزمایش قرار گرفته است. در زیر تصاویری از صفحات تولید شده تحت سیستم مدیریت محتوای ساخته شده با سیپلاسپلاس را مشاهده میکنید. ? همه چیز در قدمهای اول قرار دارد و با توجه به سادگی تولید وب سایت بر خلاف تصوری که داشتیم بسیار توسعه و جای پیشرفت خواهد داشت. بخشی از نمونه کدهای این سیستم به صورت زیر آورده شده است تا ذهنیتی برای توسعهدهندگان ارائه شود: تکه کُد زیر عمل ارسال اطلاعات و تمامی لینکهای مربوط به بوت استرپ را برای سمت HTML ارائه میکند که در قالب استاندارد جدید C++17 آورده شده است: auto bootstrapCss = bootStrapLib.find("css"); if(bootstrapCss != bootStrapLib.end()) { c->setStash("BootstrapCss", bootstrapCss->second.c_str()); std::cout << "Found " << bootstrapCss->first << " " << bootstrapCss->second << '\n'; } کد مربوط به سمت قالب به صورت زیر خواهد بود: <!-- Bootstrap core css --> <link href="{{BootstrapCss}}" rel="stylesheet"> نتیجهٔ فوق در صورتی که CDN بر روی لوکال تنظیم شده باشد از روی کدهای کامپایل شده و یا استاتیک فراخوانی خواهد شد. در غیر اینصورت از روی یکی از سرورهای CDN فراخوانی میشوند. نحوهٔ ارسال متغیر از سمت سیپلاسپلاس به قالب بسیار ساده است! بسیار ساده از Php و یا Node.JS میباشد. با در نظر گرفتن ارسال اطلاعات از سمت سیپلاسپلاس به سمت رابط کاربری کافی است نام متغیرها را در قالب خود اعمال کنید. {% for post in news %} <div class="blog-post"> <h2 class="blog-post-title"><a href="news/{{post.uri}}">{{post.title}}</a></h2> <p class="blog-post-meta">{{post.date}} by <a href="#">{{post.author}}</a></p> <p>{{post.announcement|safe}}</p> </div><!-- /.blog-post --> {% endfor %}</div> این ساختار بر پایهٔ ساختار Angular.JS و DJango پیاده سازی شده است که به طور کامل پشتیبانی میشود. فعال سازی فناوری Angular.JS بر روی این سیستم جهت طراحی قالب تنها با دو دستور ساده اعمال میشود: <!-- Link to AngularJS --> <script src= "{{AngularJs}}"></script> <!-- Enable AngularJS Engine --> {{AngularJsSync|safe}} این دستورات در هستهٔ سیستم مدیریت محتوا در کلاسی با نام Template پردازش و در نهایت به سمت HTML هندل میشوند. بخشی از دستورات سمت هسته در سیپلاسپلاس ۱۷ برای مثال ارسال عنوان صفحه به صورت زیر است: std::optional<std::string> LoadListTemplate::getTitle() const { if (isset(title)) { return title; } else { return std::nullopt; } } سمت HTML کافی است دستور فوق را در نظر بگیریم: <title>{{title}}</title> اینها مثالهایی از مراحل توسعهٔ این سیستم است که میدانم آنچنان گسترده نیست، اما برای ثابت کردن طراحی و توسعهٔ وبسایت تحت سیپلاسپلاس مثالهای روشنی هستند. موفق و سربلند باشید! اطلاعیههای مربوط به این پروژه احتمالاً در کانالها و گروه تلگرامی و همین مرجع بازگو و در اختیار شما قرار گیرد.
-
11 امتیازجزئیات در ++C ویرایش ۱۷: کد نویسی ساده با توجه به مشخصاتی که در استاندارد ISO/IEC 14882:2017 که ارائه شده است، ویژگیهای جدید برای این معرفی میشوند تا کد شما تمیز تر و بهتر و در کل رَساتر اعمال شوند. این مقاله را برای مطلع شدن از جزئیات بیشتر بخوانید. سیپلاسپلاس ۱۷ چندین ویژگی بزرگ زبان را ارائه میدهد که باعث میشود کد ما زیباتر و بهتر شود. بنابراین بیایید باهم یک نگاهی به این ویژگیها داشته باشیم. ممکن است شما بگویید که بیشترین ویژگیهای جدید زبان (به جز پیشرفت های کتابخانه استاندارد - STL) برای نوشتن کد ساده تر و پاکتر میباشند. با توجه به مجموعه جزئیات سیپلاسپلاس ۱۷ که بسیاری از چیزهای بزرگ را مورد بررسی قرار داده است، ما امروز تنها برای بعضی از ویژگی ها که از داخل این مجموعه عظیم بیرون کشیدهایم اشاره خواهیم داشت که باعث میشود کد شما فشردهتر و بهینه تر شود. پیوندهای ساخت یافته / اعلانهای تجزیه عبارت Init-statement برای if/switch متغیرهای درون خطی (inline) شرط constexpr if و چند موارد دیگر پیوندهای ساخت یافته، آیا اغلب با tuple ها کار کردهاید؟ اگر نه، پس احتمالاً باید به آن نگاهی کنید. tuple ها تنها برای بازگشت مقادیر چند گانه از یک تابع پیشنهاد نمیشوند، آنها پشتیبانی ویژگیای از زبان را داشتند. به طوری که باعث میشود کد ساده تر و پاکتر شود. برای مثال (std::tie که از مرجع اصلی سیپلاسپلاس به دست آمده است) به صورت زیر است: std::set<S> mySet; S value{42, "Test", 3.14}; std::set<S>::iterator iter; bool inserted; // unpacks the return val of insert into iter and inserted std::tie(iter, inserted) = mySet.insert(value); if (inserted) std::cout << "Value was inserted\n"; توجه داشته باشید که باید iter و inserted را ابتدا وارد کرده باشید. سپس شما میتوانید از std::tie استفاده کنید. با این حال این بخش کوچکی از کد نمونه است: std::set<S> mySet; S value{42, "Test", 3.14}; auto [iter, inserted] = mySet.insert(value); اینجا توجه داشته باشید که یک خط به جای سه خط جایگزین شده است! این کد سادهتر و خواناتر و درعین حال ایمن تر است، اینطور نیست؟ همچنین، شما هم اکنون میتوانید از const استفاده کنید و آن را به صورت const auto [iter inserted] بنویسید که صحیح است. پیوند ساختاری تنها به tuple ها ختم نمیشود، چرا که ما سه مورد دیگر را داریم: اگر مقدار دهی اولیه یک آرایه باشد: // works with arrays: double myArray[3] = { 1.0, 2.0, 3.0 }; auto [a, b, c] = myArray; اگر مقدار دهی اولیه std::tuple_size<> را پشتیبانی کند و تابع get را فراهم کند که شایع ترین مورد است. auto [a, b] = myPair; // binds myPair.first/second به عبارت دیگر، شما میتوانید کلاسهای خود را پشتیبانی کنید، با فرض این که شما تابع get را در پیاده سازی رابط کلاس خود اضافه کرده باشید. اگر مقدار دهی اولیه فقط شامل اعضای عمومی شود در این صورت: struct S { int x1 : 2; volatile double y1; }; S f(); const auto [ x, y ] = f(); در حال حاضر این روش برای دریافت یک مرجع از یک عضو tuple آسان است. auto& [ refA, refB, refC, refD ] = myTuple; و یکی از جالبترین استفادهها (پشتیبانی از حلقهها است): std::map myMap; for (const auto & [k,v] : myMap) { // k - key // v - value } پیوند ساختاری یا تقسیم بندی اعلانها برای این ویژگی، ممکن است شما نام های دیگری را دیده باشید، "اعلان تجزیه". همانطور که میبینیم، این دو نام در نظر گرفته شده است، اما فعلاً استاندارد سازی در حالت پیشنویسه است و با نام "پیوندهای ساختاری" میباشند. جزئیات بیشتر در رابطه با این مورد در اسناد P0217R3، P0144R0 و P0615R0 موجود هستند. همچنین این مورد با کامپایلرهای GCC 7.0،MSVC2017 و Clang 4.0 سازگار است. عبارت Init-statement برای if/switch نسخه جدید عبارت شرطی if و switch در سیپلاسپلاس جدید به صورت زیر است: if (init; condition) , switch (init; condition) قبلاً باید به صورت زیر مینوشتیم: { auto val = GetValue(); if (condition(val)) // on success else // on false... } در اینجا val یک دامنه جدا کننده بدون دارد که باعث "نشت - فقدان" در خاتمه دهنده دامنه خواهد شد. در حالی که شما در نسخه جدید میتوانید به صورت زیر بنویسید: if (auto val = GetValue(); condition(val)) // on success else // on false... متغیر val تنها در داخل عبارات if و else قابل رویت است، بنابراین آن یک "نَشت" نخواهد داشت. condition ممکن است چندین عبارت باشد نه تنها if بنابراین متغیر val یکی از دو مقدار true/false را خواهد داشت. چرا این ویژگی کاربرد دارد؟ اجازه دهید تا به شما بگوییم زمانی که میخواهید چندین چیز را در یک رشته را جستجو کنید به صورت زیر خواهید داشت: const std::string myString = "My Hello World Wow"; const auto it = myString.find("Hello"); if (it != std::string::npos) std::cout << it << " Hello\n" const auto it2 = myString.find("World"); if (it2 != std::string::npos) std::cout << it2 << " World\n" ما باید از نامهای مختلفی برای it استفاده کنیم و یا اینکه آن را با دامنه خاتمه دهنده جدا سازیم. { const auto it = myString.find("Hello"); if (it != std::string::npos) std::cout << it << " Hello\n" } { const auto it = myString.find("World"); if (it != std::string::npos) std::cout << it << " World\n" } عبارت جدید شرطی if در نسخه جدید یک دامنه اضافه را در یک خط ایجاد میکند. if (const auto it = myString.find("Hello"); it != std::string::npos) std::cout << it << " Hello\n"; if (const auto it = myString.find("World"); it != std::string::npos) std::cout << it << " World\n"; همانطور که قبلاً اشاره شده است، متغیر تعریف شده در عبارت شرطی if در بلوک دیگری قابل مشاهده است. بنابراین شما میتواین به صورت زیر بنویسید: if (const auto it = myString.find("World"); it != std::string::npos) std::cout << it << " World\n"; else std::cout << it << " not found!!\n"; به علاوه، شما میتوانید آن را با پیوند ساختاری بر اساس کد نمونه از جانب (Herb Sutter) استفاده کنید: // better together: structured bindings + if initializer if (auto [iter, succeeded] = mymap.insert(value); succeeded) { use(iter); // ok // ... } // iter and succeeded are destroyed here جزئیات بیشتر در اسناد زیر آمده است: سند P0305R1 ویدیو موجود در یوتیوب با عنوان (C++ Weekly - Ep 21 C++17’s if and switch Init Statements) این مورد با کامپایلرهای GCC 7.0،MSVC-2017.3 و Clang 3.9 سازگار است. متغیرهای درون خطی (inline) با شروع مقدار دهی دادههای غیر استاتیک، اکنون میتوانیم یک متغیر عضو را دی یک مکان اعلام کنیم. با این حال، با متغیرهای استاتیک یا const static، معمولاً باید آن را در برخی از فایلهای cpp تعریف کنید. در سیپلاسپلاس ۱۱ و کلید واژه constexpr که مارا قادر میسازد تا در یک مکان اعلان و تعریف متغیرهای استاتیک را انجام دهیم، اما این امکان تنها به constexpr محدود میشود. قبلاً فقط روشها/توابع میتوانستند به عنوان inline تعریف شوند، حالا شما میتوانید این کار را با متغیر ها در داخل فایل هدر انجام دهید. یک متغیر اعلام شده درون خطی معنای مشاهبی دارد بنابراین همانند یک تابع inline تعریف میشود. آن را میتوان به واحدهای ترجمه چند گانه نیز تعریف کرد. مثالهای زیر را ببینید: struct MyClass { static const int sValue; }; inline int const MyClass::sValue = 777; و حتی struct MyClass { inline static const int sValue = 777; }; همچنین توجه داشته باشید که متغیرهای constexpr به طور ضمنی inline هستند، بنابراین نیازی به استفاده به صورت constepr inline myVar = 10; نمیباشد. این ویژگی چرا کد را ساده تر میکند؟ برای مثال، تعداد زیادی از هدرها در کتابخانه تنها تعدادی از روش های (هک) را محدود میکنند (مانند استفاده توابع درون خطیinline و یا قالب ها) و در نهایت مزیت constexpr این است که مقدار دهی اولیه شما نباید constexpr باشد. جزئیات بیشتر در رابطه با این ویژگی در سند زیر موجود است: سند P0386R2 این مورد با کامپایلرهای GCC 7.0 و Clang 3.9 سازگار است اما فعلاً با MSVC سازگاری ندارد. ویژگی مربوط به constexpr if ممکن است در بعضی جاها به قابلیت std::enable_if در سیپلاسپلاس ۱۴ نگاه کنید که آن به راحتی با constexpr if جایگزین میشود. بنابراین، در اکثر موارد، ما اکنون میتوانیم تنها با نوشتن عبارت یک constexpr if این کار را بهتر و تمیز تر انجام دهیم. این ویژگی برای برنامه نویسی metaprogramming/template بسیار مهم است که احتمالاً طبیعت آن بسیار پیچیده خواهد بود. یک مثال ساده با تابع Fibonacci: template<int N> constexpr int fibonacci() { return fibonacci<N-1>() + fibonacci<N-2>(); } template<> constexpr int fibonacci<1>() { return 1; } template<> constexpr int fibonacci<0>() { return 0; } حال میتوان آن را تقریباً در یک حالت نرمال (نسخه بدون کامپایل) نوشت: template<int N> constexpr int fibonacci() { if constexpr (N>=2) return fibonacci<N-1>() + fibonacci<N-2>(); else return N; } در رویداد ۱۸ هم جلسات هفتگی سیپلاسپلاس در جیسون ترنر نمونهای را میتوان یافت که در آن عبارت constexpr if هیچ منطق اتصال کوتاهی را در زمان کامپایل انجام نمیدهد، بنابراین این کد باید کامپایل شود: if constexpr (std::is_integral<T>::value && std::numeric_limits<T>::min() < 10) { } در کد فوق برای T شما در std::string خطایی کامپایل را دریافت خواهید کرد زیرا numeric_limits برای رشته ها تعریف نشده اند. در جلسات C++NOW 2017 آقای Bryce Leblbach با عنوان جلسه خود C++17 Features در ۱۶ دقیقه مثال بسیار زیبایی را در رابطه باconstexpr if زد که میتواند برای تابع get استفاده شود که آن برای پیوند ساختاری مورد استفاده قرار میگیرد. struct S { int n; std::string s; float d; }; template <std::size_t I> auto& get(S& s) { if constexpr (I == 0) return s.n; else if constexpr (I == 1) return s.s; else if constexpr (I == 2) return s.d; } قبلاً ما باید به صورت زیر مینوشتیم: template <> auto& get<0>(S &s) { return s.n; } template <> auto& get<1>(S &s) { return s.s; } template <> auto& get<2>(S &s) { return s.d; } همانطور که میبینید، مشکل سوال برانگیز اینجاست که کد در این جا ساده تر است. اگر چه در این مورد فقط از یک ساختار ساده استفاده شده است، با برخی از نمونه های واقعی دنیا، کد نهایی باید بسیار پیچیده تر از این باشد بنابراین باید constexpr if کد تمیز تری نسبت به این مورد باشد. این مورد با کامپایلرهای GCC 7.0،MSVC-2017.3 و Clang 3.9 سازگار است. ویژگیهای دیگر ما میتوانیم در رابطه با بسیاری از ویژگی های جدید سیپلاسپلاس صحبت کنیم اما در این پست ما بیشتر در رابطه با قطعات بزرگتر تمرکز کردهایم. با این حال، فقط برای یادآوری، ممکن است بخواهید ویژگیهای زیر را در نظر بگیرید که آنها نیز کد ها را ساده تر میکنند: الگو یا قالبها (templates) عبارت Fold الگو برای کلاس ها بنابراین برای ذکر ویژگیهای بیشتر در رابطه با نسخه جدید در پستهای آن ها را پوشش خواهیم داد. شک نکنید که، سیپلاسپلاس ۱۷ پیشرفت واقعی را در برابر کد های جمع و جور و آسان فراهم گرده است. یکی از بهترین چیزها constexpr است که آن به ما اجازه میدهد کد template/metaprogramming را به روش کد استاندارد شده بنویسیم. این یک مزیت بسیار بزرگی است. ویژگی دوم: پیوند ساخت یافته (که حتی برای حلقه ها کار میکند) مانند حسی را القا میکند که در زبانهای پویایی مثل Python وجود دارد. همانطور که میبینید، تمام ویژگیهای ذکر شده در حال حاضر در Clang، MSVC و GCC قابل اجرا هستند. اگر شما با نسخههای اخیر این کامپایلر ها کار میکنید میتواین بلافاصله با سی++ ۱۷ کار کرده و آن را تجربه کنید.
-
10 امتیازبا سلام، با توجه به سوالات مکرر برخی از کاربران و خصوصاً دانشجویان جدید، تصمیم گرفته شد تا توضیحاتی دربارهٔ نحوهٔ یادگیری برنامهنویسی با سیپلاسپلاس بیان شود. قبل از هر چیز لازم است بدانید، سیپلاسپلاس یک زبان برنامهنویسی کاملاً تخصصی مهندسی است. بنابراین یادگیری آن طبیعتاً نیاز به تلاش، تحمل و پشتکار کافی در مقابل چالشهای آن خواهد داشت. مقدمه در حال حاضر بیش از سه دهه است که از ساخت و معرفی زبان برنامهنویسی ++C میگذرد. در رابطه با آن که هدف از ایجاد این زبان چه چیزی بوده و مزایای آن نسبت به زبانهای دیگر چه چیزی است (چرا موتور مخفی جهان مدرن امروزی است) را میتوانید در این مقاله مطالعه کنید. اما بسیاری از افراد علاقهمند به زبانهای برنامهنویسی تمایل بسیاری دارند تا در برنامهنویسی با این زبان به درجه مطلوب و درواقع (حرفهای) برسند. قبل از هر چیز باید مواردی را در نظر داشته باشیم که یاد گیری زبانهای برنامهنویسی به خودی خود کافی نیست! مخصوصاً زبانهای C و ++C مستلزم پیشنیازهای تخصصی بسیاری هستند که در روند تولید، توسعه، تجزیه و تحلیل لایههای مختلف مهم است. آیا زبان سیپلاسپلاس در حال توسعه است؟ به جرأت میتوانم بگویم که سیپلاسپلاس به عنوان پیشتاز زبانهای برنامهنویسی با سرعت بسیار زیادی در حال گسترش و توسعهٔ خود است. بهتر است بدانید این زبان از شیوهٔ نسخهنگاری معمولی بهره نمیبرند، بلکه از «استاندارد» (ISO/IEC) که کمیتهٔ استانداردسازی آن را تأیید و نهایی میکند بهره میبرد. بنابراین، بر اساس استانداردی پیش میرود که پیشنویسهها و بهبودهای آن تماماً با حفظ (پشتیبانی از عقبگرد) قابل توجه است. همانطور که در تصویر مربوطه میبینید، سیپلاسپلاس در آخرین بهروز رسانی، به نقشهٔ توسعهٔ خود در سالهای بعد نیز اشاره کرده است که در قالب استانداردهای ۲۳، ۲۶ و ۲۹ از الآن یاد شدهاند. چیزی که در هیچ زبانی در وضعیت فعلی به صورت نقشهٔ راه از توسعه آنها نمیتوان دید! این خود یک نکتهٔ بسیار مثبت است که تیم (کمیته) استانداردسازی این زبان کاملاً این اطمینان را میدهد که این زبان نسبت به نیاز و آینده در حال به روز بوده، است و خواهد بود. لازم است بدانید، استانداردهای فعلی، ۱۷ و ۲۰ و بعد ۲۳ به عنوان یک نسل انقلابی و جهش یافته از سیپلاسپلاس یاد میشوند، اگر شما تجربهٔ نوینی از برنامهنویسی را میطلبید، بهتر است به استاندارد ۲۰ خوشآمدگویی کنید که در کنار کارآیی بسیار عالی، یک نحو و سبک بسیار ساده و روان در اختیار توسعهدهنده قرار میدهد. در ادامه ما به سوالاتی که معمولاً توسط تازهکاران پرسیده شده است پاسخ دادهایم: ابعاد علمی و اقتصادی کار با ++C در ایران متاسفانه اکثر ما ملتی هستیم، تَنبَل و حاضر برای لُقمهٔ آماده! بنابراین بازار کار در ایران به گونهای است که بیشتر شرکتها و افراد توسعه دهنده به سراغ زبانهای سادهتر و در دسترستر (بی دردسر) میروند. غافل از آن که یک برنامهٔ تولید شده توسط سی++ بسیار سریع، جذاب، قدرتمند و انعطافپذیرتر است. همهٔ بحث در اینجا تمام نمیشود، چرا که شاید در سالهای اخیر وضعیت تقریباً فرق کرده و به کمک اطلاع رسانیهای اساتید و دوستان حرفهای، ما در این زمینه این اطلاعرسانی به خوبی صورت گرفته و توسعه دهندهها از قابلیتها پنهان این زبان آگاه شدهاند و میدانند که سیپلاسپلاس به عنوان یک زبان بسیار کاربردی در زمینههای مختلف جایگاه ویژهای دارد. شرکتها و گروههای برنامهنویسی بسیاری به دنبال برنامهنویسهای سی++ هستند که این امر نشان دهندهٔ این است که نسبت به سالهای گذشته پیشرفت و آگاهی جامعهٔ برنامهنویسی در این حوزه منطقیتر و بهتر شده است. من بارها در مورد بحث محدودیتهای سختافزاری، مشکلات و محدودیتهای پیش و روی قانون مور، مسائل مربوط به انرژی سبز و غیره صحبت کردهام. و اکنون زمان آن رسیده است که بیشتر در این باره فکر کنید که واقعاً چه ابزارهایی آیندهٔ بهتر و موثرتری در پیشرفت صنایع خواهند داشت. بنابراین، بهتر است قبل از هرچیز در نظر داشته باشید که هدف از این تاپیک، این نیست که اثبات کنیم یک زبان نسبت به زبان دیگر برتری دارد. هدف اصلی من این است به واقعیتهایی اشاره کنم که غیر منطقی نیستند. چرا که واقعاً کارفرمایانی وجود دارند که نیازمند به برنامهنویسانی هستند که تخصص خوبی در زبانهای برنامهنویسی دیگری مانند ++C دارند. همه چیز در زبانهای سطحبالاتر خلاصه نشده است! توجه داشته باشید که هدف از این توضیحات چنین نیست که بعد از خواندن این مطالب زبان برنامهنویسی مورد علاقهٔ خود را کنار گذاشته و به سمت سی++ بروید، خیر! یا مقصود آن نیست که با دیدن و شنیدن پیچ و خمهای آن از یادگیری آن منصرف شوید. من بارها گفتهام، تمامی زبانها به عنوان ابزارهای کاری شما در یک جعبهٔ ابزار هستند و هر زبانی حوزهٔ کاربردی خودش را دارد. بنابراین قبل از اینکه شما تصمیم بگیرید که چه زبانی را یاد خواهید گرفت باید حوزهٔ کاری وعلاقهٔ خودتان را مشخص کنید سپس وارد تحقیق و بحث و نظر خواهی راجع به آن زبان نمایید. مقایسهٔ زبان طبق این قانون کاملاً کار اشتباه و بچهگانه است و به هیچ عنوان در مورد یک زبان برنامهنویسی گاردِ تعصبی نگیرید. متاسفانه به خاطر تفکرات اشتباه و معرفیهای غیر منطقی و غیرعلمی برنامهنویسان کشور ما که ممکن است حتی خودِ شما هم چنین تصور کنید، در رابطه با سایر زبانها مانند سی++ بسیاری از کارفرمایان نیازمند چنین برنامهنویسانی هستند که در کشور ما واقعاً نیاز است. توجه داشته باشید که انتخاب درست این نیست که چون همه سراغ زبانهای پر مخاطبتری میروند و چون تمامی آگهیها استخدامی مرتبط با آنها است پس فقط باید آنها را یاد گرفت! خیر چنین تفکری اشتباه است و ضربهٔ بسیار بزرگی در صنعت و دانش آیندهٔ جامعهٔ تخصصی هر کشوری که به این شکل پیش میرود خواهد زد، چرا که ما باید طبق مسیر و سرعتی که دنیا در حال جهش است، خود را هماهنگ و بهروز کنیم. نکاتی در این میان وجود دارد که باید به آنها اشاره کرد: متاسفانه در کشور ما بسیاری از برنامهنویسان چه مبتدی چه حرفهای اینطور تصور میکنند که تولید محصول نرمافزاری یعنی برنامهنویسی یک نرمافزار که قرار است به بانک اطلاعاتی متصل شده و کارهایی مانند ثبت و ویرایش اطلاعات و در نهایت گزارش گیری و دیگر عملیات ممکن را انجام دهد! این تفکر به شدت اشتباه است! الآن دیگر سیستم نرمافزاری، معماریها و سبک و سیاقهای ساختوساز فرق کرده است. مبتنی بودن بر خدمات متمرکز، غیرمتمرکز و دیگر فناوریها بسیار مهم است. توجه کنید که بزرگترین و معروفترین فناوریها مطرح جهانی معمولاً به واسطهٔ این زبان طراحی میشوند، مانند، سیستمعاملها، نرمافزارها، زیرساختها و حتی بلاکچین و بیتکوین که خالی از لطف نیستند. بسیاری از بانکها و شرکتهای صنعتی و اقتصادی مهم کشور نیازمند برنامهنویسان سی++ هستند تا بتوانند در بحث بانکی برای توسعه دستگاههای پرداخت مانند Pos و ATM از این زبان و برنامهنویسان بهره ببرند. در صنایع بزرگ خودرو سازی و دیگر موارد نرمافزارهای مورد نیاز است تا با سرعت بسیار و بدون محدودی پلتفرمی پاسخگوی یک چرخهٔ تولید باشند تا بتواند زیرساختها و رابطهای یک شرکت بزرگ را مدیریت و آن را بهینه کند. در بسیاری از حوزههای صنعتی کشور شرکتهای غولپیکر در زمینهٔ تولیدات انبوه و سنگین که توسط ماشینآلات صورت میگیرد به دنبال برنامهنویسان سی و سی++ هستند که ممکن است به صورت معرف یا آشنا با آنها مواجه و استخدام شوید. شرکتهای سختافزاری و استارتآپهایی که در حوزهٔ الکترونیک و سختافزار فعالیت میکنند به دنبال برنامهنویسیان سی++ هستند تا بتوانند در حوزهٔ کاری خود اهداف خود را توسعه و شما را به عنوان مهرهای مفید پیش ببرند. شرکتهای توسعهدهندهٔ موبایل و خطوط تولیدی تلفنهای همراه داخلی گسترش یافته و به شدت نیازمند برنامهنویسان سی++ هستند که برخی از آنها مبادلات بینالمللی نیز دارند. در بخش حوزهٔ شهر سازی، مدیرت شهر و همچنین راهداری شرکتهایی هستند که برای تولید سیستمهای مدیریتی مانند مدیریت راهها و ترددهای خودرو و یا مدیریت ترافیک و موارد این چنینی به دنبال برنامهنویسان سی++ هستند. بسیاری از شرکتها و حتی تیمهای توسعه بر روی پلتفرمهای iOS و Android به صورت تخصصی سفارشی سازی و حتی ساخت و توسعهٔ اپلیکیشنهای ایرانی تمرکز دارند که جدیداً به لطف آگاهی از فریموُرکهایی مانند Qt به سمت این حوزه آمده و نیازمند سی++ کاران هستند. شرکتهای بازیسازی کشور ما که این سالها با پیشرفتهای خوبی مواجه شدهاند به دنبال برنامهنویسان سی++ هستند که بتوانند در این صنعت برای فرهنگسازی و توسعه صنعت بازی سازی جلو بروند. بسیاری از شرکتهای پنهان وجود دارد که به صورت بسیار مخفیانه در صنایع سهبعدی و پیشرفته در حال فعالیت هستند که محصولات خود را نه در ایران بلکه در خارج از آن آمریکا و دیگر کشورهای اروپایی به فروش میرسانند که به سفارش آنها بوده است. با دید سطحی به این مسائل نباید نگاه کنید، اگر آگهیهای استخدامی نمیبینید به خاطر این است که این زبان کار کُن می خواهد نه تَنبل! بنابراین شما باید به سراغ آن بروید چرا که بسیاری از شرکتهای بینالمللی فعالیتهای بزرگی انجام میدهند که هیچوقت از آنها خبر ندارید و به صورت کاملاً سفارشی و حساسیت کامل به دنبال برنامهنویسان این زبان هستند (چون میدانند یک سی++ کار هدفمند و با دید بازتری به توسعه نگاه میکند). چنین شرکتها معمولاً استخدام را به صورت رابطهای انجام میدهند و تعداشان هم کم نیست. ما میدانیم که شاید شما با دیدگاه اینکه حتماً باید نرمافزارهای کاربردی تولید کنید به قضیه نگاه میکنید، خوشبختانه فریمورک کیوت به قدری قدرتمند و پُخته شده است که میتوان هر محصول کاربردی در هر زمینهای را تولید کرد که از کارایی بسیار بهتری نسبت به دات نت بهرهمند است. در حوزهٔ امنیت، شبکه و موارد این چنینی شرکتهای بزرگ و Ispها نیازمند این زبان هستند. البته دلایل بسیاری وجود دارد که موجب میشود شرکتها از روی ناچاری به سراغ برنامهنویسان دیگر بروند، که من شخصاً آن را تجربه کرده ام ! در بسیاری از پروژهها که به عنوان مشاور فنی در آنها شرکت کرده بودیم متوجه آن شدیم شرکتها به خاطر عدم وجود برنامهنویس سی++ برای ادامهٔ چرخهٔ تولید خود مجبوراً سراغ برنامهنویسهای دیگر زبانها میروند. این امر به خاطر این است که واقعاً درصد تعداد برنامهنویسان این زبان نسبت به زبانهای دیگر به خاطر (راحت طلبی) و شاید عدم آگاهی از این زبان دور هستند. یکی از نکتههایی که اخیراً جالب بوده است، آن است که شما به واسطهٔ سیپلاسپلاس میتوانید حتی وبسایتهای مورد نیاز خود را بسازید! یک سیستم چند-منظوره طراحی کنید که در حوزههای قابل استفاده باشد. برخی از هماهنگیهایی که این زبان خود را به بهروز رسانیهای بسیار سریع در فناوری وفق داده است، پشتیبانی از ساختارهای چند-سکویی و کاملاً بومی با کارآیی بالا است که در حوزههای موبایل، دسکتاپ و وب میتوانید آن را مورد استفاده قرار دهید. از فناوریهای مربوط به فریمورکهای طراحی گرفته، تا امکان ساختوساز در قالب وباسمبلی، بلاکچین و دیگر موارد. یک نکتهٔ بسیار مهم که طی این سالها تجربه کردهام، این است که خیلی از شرکتها و خدمات دهندهها با این که در جریان مزایای این زبان هستند، مجبوراً به خاطر عدم وجود متخصص کافی از ابزارهای دیگر برای توسعهٔ کار خود استفاده میکنند. هرچند مشکلات این زبان تا به الآن شفاف شده است، اما بهروز رسانیها و توسعههای پی در پی آن موجب بهبودهای بسیار چشمگیری در آن نیز شدهاست. برخی از سوالاتی که علاقهمندان به این حوزه میپرسند در ادامه آمده است: من یک دانشجو هستم و رشتهٔ تحصیلی من کامپیوتر است، به برنامهنویسی با ++C علاقه دارم از کجا باید شروع کنم؟ اگر شما به قصدِ حرفهای شدن دنبال یادگیری این زبان هستید، همانطور که اشارهای شد مباحث پیش نیاز برای یادگیری این زبان مهم هستند و برای درک هرچه بیشتر این زبان بهتر است دانش خوبی در زمینهٔ تجزیه و تحلیل رفتار کامپایلر داشته باشید. علاوه بر این برای آشنایی با کامپایلر رفتار سیستمعامل و واکنشهای کامپایلری در سیستمعاملهای متفاوت بسیار مهم است. به عنوان مثال کامپایلر GCC بر روی ایستگاههای یونیکس تعبیه شده و برای خود قوانین و استانداردهایی را دارد. در کنار آن کامپایلر MSVC نوعی کامپایلر اختصاصی تحت ویندوز است که متناسب با ساختار و معماری ویندوز رفتار میکند. در نگاه اول آشنایی با آنها شاید الزامی به نظر نرسد، چرا که شما صرفاً به سمت یادگیری زبان، نحو (سینتکس)، ویژگیها، کتابخانهٔ پیشفرض و هستهٔ آن میپردازید. اما در بُعد ساخت و ساز یک محصول عالی اطلاعات شما در زمینههای مختلف لازم است کافی باشد. من یک دانشجو هستم اما متاسفانه رشتهٔ تحصیلی من کامپیوتر نیست، به برنامهنویسی با ++C علاقه دارم از کجا باید شروع کنم؟ این کار کمی دشوار است، در مرحلهٔ اول پیشنهاد ما این است که سراغ زبانهای برنامهنویسی دیگری بروید که نیازی نداشته باشد شما درگیر درک کامپایلر یا رفتارهای سیستمعاملی شوید. اما به هر حال اگر شما به هر نحوی میخواهید این زبان را یاد بگیرید چارهٔ کار تلاش مستمر و حوصله است. متاسفانه سیپلاسپلاس ذاتی مرموز دارد و آن این است که اگر بتوانید به آن مسلط شوید یک زبان با وفا و قدرتمندی خواهد بود که در هر زمینهای به نیازهای شما پاسخگو خواهد شد. اما اگر به هر دلیلی نتوانید با این زبان دوست شوید به طور بسیار مرموزی اعصابتان را به هم خواهد ریخت ? که البته طبیعی است چون سی++ تحت کامپایلرهای خود دستِ برنامهنویس را آزاد گذاشته و شما هستید که انتخاب میکنید کُد شما به چه شیوهای با توجه به هدف چگونه عمل کند. چقدر زمان لازم است تا من این زبان برنامهنویسی را یاد بگیرم؟ با توجه به ساختار زبان و رفتارهای کامپایلر میتوان گفت به قدری دامنهٔ سی++ گسترده است که تنها راه حل ممکن برای رسیدن به یک وضعیت مطلوب از دانش مرتبط با آن باید زمان مشخصی در نظر گرفته شود. ممکن است شما بتوانید در بازهٔ ۱ الی ۳ ماه مباحث مقدماتی این زبان را درک کنید. اما توجه داشته باشید پیشنیازات آن نیز نیازمند تحقیق، تجربه عملی و نتیجهگیری تئوری و علمی هستند. با توجه به اینکه شما (سریع، هوشمند با گیرایی بالا باشید) میتوانید در کمتر از ۶ ماه به یک پایداری تقریباً قابل قبول در حد مقدماتی این زبان برسید. استاندارد زبان را درک کنید و نحوهٔ برقراری ارتباط با کتابخانههای پیشفرض STL و غیره را تجربه کنید. برای کسب دانش و افزایش آن به میزان متوسط و به بالا نیازمند تلاش بسیار بیشتری خواهید بود که باید در قالب پروژههای عملی و واقعی صورت گیرد. متاسفانه سی++ به دلیل گسترده بودن چنان پیچیدگیهایی را دارد که تنها میتوان در موقع برنامهنویسی به صورت عملی (بر روی پروژههای واقعی) آن را تجربه کرد. آیا ارزش دارد من این زبان را یاد بگیرم؟ فرصت من کم است و میخواهم سریعاً به درآمدزایی برسم در همین ابتدا به شما میگویم که اگر صرفاً به درآمدزایی سریع فکر میکنید، سیپلاسپلاس گزینهٔ مناسبی برای این رویا نیست! اگر شما به عنوان یک برنامهنویس متوسط و به بالا به این زبان تسلط دارید، و حداقل میتوانید با یکی از کتابخانههای خوب آن ارتباط برقرار کنید، وقت آن است که با کتابخانههای قدرتمند این زبان وارد عمل شوید. کتابخانههایی مانند Boost، Poco، Qt و غیره از سری کتابخانههایی میباشد که امکانات بسیاری را در اختیار شما علاقهمندان این زبان قرار میدهند تا بتوانید در کمترین زمان ممکن به نیازهای خود دسترسی داشته و آن را پیاده سازی کنید. همهٔ آنها در ساخت و توسعهٔ محصول به شما کمک میکنند. فراموش نکنید که بارها گفتهام به زبانها، کتابخانهها و فناوریها به عنوان ابزار در داخل جعبهابزار خود بنگرید. توجه داشته باشید که لازمهٔ طراحی و توسعه یک محصول مفید (قابل قبول) در قالب MVP (کمینه محصول پذیرفتنی) مستلزم داشتن دانش طراحی محصول نیز میباشد. اما همه چیز اینگونه خلاصه نشده است و شما برای اینکه بتوانید یک محصول واقعاً قابل قبول را پیاده سازی کنید مسلماً باید آن را مجهز به قابلیتهای دیگری مانند منابع ذخیره داده و یا سرویسها و ماژولهایی کنید که بتواند به عنوان یک محصول کاربردی روی آن حساب کرد. آیا صرفاً با دانستن زبانهای برنامهنویسی و تسلط بر آن میتواند یک محصول استاندارد و سطح جهانی را به طور کامل تولید کرد؟ نظر من قطعاً خیر است! اگر شما واقعاً با دیدگاه یک سازنده، یک تولید کننده و مهندس تمام عیار در ذهن خود رویا پروری میکنید، در این صورت باید بدانید همه چیز در زبان خلاصه نمیشود! از نظر من حداقل مواردی که (به طور خیلی خیلی خلاصه و محدود) نیاز است تا یک متخصص بتواند پاسخگوی تصمیمگیری نقشهٔ توسعهٔ یک محصول برای مشتری در ابعاد مختلف و سطوح متفاوت از حوزههای موجود در قالب اصولی باشد به صورت زیر است که فرد یا یک تیم باید به آنها اشراف کافی داشته باشد: ۱- آشنا مبانی کامپیوتر که امر طبیعی (شامل درک و فهم مسائل و نحوهٔ حلشون متناسب با پلتفرم اجرایی محصول) ۲- آشنا به ساختار نوع محصول استاندارد در یک حوزه مثل: وب، آیاواس، اندروید یا دسکتاپهای مختلف مثل لینوکس، مک و ویندوز، اینترنت اشیاء و دیگر موارد. ۳- آشنا به فلسفهٔ بکاند و فرانتاند یا ترکیبی از این دو به همراه ابزارهای مناسب. ۴- آشنا به اصول طراحی UI/UX به عنوان یک نیاز و یک فاکتور مهم در ساخت محصولی که وابسته به عملکرد کاربر دارد و در حوزهٔ فرانتاند مهم و کاربردی هست. ۵- آشنا به اصول SOLID و امثالش مهم هستند. ۶- آشنا اصول برنامهریزی ساخت بانک اطلاعاتی، اینکه از چه بانک اطلاعاتیای استفاده کنی و چرا؟ ۷- آشنا به ارتباطات دادهای، جداول و ارتباط بین فیلدها، جداول و روشهای درست تبادل اطلاعات مابینی دادهها. ۸- آشنا و تسلط کافی به یک محیط توسعه و ادغام ابزارها و محیط طراحی برای هدف. ۹- آشنا به معماری ساختار و رابطهای برنامهنویسی (Api) ۱۰- آشنا به استانداردهای Http، درک و مدیریت درخواست، پاسخها و ... ۱۱- آشنا به الگوهای طراحی برنامهنویسی (DP) ۱۲- آشنا به روشهای نگهداری و آزمایش نرمافزار و کدها به خصوص درک مبحث Fault tolerance. ۱۳- آشنا به روشهای اطمینانسازی و ایمنسازی پردازشهای داخلی نرمافزار برای جلوگیری یا دشوار سازی نفوز و خرابکاری. ۱۴- آشنا به روشها و معماریهای احراز هویت و نحوهٔ ادغامش با نرمافزار مثل:JWT, OAuth, AWS و غیره... ۱۵- آشنا به نوع پارادایمهای زبان برنامهنویسی، در قالبهای (دستوری) Imperative و (اعلانی) Declarative مثل OOP، functional و دیگر موارد. ۱۶- آشنا به سبک معماری نرمافزاری (Microservice یا مثلاً Monolith) مزایا و معایب آنها. ۱۷- آشنا به سبک معماری طراحی مانند MVC در طراحی بدنهٔ محصول. ۱۸- آشنا به سبک و الگوهای طراحی ساختاری در بکاند مانند Builder، Abstract، Factory و غیره. ۱۹- آشنا به ساختار یک زبان (در صورتی که میخواهید جوابگوی مسائلِ پیش آمده باشید) کالبدشکافی زیرپوستی و عمیق یک زبان مهم است. ۲۰- آشنا و درک کامپایلرها و مفسرها، تفاوتها و شیوههای عملکردیشون نسبت به کدهای بهینه شده و عادی. ۲۱- آشنا و درک مدلهای مختلفی از سیستمهای توزیع شده مثل IaaS، PaaS، SaaS یا FaaS. ۲۲- آشنا به ابزارهای ساخت و فرآیند کاری اونها مثل CMake، NMake، QMake و غیره. ۲۳- آشنا به روشهای مدیریت وابستگیهای نرمافزار و ابزارهای لازم برای بستهبندی بهتر خروجی. ۲۴- آشنا به روشهای کدنویسی قابل آزمایش (Unit Test) و استفاده از ابزارهایی مثل CTest, GTest, Catch2 و غیره. ۲۵- آشنا به توسعهٔ آزمون محور (Test Driven- Development) ۲۶- آشنا به گامها و شرایط نسخهنگاری و مراحل توسعهٔ نرمافزار (SDP) ۲۷- آشنا به روشهای امنیت در کد و توسعه به شیوههای بررسی از طریق Fuzz-Test، Sanitizer، آنالیزرهای پویا و ایستا و غیره... ۲۸-آشنا به قوائد طراحی بر پایهٔ خدمات مبتدی بر معماری ابری برای خدمات پیامی، وبسرویسها، پردازش و غیره. ۲۹- در سطوح وب آشنا به مکانیزم شاخص بندی، فاکتورهای SEO و شیوههای درست بهبود صفحات وب. ۳۰- آشنا به روشهای به کار گیری و پیادهسازی ثبت کنندهٔ وقایع در دل محصول و روشهای بازخورد برای توسعهٔ بهتر به همراه مانیتورینگ، نظارت و تریسینگ. ۳۱- در شرایط لزوم آشنا به نحوهٔ به کار گیری و دلیل استفاده از فناوریهایی مثل Redis، Memcached و غیره. ۳۲- آشنا و درک صحیح از مفاهیم همزمانی (Concurrency) و روشهای به کار گیری آن نسبت به زبان برنامهنویسی و شرایط مناسب استفاده. ۳۳- آشنا به سبک و قوائد و ساختار زبانهای برنامهنویسی و فرآیند ساخت و ترجمه. ۳۴- و تا صدها گزینهٔ دیگر که میتوان در این بخش لیست کرد که اگر انتخاب شما زبانهای نزدیک به سیستم باشد این داستان در ادامهٔ این توضیحات سر به فلک خواهد کشید. با توجه به این موارد اگر بخواهید محصولی را بسازید که طبق استاندارد آن را توسعه و تولید کنید که در بستر سیپلاسپلاس شکل میگیرد، باید ابزارها و موارد پیشنهادی زیر را در اختیار داشته باشید و کار با آنها را تا حد نیاز بدانید: یک محیط توسعه یکپارچهٔ نرمافزار مانند Qt Creator، Xcode یا Visual Studio (پیشنهاد ما Qt Creator است) این محیط به عنوان IDE نیز یاد میشود. پلتفرم توسعه (سیستمعاملی) که قرار است محیط توسعهٔ یکپارچه خود را بر روی آن نصب و شروع به برنامهنویسی کنید را مشخص نمایید. اگر شما کاربر ویندوز هستید باید محیط توسعهٔ یکپارچهٔ شما مجهز به کامپایلر MSVC و یا نسخهٔ پورت شدهٔ GCC یعنی MinGW باشد. اگر شما کاربر مکاواِس هستید به صورت پیشفرض با نصب محیط توسعه کامپایلر Clang بر روی آن تعبیه خواهد شد. البته میتوانید به صورت سفارشی از کامپایلر GCC نیز استفاده کنید. در صورتی که کاربر لینوکس هستید کامپایلر GCC به صورت پیشفرض بر روی محیط توسعهی شما تعبیه خواهد شد. آشنا به دستورات ترمینال و یا کنسول در سیستمعاملهای لینوکس، مک و ویندوز در ساخت و سازهای دستوری مفید هستند و نیاز است آنها را بدانید. آشنا به Git و دستورات مربوط به آن در نگهداری و به اشتراکگذاری مخازن پروژه میتواند برای شما سودمند باشد. بر اساس پیشنها جهت محیط توسعه کتابخانهٔ Qt نیز پیشنهاد میشود (دلیل آن این است که این کتابخانه به شما کمک میکند تا بتوانید رابط کاربری نرمافزار (محصول) خود را پیاده سازی کنید). اگر هدف شما طراحی یک محصول استانداردی است که از شکل و ظاهر آنچنانی برخوردارد نیست بهتر است از ماژولهای پیشفرض Qt مانند Qt Widget برای طراحی آن استفاده کنید. این کار بسیار ساده است و نیازی برای داشتن دانش در رابطه با حوزههای JavaScript و QML ندارد. البته میتوانید با ترکیب CSS طراحی رابط کاربری برنامهٔ خود را بهبود ببخشید. بعد از این موارد نیاز است که شما هدف توسعهٔ خود را مشخص کنید، اینکه میخواهید توسعه دهندهٔ چه پلتفرمی باشید؟ تولید کننده برنامههای دسکتاپ بر روی ویندوز؟ یا لینوکس و مک؟ یا همهٔ آنها؟ خوشبختانه با توجه به قابلیتهای ذاتی سی++ و کیوت شما میتوانید برنامهٔ خود را تنها با داشتن محیط توسعهٔ خود بر روی پلتفرم مورد نظر خود کامپایل و خروجی بگیرید (البته به شرط اینکه از سرویسهای اختصاصی سیستمعاملی) استفاده نکرده باشید. البته دقت کنید اگر شما توسعهدهندهٔ اختصاصی برای فقط یک سیستمعامل خواهید بود، در این صورت نیازی به یادگیری مفاهیم یا رابطهای اختصاصی برنامهنویسی یک پلتفرم دیگر نخواهید بود. اگر مشتاق آن هستید که برای پلتفرمهای موبایل مانند آیاواس یا اندروید برنامه تولید کنید، موضوع کمی گستردهتر خواهد شد و حتماً باید ملزوماتی که در ابتدای مقاله به آن اشاره شده است را در نظر داشته باشید. برای مثال تولید یک نرمافزار iOS مستلزم آن است که شما علاوه بر داشتن دانش سی++ در رابطه با معماری و ساختار و همچنین قوانین، قوائد و ساختار نرمافزارهای مرتبط با اپل راداشته باشید. در Android نیز این چنین است. اگر شما تازه کار هستید پیشنهاد میکنیم هدف خود را فعلاً محدود بر یک پلتفرم خاص کنید، حتماً نیاز نیست اطلاعات خود را کامل و سپس اقدام کنید. برای مثال توسعه محصول بر روی ویندوز برای آغاز کار بسیار مناسب است و شما صرفاً بر روی این پلتفرم متمرکز خواهید بود. در نهایت شما محصول خود را با آزمایش وخطاهای بسیاری میتوانید تولید و با توجه به مستنداتی که در همین مرجع ارائه شده اس مستقر و برای کاربر نهایی ارائه کنید. برای اینکه بدانید مزایای این زبان در چیست و چه کتابخانههایی میتوانند مفید باشد و برخی از سوالات احتمالی که ممکن است به ذهن شما برسد این بخش را مطالعه کنید. برای نحوهٔ شروع کار با Qt این بخش را مطالعه کنید. جهت نحوهٔ نصب و راه اندازی محیط توسعه این بخش را مطالعه کنید. منابع فارسی یا زبان اصلی؟ پاسخ این سوأل بدون شک راحت است! زبان انگلیسی، زبان علم است، بنابراین هر آنچه که شما در زبانهای بومی و غیر انگلیسی مطالبه میکنید، ممکن است با محدودیتهای شدیدی مواجه شوید. بنابراین برای یادگیری محتوای علمی به شدت توصیه میشود به کمک مراجع انگلیسی آن را بیاموزید! من زبانم ضعیف هست، آیا باید به زبان انگلیسی تسلط کافی داشه باشم تا بتوانم زبانهای برنامهنویسی را یاد بگیرم؟ این یکی از سوألهای بسیار پر تکرار است که بارها با آن مواجه میشویم! در پاسخ باید صادقانه بگویم، شما به حداقلهای زبان انگلیسی واقعاً نیاز دارید! در حد این که متنهای عادی را بخوانید، آنها را متوجه باشید و بر اساس نگارش معنای صحیح جمله و واژهها را درک کنید. رفته رفته به آن عادت خواهید کرد و در آن نیز حرفهای خواهید شد. اما فراموش نکنید که زبانآموزی در کنار برنامهنویسی از لزومات است. در مورد واژههای تخصصی هم نگران نباشید، معمولاً واژههایی که معنای آنها را مابین جملات و کتابها نمیدانید، در مراجع و یا پانویسهای آنها تعریف میکنند. بسیاری از واژهها در قالب یک روش، مفهوم یا اصطلاح عنوان میشوند و شما باید به دنبال تعریف کامل آن باشید. به عنوان مثل، اصطلاح RAII در سیپلاسپلاس که به برخی از آنها در این بخش اشاره کردهام. من سن پایینی ندارم، آیا برای شروع کردن برای یادگیری سیپلاسپلاس دیر است؟ شاید من تجربهٔ سنیِ کافی، نسبت به کسانی که این سوأل را میپرسند نداشته باشم، اما نسبت به تجربهای که در مهندسی کامپیوتر و به خصوص ساختوساز و توسعهٔ محصولات نرمافزاری دارم، میتوانم به جرأت بگویم که این یک دغدغهٔ ذهنیای به حساب میآید که شاید در قالب و جنسِ ترسِ بیهوده از دست دادن زمان را به خود بگیرید. اما واقعیت آن است، تا زمانی که شما شروع نکنید، بله نمیتوانید! اما نکتهای که مد نظرم است بدانید، این است که در انتخاب زبانها، به خصوصی یادگیری سیپلاسپلاس، بهتر است بخشی از هدف و استعدادی که به آن دارید را هدف قرار دهید، (هدف مشخص و شفافی داشته باشید) چون خاصیت این زبان در چند-منظوره بودن آن است، و ممکن است شما را وسوسهٔ خود در همهٔ جوانب کند! که این باعث میشود شما هرگز به یک نقطهٔ شروع نرسید. به عنوان مثال، برای شروع بهتر است یک حوزه را انتخاب کنید و پیشبرورید، مانند: برنامهنویسی و طراحی اپلیکیشن در سیستمعامل ویندوز. یا برنامهنویسی در حوزهٔ موبایل، وب، بازیسازی، امبدها (سیستمهای درونسازی شده) و غیره... این بستگی به سلیقهٔ شما و نوع نیازی که در بازار میبینید خواهد داشت. در زیر منابعی را معرفی میکنم که به رایگان یا با کمترین هزینه میتوانید به آنها دسترسی داشته باشید: منابع استاندارد و رسمی زبان سیپلاسپلاس: https://en.cppreference.com https://isocpp.org برای یادگیری در سطوح مقدماتی وبسایتهای زیر پیشنهادات مناسبی هستند: https://www.geeksforgeeks.org/references-in-c http://www.cplusplus.com/reference https://www.tutorialspoint.com/cplusplus/cpp_references.htm https://www.learncpp.com در صورتی که میخواهید در حالت بسیار ساده، تصویری و در قالب برگههای تقلب به ویژگیهای زبان و کتابخانههای آن بپردازید، وبسایت زیر یک نمونه بسیار مناسب است: https://hackingcpp.com توجه کنید که خیلی از مباحث در وبسایتها ذکر نمیشود، نیاز است بعضی از کتابها را در نظر بگیرید و آنها را عمیقاً مطالعه کنید، بنابراین برای مطالعه به ترتیب سطح مقدماتی و پیشرفته را در زیر عنوان میکنم: Beginning C++ Programming Beginning C++20 A Tour of C++ The C++ Programming Language C++ Primer Programming: Principles and Practice Using C++ کتابهای معرفی شده به استانداردهای ۱۱، ۱۴، ۱۷ و ۲۰ اشاره میکنند. کتابهای پیشنهادی برای سطح پیشرفته: Effective C++ Professional C++ C++ Templates: The Complete Guide – Second Edition Modern C++ Programming Cookbook Hands-On System Programming with C++۱۷ C++ High Performance Optimized C++ در صورتی که نیاز به کسب دانش بیشتر در حوزهٔ سطح پایین، سختافزار، معماری و ساختارهای نرمافزاری دارید کتابهای زیر بسیار مفید هستند: Computer Organization & Design RISC-V / ARM / MIPS / x86 Software Architecture with C++ اگر به دنبال مشاورهها، منابع یا مقالات و توصیههای فارسی یا انگلیسی من هستید، پیشنهاد میکنم در همین وبسایت، یوتیوب، گیتهاب و یا کانال تلگرامی من ملحق بشید. من هر جا که باشم، با شناسهٔ KambizAsadzadeh اگر در حد توانم باشد شما را راهنمایی خواهم کرد.
-
10 امتیازبا سلام، در این پست ما قصد داریم در رابطه با نحوهٔ آغاز یادگیری کیوت توضیح دهیم. اینکه به عنوان یک تازهکار چه پیشنیازاتی را باید مطالعه و در نهایت چگونه و تحتِ چه منابعی این کتابخانهٔ قدرتمند را بیاموزیم. همچنین پاسخ برخی از سوالات شما را در این پُست به طور شفاف ارائه شده است که طیِ چندین سال سوال علاقه مندان بودهاند. معرفی سریع و سادهٔ کیوت (Qt) این ابزار (به انگلیسی: Qt) با آوای «Cute» به فارسی (کیوت) مجموعهای از کتابخانهها و سرآیندهای نوشتهشده به زبان سی++ است که به برنامهنویس امکان توسعه آسان نرمافزارهای کاربردی را میدهد. کیوت شامل چندین کلاس برای کار با واسط گرافیکی، چندرسانه، ابزارهای پایگاهداده، شبکه و … است. نرمافزارهای نوشته شده با ابزار کیوت قادرند تا با استفاده از یک کامپایلر زبان سیپلاسپلاس برای طیف وسیعی از سیستمعاملها از جمله گنو/لینوکس (نسخههای رومیزی و وسیلههای قابل حمل)، ویندوز، ویندوز CE، مکاواس و … همگردانی شوند. بدین ترتیب حمل نرمافزار نوشته شده بدون تغییر در متن کد نوشته شده امکانپذیر است. از کیوت در زبانهای برنامهنویسی متعددی مانند سی++ و جاوا و پایتون میتوان استفادهکرد. پیشنیازات برای یادگیری کتابخانه Qt دانش متوسط و به بالا در رابطه با زبان برنامهنویسی مُدرن سیپلاسپلاس نسخههای ۱۱ به بعد، (بنابراین اگر شما هیچ اطلاعی در رابطه با ساختار برنامههای سیپلاسپلاس و نحوهٔ عملکرد آن ندارید، شانس موفقیت شما بسیار پایین خواهد بود و ممکن است برنامهٔ تولید شدهٔ شما به بدترین شکل ممکن پیاده سازی شود و حتی مدام دست به کمک دیگران باشید). من پیشنهاد میکنم قبل از آن با زبان سیپلاسپلاس آشنا شوید. آشنایی با کامپایلر و نحوهٔ عملکرد آن در پلتفرمهای مختلف از جمله ویندوز، مکاواِس، لینوکس، اندروید و آیاواِس. مهم است بدانید تسلط کافی در زبان سی++ و ساختار برنامههای نوشته شده در این زبان بسیار موثر است. آشنایی و تسلط کافی به ابزارهای ساخت و ساز مانند CMake یا QMake و QBS. آشنایی با معماریهای مختلف مانند x86، x86-64، Arm و غیره... و پیکربندی پروژه و تهیهٔ خروجی. آشنایی با معماریِ سیستمعاملها، برخی از رابطهای برنامهنویسی (Api)، برای مثال اگر قرار است از خاصیت چند-سکویی کیوت استفاده کنید تا یک برنامهٔ تحت اندروید را توسعه دهید، در این صورت باید در نظر داشته باشید که همه چیز توسط کیوت حاضر و آماده نیست، شما بدون درکِ معماری سیستمعامل اندروید و پیکربندی برنامه در مراحل توسعه نمیتوانید به راحتی از پسِ این کار بر آیید و هر از گاهی نیاز است به شیوهٔ اختصاصی پلتفرم مورد نظر برنامهٔ خود را توسعه دهید. در پلتفرمهای اپل نیز تسلط کافی به Xcode و مدیریت حساب توسعه در Apple Developer مورد نیاز است، شما باید بدانید چطور یک پروفایل را برای پلتفرم آیاواس باید تنظیم کنید. اگر شما در پلتفرمهای مختلف کار میکنید، قطعاً نیاز به کار با کیتهای توسعه، رابطهای توسعه و همچنین ابزارهای ساخت هر پلتفرم خواهید داشت. بنابراین، در محیط ویندوز نیاز دارید محیط خود را با ابزارهای ساخت و ساز آن مانند Microsoft Visual Studio Build Tools که شامل کامپایلرها، دیباگر و برخی از ابزارهای برنامهنویسی است هماهنگ کنید، چرا که بدون آن امکان توسعه وجود ندارد (نیاز نیست نرمافزار محیط توسعهٔ یکپارچهٔ Visual Studio را نصب کنید، همان ابزار Build Tools کافی است). در محیط لینوکس نصب پیشنیازها و کامپایلرهای GCC و یا Clang مهم است و در مک نیز بهروز رسانی و نصب ابزارهای ساخت و ساز و همچنین نسخهٔ کامل Xcode از واجبات توسعه در کیوت خواهد بود. بنابراین داشتن تجربه و آشنایی کافی با این ابزارها متوسط به بالا به نفع شماست. آشنایی با اصطلاحات و مفاهیم تجربهکاربری و رابطکاربری جهت طراحی مناسب با فناوریهای Qt Widget و Qt Quick (در صورتی که علاقهمند به طراحی ظاهر برنامههای خلاقانه دارید). آشنایی Xml برای سبک سنتی و ویجت و JavaScript پیشنیاز خوبی برای درک مسائل مربوط به فناوری طراحی در کیوتکوئیک است که تحت QML رابطهای کاربری و اجزای مختلف و خلاقانه را پیاده سازی خواهید کرد. توجه کنید که مستندات کیوت به اندازهٔ کافی جهت آشنایی با پیشنیازات بهروز رسانی میشود و نسبت به نسخههای ۵ و حتی ۶ توضیحات لازم را ارائه میکند. با توجه به این مسائل، مراحل نصب و داشتن حساب کاربری در کیوت لازم است، اما به این معنا هم نیست که شما از نسخهٔ رایگان نمیتوانید استفاده کنید، توجه داشته باشید که تنها تفاوت بین نسخهٔ رایگان و تجاری در یک سری ویژگیهای اختصاصی شرکت کیوت است که در پشتیبانی از آنها اعمال شده و نه بیشتر. آیا کیوت یک زبان برنامهنویسی است؟ چرا نحوِ (Syntax) آن با سیپلاسپلاس استاندارد فرق میکند؟ خیر، کیوت ابتدا به عنوان یک کتابخانهٔ رابط گرافیکی کاربر توسعه داده شده است که بعدها برای توسعه اهدافِ بیشتری شامل کتابخانههای شبکه و غیره شده است که در قالب یک چهارچوب (فریموُرک) که تحت زبان برنامهنویسی سیپلاسپلاس برای این زبان توسعه یافته است و در زمینههای مختلفی کاربردهای فراوان دارد. دلیل زیبایی و ظاهر سادهٔ آن ساختار بسیار قدرتمند آن است که موجب شده همانند چهارچوبهای قدرتمند دیگری خودنمایی کند. (اما قول این ظاهر و سادگی آن را نخورید، چون با سیپلاسپلاس طرف هستیم) آیا کیوت از سرویسها و قابلیتهای اختصاصیِ اپلیکیشنهای اندروید و آیاواِس را به طور کامل پشتیبانی میکند؟ به صورت پیشفرض خیر، هیچ ابزاری به صورت چند-سکویی فعلاً (تاکید میکنیم - فعلاً تا به این تاریخ) وجود ندارد که تمامی امکانات اختصاصی این پلتفرمها را بدون کد نویسی اختصاصی پشتیبانی کند. اما این به این معنی نیست که جواب منفی خواهد بود، لذا شما در برنامهنویسی سیپلاسپلاس به راحتی میتوانید برای پلتفرمهای فوق با سرویسهای آنها ارتباط برقرار کنید. این کار کمی نیاز به دانش فنی بالایی خواهد داشت! برای مثال (دسترسی به سرویسهای اندروید یا آیاواس) با ترکیب کُدهای آبجکتیو-سی و جاوا امکانپذیر است و یا باید با توجه به SDKهای پلتفرمهای مورد نظر آنها را سفارشی نویسی کنید. این کار به راحتی قابل انجام خواهد بود و کافی است شما در رابطه با نحوهٔ ترکیب کُدهای آن آشنا باشید. کیفیت خروجی برنامههای تحت کیوت چگونه است؟ اگر شما واقعاً یک برنامهنویسِ ماهرِ سیپلاسپلاس باشید میتوانید برنامهای را تولید کنید که بسیار خوش دستتر و سریعتر از برنامههای پیشفرضِ پلتفرمها باشد. در بارهٔ دلایل آن به ساختار برنامههای نوشته شده توسط این زبان به این مقاله مراجعه کنید. اگر غیر از این باشد برنامهٔ شما بسیار بد و کُند عمل خواهد کرد و بهتر است سراغ زبانهای پیشنهادی (هر پلتفرم) بروید. هرچند سیپلاسپلاس یک زبان بومی برای تمامی پلتفرمها محسوب میشود اما این ریسک برای افراد مبتدی پیشنهاد نمیشود. معمولاً برنامههای گسترده و عظیم توسط سیپلاسپلاس توسعه داده میشوند که برنامهنویسان آن واقعا حرفهای و با قوانین این زبان آشنا هستند. آیا برای تولید برنامههای مک و آیاواس نیاز به سیستم خاصی داریم؟ بله، شما بدون وجود سیستمعامل مک نمیتوانید برنامهای را بر روی دستگاههای اپِل کامپایل کنید. این امر مستلزمِ سیستم عامل اختصاصی این شرکت بوده و باید توسعه دهنده دارای حساب کاربری معتبر سالانه باشد تا بتواند برنامهٔ خود را بر روی دستگاههای مورد نظر اجرا کند. در غیر این صورت تنها میتواند برنامهٔ خود را بر روی سیستم خود مورد آزمایش و خطا قرار دهد. آیا کیوت در ایران بازار کار مناسبی دارد، آیا ارزش دارد من این کتابخانه را یاد بگیرم؟ خوشبختانه کیوت بیشتر از ۲۰ سال است که در دنیا مورد استفاده قرار میگیرد و کشورهای پیشرفته از آن استقبال میکنند. در کشور ما مدتی است این کتابخانه مورد استقبال قرار گرفته و بسیاری از شرکتها مایل به ساخت و توسعهٔ برنامههای خود تحت این کتابخانه هستند که برخی از دلایل آن (بهره بردن از قابلیتهای زبان سی و سیپلاسپلاس و ویژگیهای خاص آن است). از طرفی کیوت به عنوان یک کتابخانهٔ چندسکویی، مناسب برای تولید و توسعهٔ محصولات در قالب اپلیکیشنهای موبایل و برنامههای کاربردی بر روی دسکتاپ است که در نوع خود کم نظیر است. استفاده از این کتابخانه، موجب سهولت و افزایش سرعت توسعهٔ تولید و طراحی نرمافزار میشود و شما میتوانید با توجه به حفظ کیفی کدهای خود از یک محیط مجهز به ابزارهای طراحی پیشرفته استفاده کنید. پشتیبانی بسیار خوب از زبان فارسی و به خصوص تاریخ شمسی و دیگر موارد، طراحی به شیوهٔ استاندارد راست به چپ و رعایت اصول در آن یکی از دلایلی است که میتوان تضمین کرد کیوت یک ابزار مناسب در طراحی و توسعهٔ برنامههای بومی به زبان فارسی است. چه کسانی یا شرکتهایی از این فریمورک استفاده میکنند؟ جالب است بدانید کتابخانهٔ کیوت محدود به فرد یا شرکت خاصی نیست، با توجه به دو نسخهٔ تجاری و رایگان آن، شرکتهای خصوصی، افراد و توسعهدهندگان بسیار هستند که از آن به عنوان یک فریمورک طراحی و تولید برنامه استفاده میکنند. معمولاً شرکتهای توسعهدهندهٔ تجهیزات سختافزاری، پزشکی، رباتیک، صنعتی و دیگر موارد از آن استفاده میکنند. همچنین بازار طراحی نرمافزارهای هوشمند موبایل، نرمافزارهای کاربردی و پرکاربرد از این کتابخانه استفاده میکنند. اما تبلیغات در این زمینه به دلیل عدم شناخت، تسلط و آشنایی به سی++ نسبت به دیگر ابزارها کمتر است. درآمد و هزینههایی که میتوان از انجام پروژههای کیوت دریافت کرد چگونه است؟ به طور کلی نمیتوان در مورد یک تعرفهٔ مشخص صحبت کرد، این بستگی به نوع مهارت شخصی و کیفیت کار دارد. اما در این مقاله میتوان به این اشاره کرد که برنامهنویسی سی++ و کیوت یکی از خوش درآمدترین مباحثی هستند که میتوان به آن اشاره کرد که البته بستگی به مهارت و تسلط کافی توسعهدهنده دارد. آیا کیوت از سکوی وِب پشتیبانی میکند؟ کیوت از تمامی پلتفرمها پشتیبانی میکند، مخصوصاً با پشتیبانی از ماژولهای QtWebEngine و QtWebAssembly این امر امکانپذیر است که برنامههای خود را تحت فناوریهای وِب نیز توسعه دهید. آیا من حتماً باید به زبان سیپلاسپلاس مسلط باشم؟ هرچند زبان سی++ یکی از الزامات کیوت است، اما همانطور که اشاره شد، آشنایی با هسته، کتابخانهٔ پیشفرض، سینتکس و روشهای برنامهنویسی رایج آن برای درکِ بهتر کیوت مهم هستند. من دانشجو یا متخصص رشتهٔ کامپیوتر نیستم، آیا میتوانم این کتابخانه را یاد گرفته و از آن در توسعه برنامههای مورد نظر خود استفاده کنم؟ بله، اما ممکن است در تجزیه و تحلیل رفتارهای سیستمعامل، مدیریت خطاها و پیکربندی ابزارهای تخصصی (برنامهنویسی) با مشکلاتی مواجه شوید که تنها متخصصات این رشته میتوانند آن را درک و حل کنند. آیا واقعاً حجم برنامههای کیوت نسبت به Net. یا Java بیشتر است !؟ خیر، به طور ذاتی برنامههای توسعه داده شده توسط سی++ دارای کمترین حجم برنامه هستند، معمولاً کتابخانههای استاندارد این زبان به صورت پیشفرض بر روی سیستم عاملها تعبیه شده و در دسترس قرار دارند. اما شما در ویندوز زمانی که با داتنت برنامهنویسی میکنید، فریمورک مربوطه از قبل بر روی سیستم عامل ویندوز نصب بوده و بدون آن هیچ برنامهٔ نوشته شده توسط داتنِت قابل اجرا نمیباشد. اما چون از قبل این کتابخانه بر روی سیستمعامل تعبیه شده است شما نیاز به تنها داشتن فایل اجرایی دارید و نیازی نیست فریمورک داتنت را در کنار فایل اجرایی خود مستقر کنید. بنابراین حجم مربوط به چهارچوب به چشم نیامده و اینطور به نظر میرسد که برنامههای تحت دات نت بسیار سبُکتر هستند! متاسفانه این تفکری اشتباه است برنامههای تحت سیپلاسپلاس نسبت به زبانهای دیگر کم حجمتر و سبُکتر بوده و شما کافی است فایلهای مربوط به کتابخانه را در کنار برنامهٔ خود داشته باشید. در رابطه با کتابخانهٔ Qt نیز باید گفت کیوت به عنوان یک چهارچوب مانند دات نت شامل کلاسها و ماژولهایی است که باید همانند دات نت بر روی سیستم عامل تعبیه شود اما چون اینکار به صورت جداگانه در کنار برنامهٔ شما قرار میگیرد اینگونه تصور میشود که برنامههای مبتنی بر کیوت نسبت به دات نت از حجم بیشتری برخوردار هستند. این کاملاً طبیعی بوده و به عنوان نکته ضعف نیست. من علاقهٔ خاصی به سیپلاسپلاس دارم و میخواهم کیوت را یاد بگیرم، از کجا و چه تحت منابعی باید شروع کنم؟ خوشبختانه کیوت از لحاظ مستندات بسیار جامع است و شما میتوانید از این آدرس به تمامی مستندات مورد نیاز خود دسترسی داشته باشید. همچنین اگر نگران اینترنت خود هستید و یا به آن دسترسی مداوم ندارید میتوانید از داخل محیط توسعهٔ کیوت کریتور از بخش Help آن مستندات مورد نیاز خود را به صورت آفلاین دریافت کنید. من دنبال کتاب آموزشی کیوت هستم، آیا کیوت کتابهای آموزشی مفیدی در این زمینه از مقدمه تا پیشرفته دارد؟ بله، در این بخش شما میتوانید کتابهایی را در این زمینه مشاهده کنید که مرجع رسمیِ کیوت آنها را تایید کرده است. من به زبان انگلیسی تسلط کافی ندارم، ترجیح میدهم که از مراجع فارسی معتبر استفاده کنم، آیا کیوت در این زمینه منابعی دارد که معتبر باشند؟ خوشبختانه کیوت به قدری طعمِ جذابی برای برنامهنویسی دارد که دو کتاب مقدماتی و پیشرفتهٔ این کتابخانه به زبان فارسی نوشته و در کتابخانهٔ ملی کشور به صورت رسمی به ثبت رسیدهاند و عبارتند از نسخههای مقدماتی برای Qt Widgets و نسخهٔ پیشرفته برای Qt Quick (این کتابها تجاری هستند) که در لیست کتابخانهٔ اصلی کیوت نیز تأیید و ثبت شدهاند. آیا مقالات یا کتابهای آموزشی رایگانی هم برای کیوت وجود دارد؟ تنها مرجع آموزشی که در این رابطه به زبان فارسی توضیح میدهد، آیاواستریم است، تقریباً هیچ مقاله یا کتاب جامع و کاملی به صورت رسمی به زبان فارسی خارج از مرجع آیاواستریم (به رایگان) وجود ندارد. اما وعدههایی میدهیم که در پلتفرم فانوکس آموزشهای جدی و با ارزشی برای کیوت ارائه شود که در دو هدف رایگان و تجاری برنامهریزی شدهاند. آیا لیستی برای مشاهدهٔ برنامههای توسعه یافته توسط Qt داریم؟ بسیاری از برنامههای قدرتمند و خارقالعادهای توسط سیپلاسپلاس توسعه داده میشوند که میتوان لیست عظیمی از آنها را نام برد. اما در این میان لیستی از برنامههایی که تحت کیوت توسعه داده شدهاند در این بخش آمده است. برای یادگیری استاندارد سیپلاسپلاس و تقویت مهارت خود در این زبان کدام مقالات و کتابها را پیشنهاد میکنید؟ علاوه بر این که شما میتوانید در مرجع به دنبال آموزشهای مرتبط با این زبان باشید، پیشنهاد ما این است که از مراجع رسمی آن نیز استفاده کنید. برخی از آنها به صورت زیر آمدهاند: cppreference.com http://www.cplusplus.com/ Learn C++ C++ Tutorial | SoloLearn: Learn to code for FREE! Learn C++ (Introduction and Tutorials to C++ Programming) Qt Documents Qt Quick & QML اگر سوالی داشته باشم کجا میتوانم آن را مطرح کرده و به پاسخ خود برسم؟ شما میتوانید برای سوال و پرسش در انجمنهای این مرجع اقدام کنید. اساتید و دوستان با تجربه سوالات شما را دریافت و مناسبترین پاسخها را ارائه خواهند داد. همچنین شما میتوانید ما را در گروه سیپلاسپلاس و کانال تلگرامی دنبال کنید. نکته (در این پُست بنابر اهداف فرهنگسازی برای حق چاپ) فایلهای مرتبط با کتابهای آموزشی زبان اصل و یا زبان فارسی قرار داده نشده است. کتابهای زیادی در رابطه با این زبان وجود دارند که به زبان اصلی میباشند اما برای احترام به نویسندهٔ آنها از ارسال چنین فایلهایی معذوریم. این پُست ممکن است ویرایش یا بهروز رسانی شود.
-
10 امتیازخلاصه تعریفی از زبان برنامه نویسی سیپلاسپلاس (++C) با توجه به پیشرفت و توسعهٔ زبانهای برنامهنویسی، به ویژه ظهور زبانهای جدید که جهت حل مشکلات زبانهای موجود و یا با هدف ایجاد انقلاب و یا سهولت برنامهنویسی، یکی از سوألاتی که مدام به ذهن میآید این است که چه زبانی را باید انتخاب کرد که از لحاظ بُعد علمی، اقتصادی و فنی بهترین انتخاب باشد تا با یک خیال راحت به یادگیری آن بپردازیم. در این مقاله به مزایای این زبان نسبت به دیگر زبانها و همچنین چشماندازی از آیندهٔ زبان اشاره شده است؛ سیپلاسپلاس به عنوان قدرتمندترین زبان برنامهنویسی تا به کنون است که به جرأت میتوان گفت به عنوان یک زبان برنامهنویسیِ غالب بر دیگر زبانهای برنامهنویسی لقب «هیولای زبانهای برنامهنویسی» را به خود اختصاص میدهد. با توجه به ساختار و نقشهٔ راه توسعهٔ خود، هنوز هم به عنوان یکی از پر طرفدارترین و پر کاربردترین زبانهای برنامهنویسی ساخت دست بشر به شمار میرود. آیا تا به حال فکر کردهاید که یک جهان پیشرفتهٔ متکی به فناوری امروز، وابستهٔ چه چیزهایی است و موتور نامرئی آن چیست؟ اخیراً دانشمند بزرگ، همچنین سازندهٔ زبان سی++ «بیارنه استراس تروپ» در یک سخنرانی ۱ دقیقهای به معرفی موتور نامرئی جهان پرداخته است که در این لینک میتوانید از زبان او بشنوید. سیپلاسپلاس با قابلیتهای انواع داده ایستا، نوشتار آزاد، چندمدلی، معمولاً زبان ترجمه شده با پشتیبانی از برنامهنویسی ساختیافته، برنامهنویسی شیءگرا، برنامهنویسی جنریک است. C++ به همراه جد خود C از پرطرفدارترین زبانهای برنامهنویسی تجاری هستند بنا بر این در زیر فلسفهای از این زبان را بیان می کنیم: زبان ++C طراحی شدهاست تا یک زبان عمومی با کنترل نوع ایستا و همانند C قابل حمل و پربازده باشد. زبان ++C طراحی شدهاست تا مستقیماً و بصورت جامع از چندین شیوه برنامهنویسی (برنامهنویسی ساختیافته، برنامهنویسی شیگرا، انتزاع داده، و برنامهنویسی جنریک) زبان ++C طراحی شده است تا به برنامهنویس امکان انتخاب دهد حتی اگر این انتخاب اشتباه باشد. زبان ++C طراحی شده است تا حداکثر تطابق با C وجود داشته باشد و یک انتقال راحت از C را ممکن سازد. زبان ++C از بکاربردن ویژگیهای خاص که مانع از عمومی شدن است خودداری مینماید. زبان ++C از ویژگیهایی که بکار برده نمیشوند استفاده نمیکند. زبان ++C طراحی شدهاست تا بدون یک محیط پیچیده عمل نماید. زبان ++C مورد انتخاب برای ساخت نرمافزارهایی با کارآیی بالا است که به طور «مستقیم» به منابع یا تجهیزات و ابزارهای سیستمعامل دسترسی دارند. بنابراین علاوه بر ویژگی سطحِ بالای این زبان شما را قادر میسازد تا به سطوح پایینتر از یک سیستمعامل دسترسی داشته باشید و این امر موجب میشود از قدرت بسیار بالایی در برنامهنویسی بهره ببرید ، لذا در مقایسه با سایر زبانهای برنامهنویسی شما باید از جزئیات بیشتری اطلاع داشته باشید تا بتوانید برنامهٔ فوق حرفهای خود را تولید کنید. کتابخانهها چه چیزی هستند و در این زبان چگونه است؟ به مجموعههای یکپارچهای از کلاسهای پیاده سازی شده (به صورت فایلهای سرآیند با پیاده سازیهای کد یا اشیای زبان ماشین) که برای برنامهنویسی به کار میروند، یک کتابخانه C++ گفته میشود و یکی از ویژگیهای بارز آن تولید و دسترسی به کتابخانههای بیشمار است. لیستی از این کتابخانههای همراه با توضیحات در لینک زیر آمده است : A list of open source C++ libraries - cppreference.com لیست کامل انواع کامپایلرها : List of compilers - Wikipedia ویژگیهای جدید در ویرایش ۱۱، ۱۴، ۱۷ و ۲۰ چیست؟ زبان C++11 (معروف به C++0x) یک نسخه استاندارد از زبان ++C است که در ۱۲ آگوست ۲۰۱۱ منتشر و توسط ISO جایگزین C++03 شد این نسخه دارای نشان ISO/IEC 14882:2011 می باشد و در تاریخ ۱۸ آگوست ۲۰۱۴ نسخه جدید آن یعنی C++14 منتشر و جایگزین C++11 شد. امکانات اضافه شده به هسته C++ : یکی از وظایف کمیته استاندارد سازی توسعه هسته زبان است.در توسعه فعلی چندین بخش از زبان بهبود یافته که شامل چندنخی (multithreading) ، پشتیبانی از برنامهنویسی عمومی، مقدار دهی اولیه یکنواخت و پیشرفت عملکرد میباشد. ویژگیهای هسته زبان و تغییرات آن به چهار بخش کلی دسته بندی شداند: 1. پیشرفت در عملکرد زمان اجرا (Run-Time) 2. پیشرفت در عملکرد زمان ساخت (Build-Time) 3. پیشرفت در ویژگی ها (قابلیت استفاده) 4. و قابلیت های جدید ویرایش C++ 14 بر روی اشکالزدائی و بهبودهای جزیی استاندارد قبلی یعنی C++11 تمرکز کرده است؛ این زبان در تاریخ ۱۵ می ۲۰۱۳ منتشر و در ۱۵ آگوست ۲۰۱۴ بعد از رای گیری و انجام تغییراتی جزئی استاندارد این زبان منتشر شد. بدلیل این که عموماً تاریخ انتشار این زبان بطور قابل ملاحظهای دیر هنگام بوده است به C++14 گاهی C++1y نیز گفته میشود. همانند استاندارد C++11 که به آن C++0x گفته میشده و قرار بر این بوده که قبل از ۲۰۱۰ منتشر شود (البته تا سال ۲۰۱۱ انتشار به تعویق افتاد). گرچه تمامی کامپایلرها درحال کاربروی C++14 هستند اما هنوز تمامی آن ها از C++14 پشتیبانی نمیکنند. در C++11 و C++14 توابع جدیدی به هسته اصلی زبان و کتابخانه استاندارد آن اضافه شده است که شامل بسیاری از کتابخانههای C++TR1 به استثنای کتابخانهٔ توابع ریاضی ویژه میباشد. ویژگیهای اضافه شده کتابخانه در ویرایش ۱۱ std::move std::forward std::to_string type traits smart pointers std::chrono tuples std::tie std::array unordered containers std::make_shared memory model ویژگیهای اضافه شده به زبان در ویرایش ۱۱ move semantics variadic templates rvalue references initializer lists static assertions auto lambda expressions decltype template aliases nullptr strongly-typed enums attributes constexpr delegating constructors user-defined literals explicit virtual overrides final specifier default functions deleted functions range-based for loops special member functions for move semantics converting constructors explicit conversion functions inline-namespaces non-static data member initializers right angle brackets ویژگیهای اضافه شده به کتابخانه در ویرایش ۱۴ user-defined literals for standard library types compile-time integer sequences std::make_unique ویژگیهای اضافه شده به زبان در ویرایش ۱۴ binary literals generic lambda expressions lambda capture initializers return type deduction decltype(auto) relaxing constraints on constexpr functions variable templates ویژکیهای اضافه شده به کتابخانه در ویرایش ۱۷ std::variant std::optional std::any std::string_view std::invoke std::apply splicing for maps and sets ویژگیهای اضافه شده به زبان در ویرایش ۱۷ template argument deduction for class templates declaring non-type template parameters with auto folding expressions new rules for auto deduction from braced-init-list constexpr lambda lambda capture this by value inline variables nested namespaces structured bindings selection statements with initializer constexpr if utf-8 character literals direct-list-initialization of enums ویژگیهای اضافه شده به زبان در ویرایش ۲۰ concepts designated initializers (based on the C99 feature) [=, this] as a lambda capture template parameter lists on lambdas three-way comparison using the "spaceship operator", operator <=> initialization of an additional variable within a range-based for statement lambdas in unevaluated contexts default constructible and assignable stateless lambdas allow pack expansions in lambda init-capture string literals as template parameters atomic smart pointers (such as std::atomic<shared_ptr<T>> and std::atomic<weak_ptr<T>>) removing the need for typename in certain circumstances new standard attributes [[no_unique_address]] [[likely]] and [[unlikely]] calendar and time-zone additions to <chrono> std::span, providing a view to a contiguous array (analogous to std::string_view but span can mutate the referenced sequence) <version> header feature test macros bit-casting of object representations, with less verbosity than memcpy() and more ability to exploit compiler internals conditional explicit, allowing the explicit modifier to be contingent on a boolean expression constexpr virtual functions ranges (The One Ranges Proposal) concept terse syntax constexpr union, try and catch dynamic_cast and typeid, std::pointer_traits various constexpr library bits immediate functions using the new consteval keyword signed integers are now defined to be represented using two's complement (signed integer overflow remains undefined behavior) a revised memory model coroutines – already experimentally supported in Clang 5 modules – experimentally supported in Clang 5 and Visual Studio 2015 Update 1 as well as GCC various improvements to structured bindings (interaction with lambda captures, static and thread_local storage duration) contracts have been removed (see list of features deferred to a later standard) use of comma operator in subscript expressions has been deprecated constexpr additions (trivial default initialization, unevaluated inline-assembly) using scoped enums various changes to the spaceship-operator DR: minor changes to modules constinit keyword changes to concepts (removal of -> Type return-type-requirements) (most of) volatile has been deprecated DR: [[nodiscard]] effects on constructors The new standard library concepts will not use PascalCase (rather standard_case, as rest of standard library) text formatting (chrono integration, corner case fixes) bit operations constexpr INVOKE math constants consistency additions to atomics (std::atomic_ref<T>, std::atomic<std::shared_ptr<T>>) add the spaceship (<=>) operator to the standard library header units for the standard library synchronization facilities (merged from: Efficient atomic waiting and semaphores, latches and barriers, Improving atomic_flag, Don't Make C++ Unimplementable On Small CPUs) std::source_location constexpr containers (std::string, std::vector) std::stop_token and joining thread (std::jthread) Many new keywords added (and the new "spaceship operator", operator <=>), such as concept, constinit, consteval, co_await, co_return, co_yield, requires (plus changed meaning for export), and char8_t. And explicit can take an expression since C++20. (Most of) the use for the volatile keyword has been deprecated. C++ has added a number of attributes over the years, including new in C++20, [[likely]] and [[unlikely]]; and [[no_unique_address]]. etc... کتابخانههای استاندارد چیست و در نسخههای جدید چگونه در دسترس هستند؟ در زبان برنامهنویسی ++C کتابخانهٔ استاندارد سی++ مجموعهای از کلاسها و رویهها است که در هسته زبان نوشته شدهاند و قسمتی از استاندارد ISO سی++ میباشند. در سال ۱۹۹۸ استاندارد ++C شامل دو بخش هسته زبان و کتابخانه استاندارد ++C است. این کتابخانه شامل بیشتر بخشهای STL و کتابخانه استاندارد C است. بیشتر کتابخانههای ++C در استاندارد وجود ندارند و یا استفاده از تعریف قابلیت پیوند کتابخانهها را میتوان در زبانهایی مانند فرترن، C، پاسکال، بیسیک نوشته شوند. البته با توجه به ویژگیهای کامپایلر مشخص خواهد شد که کدام زبان را میتوان استفاده نمود. کتابخانهٔ استاندارد ++C شامل کتابخانه استاندارد C با یک سری تغییرات برای بهبود عملکرد است. بخش بزرگ بعدی این کتابخانه STL است. STL شامل ابزار بسیار قدرتمندی مانند نگهدارندهها (مانند vector و list)، تکرارکنندهها (اشارهگرهای عمومی شده) برای شبیهسازی دسترسی مانند آرایه الگوریتمهایی برای جستجو و مرتبسازی در آنها وجود دارند. نقشهها (نقشههای چندگانه) (آرایه شرکتپذیر) و مجموعهها (مجموعههای چندگانه) واسطهای عمومی فراهم میسازند. در نتیجه با استفاده از قالب تابع، الگوریتمهای جنریک با هر نگهدارنده و دارای تکرارکننده عمل نماید. همانند C ویژگیهای کتابخانه را میتوان با استفاده از شبه دستور include# شامل یک سرآیند استاندارد اضافه نمود. C دارای ۶۹ کتابخانه استاندارد است که ۱۹ تا از آنها نامناسب تشخیص داده شدهاند. استفاده از کتابخانهٔ استاندارد - مانندstd::vector یا std::string به جای آرایههای C موجب ایجاد برنامههای مطمئن تر شده است. STL در آغاز محصولی جداگانه از HP و سپس SGL پیش از ادغام در کتابخانه استاندارد ++C بودهاست. استاندارد عبارت STL را بکار نمیبرد بلکه آن را بخشی از کتابخانه میداند اما مردم هنوز هم آن را برای جداسازی بخشهای مختلف کتابخانه با این نام بکار میبرند. (جریانهای ورودی/خروجی، جهانیسازی، تشخیص، زیرمجموعه کتابخانه C) بیشتر کامپایلرها کتابخانه استاندارد و STL را پیادهسازی مینماید. پیادهسازیهای مستقلی نیز همانند STLport نیر وجود دارند. پروژههای دیگر نیز پیادهسازیهای خود را از STL با توجه به اهداف خود بوجود میآورند. روش جدیدی جناب بیجارن در نظر گرفته که کتابخانه های استاندارد ++C علاوه بر اینکه توسط خود کامپایلرها در دسترس و قابل استفاده هستش بلکه توسط کتابخانه STL و Boost نیز می توان دسترسی به مجموع عظیمی از کتابخانه ها استاندارد ISO داشت. ساختار فایلها در این زبان چگونه است؟ در رابطه با ساختار برنامه های نوشته شده توسط ++C بدانید که منظور از ساختار در اینجا انواع فایل های موجود در زبان سیپلاسپلاس است، در این رابطه باید اینگونه اشاره کنیم که در این زبان ما می توانیم از فایل های زیر برای برنامه نویسی استفاده کنیم. فایل با پسوند .c این فایل منبعی برای کد هایی از نوع زبان C هستند. فایل با پسوند .c++ منبعی برای کد هایی از نوع زبان C و ++C هستند ضعف این نوع فایل در قابل حمل نبودن و عدم شناسایی توسط فایل سیستم ها می باشد. فایل با پسوند .cxx منبعی برای کد هایی از نوع زبان C و ++C هستند با تفاوت اینکه نسبت به فایل .c++ قابل حمل تر است. فایل با پسوند .cpp منبعی برای کد هایی از نوع زبان C و ++C هستند یعنی در هر دو نیز قابل استفاده می باشند. این پسوند با تمامی سیستم ها سازگاری دارد و بسیار رایج است. فایل با پسوند .hxx معمولا فایل با عنوان (هدر/سرصفحه) یاد می شوند و معمولا فقط حاوی اعلان ها میباشند. فایل با پسوند .hpp معمولا فایل با عنوان (هدر/سرصفحه) یاد می شوند و معمولا فقط حاوی اعلان ها میباشند. این فرمت توسط مارس دیجیتال استفاده می شود. همچنین بورلند و دیگر کامپایلر های سی++ از آن پشتیبانی میکنند. ممکن است در این فایل متغیر ها، ثوابت و توایعی که در فایل منبع اصلی به آن ها اشاره شده است اعلام شود. فایل با پسوند .h معمولا فایل با عنوان (هدر/سر صفحه) یاد میشوند و معمولا فقط حاوی اعلان ها میباشند این نوع بسیار رایج است و تقریبا با تمامی سیستم ها سازگاری دارد. فایل با پسوند .hh در این زبان: فایل با عنوان (هدر/سر صفحه) یاد می شوند و معمولا فقط حاوی اعلان ها میباشند. فایل با پسوند .h++ در این زبان: این نوع فایل ها معمولا فایل با عنوان (هدر/سرصفحه) یاد میشوند و معمولاً فقط حاوی اعلان ها میباشند. ضعف این نوع فایل در قابل حمل نبودن و عدم شناسایی توسط فایل سیستم ها میباشد. فایل با پسوند .ixx در استانداردهای جدید جهت تعریف سند ماژول (اختصاصاً برای کامپایلرهای MSVC) معرفی شده است. همچنین فایل با پسوندهای cppm، ccm، mxx، cxxm و c++m به عنوان پسوندهای جدیدی در رابطه با خاصیت ماژول از استانداردهای جدید برای کامپایلرهای مدرن هستند. یک فایل سرآیند با پسوند (.h, .hpp و ...) میتواند شامل محتوای زیر باشد: تعریف کلاس تعریف توابع درون خطی (Inline) اعلام تابع اعلام شیء مثال: #ifndef CPPFILES_H #define CPPFILES_H extern int status; class CPPFiles { public: CPPFiles(); void myFunction(); inline int safe(int i); }; #endif // CPPFILES_H یک فایل منبع - سورس با پسوند (.c, .hpp، .cxx و ...) میتواند شامل محتوای زیر باشد: تعریف کلاس تعریف توابع اعلام شیء مثال : #include "cppfiles.h" int status = 1; CPPFiles::CPPFiles() { } void CPPFiles::myFunction() { //Do somthing... } int CPPFiles::safe(/*@Param*/) { return /*Somthing...*/; } انواع فایل هایی که به آنها اشاره شد بسیار است ولی متناسب با محبویت و پشتیبانی کامپایلر ها از این فایل ها در این زبان برای انتخاب آنها مهم است بنا بر این در طی آموزش و تمامی مراحل ما فقط از فایل های .h برای هدر و فایل های .cpp برای منابع استفاده خواهیم کرد. چرا و چه زمانی باید از فایل های hpp. و چه زمانی از فایل های cpp. استفاده کنیم؟ توجه داشته باشید که سیپلاسپلاس از تمامی پسوند فایلهای مذکور پشتیبانی میکند، معمولاً استفاده از فایلهای hpp و h جهت اعلان و تعریفهای اولیهٔ کدها مناسب است و در زمان تعریف کامل عملکرد کد مورد نظر فایل با پسوند cpp پیشنهاد میشود. هرچند استفادهٔ غیر استاندارد نیز پشتیبانی میشود اما باید توجه داشت جهت حفظ ساختار استاندارد روشهای اصولی منطقی و صحیح هستند. کاربرد این زبان در کجاست؟ معمولاً تمامی برنامهها و نرمافزارهایی که به صورت روزمره در زندگی مدرن امروزی مشاهده میکنیم بدون شک توسط زبان های اساسی نوشته شدهاند. به عنوان مثال انواع صنایع موجود در کشورها از قبیل صنعت خودروسازی، صنعت فضایی، سیستمهای معماری و بانکی ، تجهیزات مدرن و سختافزارهای رباتیک، سیستمهای کامپیوتری و یا کنسول هایبازی ، سیستمهای خانگی و یا هوش مصنوعی، تجهیزات مجهز به انواع حسگرها، پزشکی، فضایی، زبانهای برنامهنویسی، سیستمعاملها و بسیاری از موارد دیگری که میتوان نام برد بدون شک توسط این زبان پیاده سازی شدهاند. چگونه C++ میتواند در لایه های زیرین (سطح پایین) و بالا (سطح بالا) مورد استفاده قرار بگیرد؟ به نقل از سازندهٔ آن، این زبان هر دو ویژگی سطح بالا و سطح پایین را ارائه میکند. سیپلاسپلاس دارای بخشهای سطح پایین است، مانند اشارهگرها، آرایهها و کستها. این ویژگیها تقریباً مشابه همان ویژگی C هستند که ارائه شده است و برای کار با کارهای سختافزاری ضروری هستند. بنابراین اگر میخواهید به امکانات سطح پایین زبان دسترسی داشته باشید، بله سیپلاسپلاس مجموعهای از این امکانات را در اختیار شما قرار میدهد. با این حال، اگر نمیخواهید از ویژگیهای سطح پایین استفاده کنید، نیازی به استفاده از آنها به صورت مستقیم در این زبان نیست. در عوض میتوانید از امکانات سطح بالا از جمله کتابخانههای آن را مورد استفاده قرار دهید. به عنوان مثال اگر نمیخواهید از اشارهگرها و آرایهها استفاده کنید میتوانید از رشتهها و نگهدارندههای استاندارد استفاده کنید که به مراتب گزینههای بهتری هستند. آیا سیستم عامل ها و نرم افزار های مطرح دنیا توسط این زبان نوشته شده اند؟ دلیل آن چیست؟ همانگونه که مشخص است بسیاری از سیستم عامل ها از ابتدا توسط خانواده اسمبل ، C نوشته شده اند که به صورت زیر به تعدادی از آن ها اشاره میکنیم: DragonFlyBSD,FreeBSD,OpenBSD,NetBSD HP-UX Centos,Debian,Fedora,OpenSUSE,RedHat,Ubuntu OSX,iOS,Darwin OracleSolaris,OpenIndiana Cygwin Android Windows Phone BlackBerry WindowsXP,Vista,7,8,10 دلیل آن که از زبان هایی مانند C و ++C برای نوشتن سیستمعامل استفاده میشود قابلیت های مهم آن است به عنوان مثال: کارآیی بالا ، مستقل از سکو، زبان پاسه و غالب بودن و عدم وابستگی آن به زبان های دیگر، ارتباط با سختافزار و تمامی دیوایسها، مدیریت هوشمندانه و همچنین برنامهنویسی آزادانه ، دسترسی به لیست عظیمی از کتابخانهها که میتوان توسط آن ها هر چیزی را که در رویاهای خود به آن فکر میکنید در واقعیت خلق کنید. انواع سخت افزارهایی که این زبان پشتیبانی میکند: زبان برنامهنویسی سیپلاسپلاس با استفاده از کامپایلرهای قدرتمندی چون GCC، Clang و غیره، طیف گستردهای از سختافزارها و معماریها را پشتیبانی میکند. مدل ماشین هایی که پشتیبانی میشود : PowerPC , Oracle,Fujitsu,Sun, IBM,Freescale , AMD,Intel مدل پردازندهها: Athlon,Atom,Core,Core2,Corei3/i5/i7,Opteron,Pentium,Phenom,Sempron,Turion,etc Itanium,Itanium2,Itanium29000/9100/9300,etc PowerPC,POWER1/2/3/4/5/6/7,G1,G2,G3,G4,G5,etc UltraSPARCI/II/III/IV/T1/T2,SPARCT3/T4,etc کاربرد این زبان در زمینه وب چگونه است؟ در این زمینه معمولاً به دلیل وجود چهارچوبها و زبانهای سادهتری نسبت به سی++ در حوزهٔ وب مانند Php و غیره...، معمولاً فرصت نشده است تا به شناخت کتابخانهها و مزایای این زبان در این حوزه پرداخته شود. با توجه به توسعههای اخیر صنعت وب دانشمندان به این نتیجه رسیدهاند که جهت افزایش کارایی در زمینهٔ وب و از بین بردن محدودیتهای وابسته به مرورگرهای اینترنتی، از فناوریهای بهتری مانند wasm نیز پرده برداری شود که در این فناوری سی++ گزینهٔ پشت پردهای از این فناوری محسوب میشود که اجازه میدهد با اجرای کدها و دسترسی به رابطهای برنامهنویسی پیشرفته یک دنیای جدیدی از فناوری وب را ارائه کند. این فناوری با عنوان Web Assembly شناخته میشود که اجازه میدهد برنامههای نوشته شده توسط سی++ در مرورگر به عنوان یک پلتفرم جدید اجرا شوند. البته این تنها روش نیست، سی++ به لطف کتابخانههای عظیم خودش قادر است هر چیزی را در اختیار برنامهنویس قرار دهد. به عنوان مثال دسترسی به کتابخانههای عظیم Qt، Wt این امکان را فراهم میکنند که به راحتی یک سیستم ابر پیشرفتهٔ تحت وب را به کمک این زبان پیاده سازی کنید که هیچ نوع سیستم موجود در وب قابل رقابت و مقایسه با ویژگیها و نتایج خارقالعادهٔ آن نخواهد داشت. در مثال زیر یک سیستم مدیریت محتوا به صورت آزمایشی پیاده سازی شده است که میتوانید نتایج خارقالعادهٔ آن را مشاهده کنید. همچنین توجه کنید که این تنها کاربرد سی++ در وب نیست، حقیقت آن است که وبسایتهای بزرگی همچون فیسبوک، گوگل و غیره هستهٔ وبسایتهای خود را توسط این زبان توسعه دادهاند که دلایل آنها مصرف بهینهٔ تجهیزان سختافزاری و دسترسی به ویژگیهای سیستمی بسیار زیاد و امنیت بسیار بالا است. احتمالاً در رابطه با موتور قدرتمند v8 Engine شنیدهاید، این یک موتور اساسی برای محصولات گوگل است که کاملاً تحت سی++ توسعه یافته است. برخی از محیطهای برنامهنویسی مانند Node.JS تحت آن قدرت گرفتهاند. برخی از محصولات اساسی و معروف که بخش عمده و یا به صورت کامل توسط سیپلاسپلاس نوشته شدهاند (این لیست تنها شامل برجستهترین محصولات است) : سیستمعاملها ویندوز مکینتاش لینوکس آیاواس اندروید مرورگرها اُپرا فایرفاکس گوگل کروم مایکروسافت اِدج اپل سافاری نرمافزارهای کاربردی و مهندسی تمامی محصولات قدرتمند Adobe مانند فوتوشاپ، افترافکت و غیره... تمامی محصولات Autodesk مانند Maya، 3dsMax و Autocad مجازیسازها مانند Virtual Box و VMware محصولات مایکروسافت مانند Visual Studio و Office محصولات اپل مانند iTunes، Xcode و غیره... بازیها و صنایع مرتبط توسعهٔ کنسولهای بازی Playstation و Xbox اکثر بازیهای خارقالعاده در سطح AAA پیامرسانها تلگرام اسکایپ موتورهای دیتابیس مانند MySQL و غیره... کتابخانهها و ابزارهای پیشرفتهٔ توسعه ابزارهای مرتبط با فناوریهای روز مانند Blockchain و غیره... زبانهای برنامهنویسی مانند Swift و غیره... راهاندازها و ابزارهای قدرتمند AMD، Intel و NVIDIA Geforce و پلتفرمهایی مانند Cuda. و هزاران و میلیونها ابزار و برنامههایی که در زندگی روزمره با آنها سرو کار داریم. اشاره ای بر انواع موتور های دیتابیس که توسط ++C پشتیبانی میشوند : SQL NoSQL SQLite MySQL Sybase Adaptive Server SQL Server Oracle PostgreSQL IBASE : Borland IBM DB2 متأسفانه به دلیل عدم اطلاع و شناخت کافی از حقایق این زبان، توصیه برای یادگیری زبانهایی مانند Java و #C و مشابه آنها ممکن است بر اساس علاقههای فردی و تعصب باشد. بنابراین توصیه میشود حتماً در مورد تفاوتهای ساختاری و مزایای زبانها حتماً تحقیق شود. چگونه باید طراحی رابط کاربری را انجام دهیم؟ برای طراحی رابط گرافیکی ابتدا باید ذهن خود را از محیط VS و همچنین کنسول کنار بکشید لذا برای این کار کتابخانه های مخصوصی در نظر گرفته شده است به صورت زیر: FLTK nana WxWidgets OWLNext GTK+ glibmm gtkmm goocanvasmm libglademm libgnomecanvasmm webkitgtk flowcanvas evince Qt libdbusmenu-qt توسط این کتابخانه های میتوان محیطهای کاربری را فراهم ساخت. در این میان دو کتابخانهٔ wxWidgets و Qt بسیار قدرتمند عمل کردهاند که بین این دو نیز Qt با قدرت بسیار زیادی از رقیب خود یعنی wxWidgets پیشی گرفته است و معمولاً پروژههایی که در آن رابطکاربری خلاقانه (Creative) و مدرن مطرح است حرف از Qt به گوش میرسد (کیوت یک چهارچوب جامع جهت طراحی رابطهای کاربری قدرتمند است). پیشنهادات ما استفاده از مقالات خارجی و منابع رسمی میباشد: http://en.cppreference.com/w Learn C++ https://www.learn-cpp.org Learn C++ (Introduction and Tutorials to C++ Programming) http://www.cplusplus.com نگاهی به کاربرد این زبان در بین فناوریهای جدید! سیپلاسپلاس همچنین به عنوان یکی از قدرتمندترین و محبوبترین زبانهای برنامهنویسی در دنیای فناوری شناخته میشود و در صنعت بلاکچین نیز یک قدرت غالب است. زبان شیءگرایی برای توسعه بلاکچین مناسب است، زیرا از همان اصول کپسولهسازی، انتزاع، چندریختی و مخفی کردن دادهها استفاده میکند. به عنوان مثال بلاکچین از ویرایشهای ناخواسته از دادهها جولوگیری میکند که به عنوان یکی از چهار زبان برنامهنویسی آینده دار میتوان به آن اشاره کرد. همچنین توجه داشته باشید که فناوریهای دیگری مانند مباحث Cross-Platform و رشد بسیار شدید فناوری IoT این زبان به عنوان یک زبان پیشتاز در این حوزه است که در کنار بسیاری از کاربردهای اساسی خود میتوان به عنوان یک ابزار اساسی و کاربردی به آن در آیندهای که از همین حالا شروع شده است اشاره داشت. آیا با ++C میتوان برنامههای موبایلی مانند Android , iOS و غیره را تولید کرد؟ پاسخ، بله! متأسفانه این مورد هم مانند حوزهٔ وب به خاطر عدم شناخت و تبلیغات کافی از ذهن بسیاری از افراد به یک گزینهٔ بی اهمیت تبدیل شده است، اما با توجه به رشد روز افزون و ایجاد ابزارهای ضعیف، نیاز به شناخت این زبان و ابزارهای واقعی و قدرتمند آن الزامی شده است. برای مثال در حوزهٔ موبایل ابزارهایی مانند Xamarin و یا Flutter این روزها سرو صدای بسیاری کردهاند، اما واقعیت این است، آنها هیچگاه نتیجهٔ واقعی و مشابه به زبانهای پیشفرض پلتفرمهای توسعه را ندارند و نخواهند داشت. فناوری چند-سکویی به معنای واقعی تنها در ابزارهایی مانند Qt Framework و سی++ خلاصه میشود که به شما اجازهٔ تولید و توسعهٔ کدهای خود را به صورت بومی در پلتفرم هدف فراهم میکند. پیشنهاد ما در رابطه نحوه شروع برای یادگیری و آشنایی با زبان و انواع کتابخانه ها به صورت زیر است: قبل از هر چیز هدف خود را در رابطه با منابع مشخص نمایید، اگر زبان انگلیسی شما خوب است میتوانید در همین قدم اول از منابع رسمی و استاندارد که بی نقص هستند استفاده کنید. سعی کنید اگر قرار است این زبان را یاد بگیرید عملا با آن درگیر شوید. از مقدمات برنامه نویسی شروع کنید و حتما در رابطه با تاریخچه زبان و اهداف آن تحقیق کنید. شرکت و سازمان های بزرگ و موفق را الگو قرار دهید. اگر هدف شما سریع رسیدن به پول بدون در نظر داشتن کیفیت و اهداف بزرگ از پروژه هستش به هیچ عنوان سراغ این زبان نروید زیرا C++ برنامه نویس مشتاق به حرفهای شدن را میطلبد نه برنامهنویس راحت طلب. حتماً سیپلاسپلاس مدرن را بیآموزید. استانداردهای مدرن شامل نسخههای ۱۱، ۱۴، ۱۷ و ۲۰ هستند. برای استفاده و کار با کتابخانههای این زبان بهتر است کتابخانههای پیشفرض STL را به خوبی یاد بگیرید. برای توسعه هرچه بیشتر پروژه و استفاده از انواع قابلیتها توسط این زبان میبایست از کتابخانههای دیگر استفاده کنیم که در این میان در رابطه با بخش طراحی و رابط کاربریQt، GTK, MFC, SDL , wxWidgetsمناسب است که پیشنهاد ما در میان این لیست (Qt) خواهد بود که تحت آن میتوان مدرنترین طراحی ها را خلق نمود. برای کار با شبکه کتابخانههای Curl, Poco, Qt, RakNet, ReplicaNet, SDL موجود هستند و در بین اینها Curl بهترین گزینه میتواند باشد. برای کار با 3D بعدی کتابخانه مخصوص OpenGL یا باز همان Qt را که بر پایه موتور OpenGL است پیشنهاد میکنیم و یا میتوانید از کتابخانه های مخصوص DirectX و OpenGL و حتی نسخههای توسعهٔافته به نام Vulkan را به صورت تخصصی استفاده یاد بگیرید. در رابطه با 2D نیز از OpenGL، Direct2D, GDI و GDI+ میتوان استفاده کرد. در مورد Sound از کتابخانه های مطرح OpenAL, Fmod و Bass استفاده کنید. در مورد بحث فیزیک کتابخانه های Nvidia Physix, Nvidia Apex, Bullet, Box2D, ODE, Open Dynamics در رابطه با هوش مصنوعی کتابخانه های OpenAI, FEAR, OpenSteer, PathLib مطرح هستند. برای کار با پردازش تصویری OpenCV, OpenNI پیشنهاد میشود. برای کار با پردازش موازی OpenCL, OpenML, CUDA مناسب است. برای اسکریپت نویسی Lua, LuaPlus, Phyton برای کار با ورودی ها از OpenInput, Qt, SDL, SFML میتوان استفاده کرد. برای بازی سازی کتابخانه های Unreal Engine, OGRE, Irrlicht, KGE مناسب هستند که در بین اینها Unreal Engine بسیار قدرتمند عمل میکند. برای طراحی و اجرای وب سایت کتابخانه های WebKit, ClearSilver, Teng مناسب هستند. برای توسعهٔ ابزارهای مرتبط با فناوری بلاکچین، میتوان به کتابخانههای قدرتمند و خارقالعادهای به نام EOS اشاره کرد. لازم بذکر است اینها نمونهای از کتابخانههای بیشمار سی++ هستند و میتوان به کتابخانههای بسیاری اشاره کرد که خارج از گنجایش این مقاله است. منابع فارسی برای یادگیری سیپلاسپلاس مدرن چیست؟ متأسفانه منابع فارسی برای این زبان معمولاً متعلق به مباحث دانشگاهی و مفاهیم مرتبط به سیپلاسپلاس سنتی است (مربوط به ۳۰ سال پیش)! یادگیری این مباحث هیچ مزیتی برای شما نخواهد داشت و به شدت پیشنهاد میشود جهت یادگیری این زبان حتماً به سراغ آموزشهای مدرن بروید. تنها بسترهای آموزشی مربوط به سیپلاسپلاس جدید در ایران (به زبان فارسی) مرجع آیاواستریم است.
-
8 امتیازبا سلام و درود، همانطور که میدانید ویژگیهای اخیر در استانداردهای ۱۷ و ۲۰ بسیار عظیم و کاربردی هستند. هدف ما در مرجع آیاواستریم این است که با توجه به بهروزرسانیهای زبان سیپلاسپلاس مهمترین مواردی که نیاز است معرفی کنیم. بنابراین در این بخش به یکی از کاربردیترین موارد مرتبط در استاندارد ۱۷ با عنوان صفتهای ویژه اشاره میشود که در ادامه به تعریف هر یک از آنها میپردازیم. با توجه به استانداردهای ۱۱ و ۱۴ که در آن صفتهایی همچون [[deprecated]] و [[noreturn]] معرفی شدهاند که وظیفهٔ آن به ترتیب نمایش وضعیت منسوخ شدن یک عملکرد و یا وضعیت بازگشتی یک تابع از نوع void است. چنین صفاتی میتوانند در زمان اعلان و تعریف متغیرها و یا توابع مورد استفاده قرار گیرند. به عنوان مثال اگر کدی به صورت زیر داشته باشیم: [[deprecated]] void print(const std::string &message) { std::cout << message << std::endl; } در صورتی که تابع print در بخشی از برنامه مورد استفاده قرار بگیرد، پیغامی از سمت کامپایلر از نوع اخطار (warning) ساطع میشود، مبنی بر آن که تابع مربوطه به عنوان منسوخ شده یاد شده است. warning: 'print' is deprecated این ویژگی میتواند در ساخت و توسعهٔ کتابخانهها، موتورها، چهارچوب (فریمورک) و برنامههایی که قرار است دیگر برنامهنویسان از آنها استفاده کنند بسیار میتواند کاربردی باشد؛ چرا که با اعمال چنین خاصیتهایی در کدهای شما برای توسعهدهندگان یادآوری خواهد شد که کد مربوطه در نسخهٔ جدید یا نسخههای بعدی امکان حذف و یا تغییر را خواهد داشت. #include <iostream> #include <string> [[deprecated]] void print(const std::string &message) { std::cout << message << std::endl; } int main() { print("Hello, World!"); return 0; } در مثال بالا اخطار پیشفرض از سمت کامپایلر ساطع میشود، اما در بعضی از مواقع لازم است پیغام سفارشی جهت راهنمایی بیشتر کاربر اعمال شود که در این صورت صفت میتواند پیغام از نوع رشته را دریافت و در هنگام ساطع شدن، آن را نمایش دهد. برای این کار کافی است متن مورد نظر را به صورت زیر در صفت خود تعیین کنیم. [[deprecated("Use printView with print instead, this function will be removed in the next release")]] برای مثال یک تابع جایگزین و بهینه شده را به صورت زیر در نظر بگیرید، کامپالر اخطار مروبطه و سفارشی شده را نسبت به آن ساطع خواهد کرد. #include <iostream> #include <string> [[deprecated]] void print(const std::string &message) { std::cout << message << std::endl; } void printView(std::string_view message) { std::cout << message << std::endl; } int main() { printView("Hello, World!"); return 0; } همچنین در رابطه با صفت [[noreturn]] که در استاندارد ۱۱ معرفی شده است، باید در نظر داشت این صفت جهت بهینهسازی کامپایلر در رابطه با تولید هشدارهای بهتر و همچنین اعلام اینکه تابع مربوطه قابل دسترسی نیست مورد استفاده قرار میگیرد. مثال: #include <iostream> [[noreturn]] void myFunction() { std::cout << "Hello, World!" << std::endl; throw "error"; } void print() { std::cout << "Print Now!"; } int main() { myFunction(); print(); return 0; } در کد فوق، در زمان همگردانی (کامپایل) پیغام زیر ساطع میشود: warning: code will never be executed بنابراین در زمان اجرا تابع print(); اجرا نخواهد شد، زیرا به عنوان یک کد غیر قابل دسترس بعد از myFunction توسط کامپایلر یاد میشود. چرا که این امر اجازه میدهد تا کامپایلر بهینهسازیهای مختلفی را انجام دهد - نیازی به ذخیرهسازی و بازیابی هرگونه حالتهای ناپایدار در اطراف صدا زننده (Caller) نیست. بنابراین میتواند کدهای غیر قابل دسترس را از بین ببرد. با توجه به نیازهای این چنینی، در استاندارد ۱۷ صفتهای جدیدتر و کاربردیتری نیز ارائه شده است که به معرفی هر یک از آنها در بخش اول از این مقاله میپردازیم. صفتهای معرفی شده در استاندارد 1z یا همان ۱۷ به صورت زیر هستند: [[fallthrough]] [[maybe_unused]] [[nodiscard]] معرفی صفت [[fallthrough]] به طور معمول در برنامهنویسی، هر وقت که مرحلهٔ مربوط به case در دستور switch به انتهای خود میرسد، کد مربوطِ به دستورِ case بعدی اجرا خواهد شد. طبیعتاً عبارت break میتواند از این امر جلوگیری کند. اما از آنجایی که این رفتار را به اصطلاح fall-through میشناسیم، ممکن است در صورت عدم معرفی اشکالاتی را فراهم کند، در این حالت چندین کامپایلر و ابزارهای آنالیز کننده خطای مرتبط به آن را هشدار میدهند تا کاربر در جریان قرار بگیرد. با توجه به این موضوع که ممکن است بعضاً این مورد چشم پوشی شود، در سیپلاسپلاس ۱۷ به بعد یک صفت استاندارد معرفی شد تا توسعهدهنده بتواند با قرار دادن آن در مکان سقوط (fall-through) به کامپایلر اعلام کند که هشداری در آن بخش لازم نیست. کامپایلرها میتوانند هشدارهای مطمئنی را در زمانی که یک عبارت case بدون اجرای دستور break به انتهای خود میرسند و یا سقوط (fall-through) میکند، حداقل با یک جملهٔ مربوطِ به آن را ساطع کند. برای مثال به کد زیر توجه کنید: #include <iostream> int main() { int number { 2017 }; int standard = {0}; switch(number) { case 2011: case 2014: case 2017: std::cout << "Using modern C++" << std::endl; case 1998: case 2003: standard = number; } return 0; } در کد فوق، در زمان اجرای دستور case سوم با مقدار ۲۰۱۷، کامپایلر هشداری به صورت زیر را اعمال خواهد کرد. warning: unannotated fall-through between switch labels در این حالت برای از بین بردن (چشمپوشی کردن) از این خطا در صورتی که نیاز نباشد موارد دیگر مورد بررسی قرار بگیرد قرار دادن دستور break بعد از آن میتواند منطقی باشد. اما با توجه به انتظاری که میرود تا دستورات بدون توقف بین آنها اجرا شود، قراردادن دستور [[fallthrough]]; بعد از آن میتواند راه حل بسیار مناسبی باشد. #include <iostream> int main() { int number { 2017 }; int standard = {0}; switch(number) { case 2011: case 2014: case 2017: std::cout << "Using modern C++" << std::endl; [[fallthrough]]; // > No warning case 1998: case 2003: standard = number; } return 0; } در این حالت، کامپایلر بدون ساطع کردن خطا آن را همگردانی خواهد کرد. معرفی صفت [[maybe_unused]] صفت [[maybe_unused]] برای نشان دادن کد ایجاد شدهای است که ممکن است از منطق قطعی استفاده نکند. این مورد ممکن است اغلب در لینک شدن با پیشپردازندهها مورد استفاده قرار بگیرد یا نگیرد. از آنجایی که کامپایلر (همگردانها) میتوانند نسبت به متغیرهای بلا استفاده هشدار ساطع کنند، این صفت روش بسیار خوبی برای سرکوب آنها خواهد بود. استفاده از این ویژگی میتواند در بخشهای مهمی مفید باشد، فرض کنید کتابخانهای نوشتهایم که قرار است به صورت چند-سکویی دارای ویژگیهای یکسان در بسترهای مختلف باشد. برای مثال ساخت یک فایل در مسیر مشخصی از سیستمعامل مورد نظر جهت اعمال تنظیمات نرمافزار. namespace FileSystem::Configuration { [[maybe_unused]] std::string createWindowsConfigFilePath(const std::string &relativePath); [[maybe_unused]] std::string createMacOSConfigFilePath(const std::string &relativePath); [[maybe_unused]] std::string createLinuxConfigFilePath(const std::string &relativePath); [[maybe_unused]] std::string createiOSConfigFilePath(const std::string &relativePath); [[maybe_unused]] std::string createAndroidConfigFilePath(const std::string &relativePath); } به کد بالا توجه کنید، در صورتی که شما در محیط کدنویسی در حال استفاده از یک دستور مورد نظر از بین دستورات بالا هستید، طبیعتاً کامپایلر به بقیهٔ دستوراتی که از آنها استفاده نمیکنید پیغامی مبنی بر آن که دستور مربوطه بلااستفاده مانده است را ساطع میکند. جهت جلوگیری از این هشدارها کافی است صفت [[maybe_unused]] را قبل از آنها اعمال کنید. معرفی صفت [[nodiscard]] در صورتی که از [[nodiscard]] استفاده شود، کامپایلر میتواند درک کند توابعی که مقدار بازگشتی دارند نمیتوانند مقدار بازگشت داده شدهٔ آنها را دور انداخت و یا از آنها در زمان صدا زدن صرف نظر کرد. بنابراین با تعریف این صفت در توابع از نوع بازگشتی میتوان پیغامی به صورت زیر را ساطع کند. مثال: #include <iostream> [[nodiscard]] int myFunction() { return 17; } int main() { myFunction(); return 0; } در مثال فوق تابع myFunction در زمان فراخوانی که مقدار بازگشتی آن بی نتیجه مانده است از سمت کامپایلر هشدار مورد نظر را دریافت خواهد کرد. این پیغام در صورتی که مقدار بازگشتی تابع به متغیری از هم نوعِ خودش ارسال شود، ساطع نخواهد شد. #include <iostream> [[nodiscard]] int myFunction() { return 17; } int main() { int func; func = myFunction(); return 0; }
-
8 امتیازپیشنهادات و ملاحظات در عملکرد و کارآیی همانطور که میدانید تولید و توسعهی یک نرمافزار با سرعت و کارآیی بالا یکی از مزایایی مهارتی توسعهدهندگان است که به تنهایی میتواند به عنوان یک فاکتور بسیار مهم مطرح شود. بنابراین در صورتی که شما محصولی را در قالب وب، موبایل یا دسکتاپ تولید میکنید باید به آن توجه داشته باشید که سرعت اجرایی برنامهی شما در زمان استارتاپ و بعد در مراحل پردازشی و فرایندهای دیگر باید مورد قبول باشد. در این میان برنامهنویسان سی++ میدانند که باید در مدیریت حافظه و دیگر موارد با دقت بیشتری عمل کنند تا بتوانند به حداقل نشتی در حافظه (حتی فاقد نشتی در آن) و در نهایت رسیدن به حداکثر سرعت پردازشی توجه داشته باشند. با توجه به این موضوع که کتابخانهی Qt به عنوان یکی از کتابخانههای این زبان بشمار میآید؛ بسیاری از توسعهدهندگان درگیر توسعهی بخش فرانتاِند نیز میشوند. بنابراین باید توجه داشت در زمان توسعه رابط کاربری مبتنی بر فناوری Qt Quick مواردی را جهت افزایش کارآیی سرعت و هماهنگی کامل با سی++ را در نظر بگیرند چرا که بدون در نظر گرفتن فاکتورهای زمانی نتیجهی آن بسیار بد خواهد بود. شما به عنوان یک توسعه دهنده نرمافزار، باید برای رسیدن حداکثر فریم ریت ۶۰ در موتور رندرینگ تلاش کنید. این میزان بدین معنی است که بین هر فریم که در میان آنها میتواند پردازش انجام شود، تقریباً ۱۶ میلی ثانیه وجود دارد که شامل پردازش مورد نیاز برای بارگذاریهای اولیه به سمت سختافزار گرافیکی میباشد. در عمل، این به این معنی است که توسعهدهنده نرمافزار باید: هر کجا که ممکن است از روش ناهمزمان (Asynchronous) در بخش برنامهنویسی رویدادمحور (Event-driven programming) استفاده کند. در بخشهایی که به میزان قابل توجهی شامل پردازش میشوند از وُرکرترد (worker threads) استفاده کند. هرگز حلقه رویداد را به صورت دستی برای چرخش و ادامه تنظیم نکند. هرگز بیش از چند میلی ثانیه برای هر فریم در بلوک توابع صرف نکند. عدم انجام این کارها باعث پَرش در فریمها میشود که تاثیر بسیار جدی در تجربه کاربری دارد. نکته: الگویی که وسوسه انگیز است اما نباید هرگز از آن استفاده شود، چرا که یک متد QEventLoop و یا صدا زدن یک متد دیگر مانند QCoreApplication::processEvent به منظور جلوگیری از مسدود شدن در یک بلوک کُد سی++ که در QML استفاده شده است به کار گرفته میشود. این خطرناک است، زیرا زمانی که یک حلقه رویداد در هندلر سیگنال و یا پیوند (Binding) وارد میشود، موتور QML همچنان برای اجرای سایر پیوندها، انیمیشنها، ترنسیشنها و غیره میپردازد. این اتصالات میتوانند باعث عوارضهای جانبی شوند. پروفایلینگ (Profiling) مهمترین نکته این است که: از ابزار QML Profiler که بخشی از محیط توسعه یکپارچهی نرمافزار Qt Creator است استفاده کنید. زیرا دانستن زمانی که در یک برنامه صرف میشود به شما امکان این را میدهد تا بر قسمت یا بخشی که در آن مشکل وجود درد تمرکز سریعتر و بهتری داشته باشید. برای نحوهی استفاده از این ابزار به کتابچهی راهنمای خود کیوت کریتور مراجعه کنید. تعیین کردن اینکه اغلب کدام پیوند (اتصال) در حال اجرا است، یا کدام یک از توابع شما بیشترین زمان را برای اجرا صرف میکنند، به شما این امکان را میدهد که تصمیم بگیرید که آیا شما نیاز به بهینه سازی آن بخش از کُدها را دارید یا نیاز خواهد بود آن بخش از کد خود را مجددا پیاده سازی کنید تا عملکرد آن بهتر شود یا خیر. به طور کلی تلاش برای بهینه سازی بدون استفاده از ابزار QML Profiler احتمالاً باعث بهبودهای جزئی و غیرقابل توجه در عملکرد خواهد شد. کُد جاوا اسکریپ (JavaScript) بیشتر برنامههای QML مقدار زیادی از کدهای جاوا اسکریپت در درون خود خواهند داشت. که به شکل توابع پویا، مدیریت سیگنال و یا عبارتهای مربوط به پراپرتیها (مشخصه، اموال) را در اختیار دارند. به طور کلی این یک مشکل نیست. با تشکر از برخی از بهینه سازیهای موتور QML، مانند آنهایی که به کامپایلر منتقل میشوند، میتواند (در بعضی موارد استفاده شده) حتی سریعتر از فراخوانیهای سمت سی++ باشد. با این حال، باید اطمینان حاصل شود که پردازش غیر ضروری به طور تصادفی اتفاق نیفتاده باشد. اتصالات (Binding) دو نوع اتصال در QML وجود دارد: اتصالات بهینه شده و غیر بهینه شده. ایدهی خوبی است که عبارات مربوطه را به همان اندازه سادهتر حفظ کنید. زیرا موتور QML برای ارزیابی عبارات از یک ارزیابی ساده و بهینه شده استفاده میکند که میتواند مشخص کند تا نیازی به تغییر آن در محیط جاوا اسکریپت نباشد. این اتصالات بهینه سازی شده بسیار کارآمدتر از اتصالات پیچیده تر (غیر بهینه سازی شده) هستند. الزامات اساسی نیز برای این گونه اتصالها این است که اطلاعات نوع هر نماد که به آن دسترسی دارد باید در زمان کامپایل شناخته شده باشد. عواملی که باعث جلوگیری از به حداکثر رساندن بهینه سازی در عبارات اتصالات میشود: تعریف متغیرهای واسط توسط جاوا اسکریپت دسترسی به خواص var صدا زدن توابع جاوا اسکریپت ساخت (آغاز یا خاتمه یافتن) و یا تعریف توابع در میان عبارت اتصالات دسترسی به خواص (پراپرتیهای) خارج از محدوده ارزیابی فوری نوشتن درمورد سایر عوامل به عنوان عوارض جانبی توجه داشته باشید، زمانی اتصالات سریعتر میشوند که نوع اشیاء و خواصی که با آنها کار میکنند مشخص شده باشند. این به این معنی است که، خواص غیرنهایی (non-final) ممکن است در بعضی موارد کُندتر باشد. (جایی که ممکن است یک خاصیت تغییر کرده باشد). محدودههایی ای که برای ارزیابی فوری میتوان در نظر گرفت قسمت زیر هستند: ارزیابی در خاصیت عبارتهای دامنهی یک شیء (برای عبارتهای اتصال، این است که شیء به کدام یک از خاصیتهای اتصال تعلق دارد). ارزیابی در شناسههای هر یک از اشیاء موجود در کامپوننت (جزء) ارزیابی در خاصیتهای ریشهی آیتم در یک کامپوننت (جزء) شناسههای اشیاء از دیگر کامپوننتها و خاصیتهای هر یک از اشیاء، مانند نمادهای تعریف شده و یا وارد شده از طرف جاوا اسکریپت در محدوده ی ارزیابی فوری نیستند. به این ترتیب اتصالاتی که به این موارد مربوط هستند نمیتوانند بهینه سازی شوند. نکته: توجه داشته باشید که اگر نمیتوانید اتصالات مورد نظر خود را توسط موتور QML بهینهسازی کنید، در این صورت باید آن را در محیط کامل جاوا اسکریپت بهینه سازی نمایید. نوع تبدیل (Type-Conversion) یک مزیت عمده برای استفاده از جاوا اسکریپت این است که در اغلب موارد، هنگامیکه به یک ویژگی از نوع QML دسترسی پیدا میشود، یک شیء جاوا اسکریپت با منبع حاوی سیپلاسپلاس پایه (یا یک مرجع آن) ایجاد میگردد. در بیشتر موارد، این عمل بهنسبت کمهزینه است، اما در سایر موارد میتواند بسیار پرهزینه باشد. یک مثال از پرهزینه بودن آن، ارجاع کردن QVariantMap و Q_PROPERTY به ویژگی نوع QML است. لیستها نیز میتوانند هزینهبالایی داشته باشند. اگرچه دنبالهی انواع خاص (QList از int، qreal، bool، Qstring و QUrl) باید کمهزینه باشد. تبدیل انواع دیگر لیست هزینهی زیادی دارد (ایجاد آرایهی جدید جاوا اسکریپت و افزودن تک به تک انواع جدید، با تبدیل هر نوع از نمونهی نوع سیپلاسپلاس به مقدار جاوا اسکریپت). رفع سازی خواصها تفکیک پذیری در خواص (پراپرتیها) زمان بر است. در حالی که در بعضی از موارد نتیجه آن میتواند ذخیره شده و دوباره مورد استفاده قرار بگیرد. بهتر است همیشه از انجام کارهای غیر ضروری جلوگیری شود. در مثال زیر، ما یک بلوک کد داریم که اغلب اجرا میشود (در این مورد، آن شامل یک حلقه صریح است؛ اما برای مثال میتوان آن را با یک عبارت پیوند و مورد ارزیابی قرار داد). در این مثال مشکل را با در نظر گرفتن شناسه "rect" و خاصیت رنگ "color" آن را چندین بار تغییر و تولید میکنیم. این مثال کاری که میخواهیم را انجام میدهد، اما روش بهینه شده ای نیست بنابراین مثال زیر بسیار بد خواهد بود: import QtQuick 2.3 Item { width: 400 height: 200 Rectangle { id: rect anchors.fill: parent color: "blue" } function printValue(which, value) { console.log(which + " = " + value); } Component.onCompleted: { var t0 = new Date(); for (var i = 0; i < 1000; ++i) { printValue("red", rect.color.r); printValue("green", rect.color.g); printValue("blue", rect.color.b); printValue("alpha", rect.color.a); } var t1 = new Date(); console.log("Took: " + (t1.valueOf() - t0.valueOf()) + " milliseconds for 1000 iterations"); } } برای اینکه کد فوق بهینه سازی شود بهتر است به صورت زیر باشد: import QtQuick 2.3 Item { width: 400 height: 200 Rectangle { id: rect anchors.fill: parent color: "blue" } function printValue(which, value) { console.log(which + " = " + value); } Component.onCompleted: { var t0 = new Date(); for (var i = 0; i < 1000; ++i) { var rectColor = rect.color; // resolve the common base. printValue("red", rectColor.r); printValue("green", rectColor.g); printValue("blue", rectColor.b); printValue("alpha", rectColor.a); } var t1 = new Date(); console.log("Took: " + (t1.valueOf() - t0.valueOf()) + " milliseconds for 1000 iterations"); } } فقط این تغییر ساده باعث بهبود عملکرد قابل توجهی میشود. بنابراین، توجه داشته باشید که کد بالا را میتوان حتی بهبود بیشتری داد (از آنجا که ویژگی مورد نظر هرگز در طول پردازش حلقه تغییر نکرده است)، با بالا بردن دقت خارج از حلقه، به صورت زیر است: import QtQuick 2.3 Item { width: 400 height: 200 Rectangle { id: rect anchors.fill: parent color: "blue" } function printValue(which, value) { console.log(which + " = " + value); } Component.onCompleted: { var t0 = new Date(); var rectColor = rect.color; // resolve the common base outside the tight loop. for (var i = 0; i < 1000; ++i) { printValue("red", rectColor.r); printValue("green", rectColor.g); printValue("blue", rectColor.b); printValue("alpha", rectColor.a); } var t1 = new Date(); console.log("Took: " + (t1.valueOf() - t0.valueOf()) + " milliseconds for 1000 iterations"); } } پیوند خاصیتها (Property Binding) در صورتی که خواص مرجع هر یک از اتصالات تغییر یابند، به آن خاصیت متصل دوباره ارزیابی خواهد شد. به همین ترتیب، عبارات خواص باید به همان اندازه ساده باشند. اگر شما یک حلقه دارید که در آن پردازشی را انجام میدهید، اما تنها نتیجه نهایی پردازش مهم است، اغلب بهتر است که موقتاً آن را بهروز کرده و در صورت نیاز آن را برای بهروز رسانی یک خاصیت مورد نیاز اختصاص دهید. این کار به منظور جلوگیری از ارزیابیهای مجدد بسیار مفید خواهد بود. مثال ذکر شده زیر این نکته را نشان میدهد که بسیار بد پیاده سازی شده است: import QtQuick 2.3 Item { id: root width: 200 height: 200 property int accumulatedValue: 0 Text { anchors.fill: parent text: root.accumulatedValue.toString() onTextChanged: console.log("text binding re-evaluated") } Component.onCompleted: { var someData = [ 1, 2, 3, 4, 5, 20 ]; for (var i = 0; i < someData.length; ++i) { accumulatedValue = accumulatedValue + someData[i]; } } } حلقه ای که در رویداد onCompleted میباشد، موجب میشود تا خاصیت متن text به تعداد ۶ بار مجدداً مورد ارزیابی قرار بگیرد (که در نتیجه هر گونه پیوند مرتبط با مقدار متن متکی است) همچنین کنترلر سیگنال onTextChanged هر یک را مجدداً ارزیابی میکند و این موجب میشود متن هر بار نمایش داده شود. این امر ضروری نیست چرا که هدف ما دسترسی به ارزش نهایی آن خواهد بود. روش پیشنهادی به صورت زیر خواهد بود: import QtQuick 2.3 Item { id: root width: 200 height: 200 property int accumulatedValue: 0 Text { anchors.fill: parent text: root.accumulatedValue.toString() onTextChanged: console.log("text binding re-evaluated") } Component.onCompleted: { var someData = [ 1, 2, 3, 4, 5, 20 ]; var temp = accumulatedValue; for (var i = 0; i < someData.length; ++i) { temp = temp + someData[i]; } accumulatedValue = temp; } } بارگذاریها و منابع مرتبط به تصاویر تصاویر بخش مهمی از رابط کاربری هستند. متأسفانه، به دلیل زمان بارگیری آنها، میزان حافظه ای که مصرف میکنند نیز قابل توجه است. بنابراین توجه داشته باشید که در صورتی که اپلیکیشن شما شامل تصاویری با اندازه بزرگتر هستند، اما شما آن را در اندازهی کوچکتر از واقعی خود نشان میدهید. در این صورت بهتر است اندازه سورس آن را نیز مشخص کنید که در خاصیت "sourceSize" مشخص میشود. این کار باعث میشود تا مطمئن شویم عنصور تولید شده با مقیاس کوچکتری در حافظه نگهداری میشود. البته مراقب این نیز باشید که تغییر اندازه سورس موجب میشود تصویر دوباره بارگیری شود. بارگیری غیرهمزمان (Asynchronous) معمولاً برنامههای زیبا و با کیفیت دارای تصاویر با کیفیت نیز هستند، بنابراین لازم است تا اطمینان حاصل شود که بارگیری یک تصویر یک رشته از UI را بلوک یا مسدود نمیکند. خاصیت asynchronous در نوع QML Image را با مقدار true تنظیم کنید تا بارگیری غیرهمزمان از تصاویر بر روی سیستم فایلهای محلی بارگیری شود. این کار از وارد کردن فشار بر روی تصاویر و رابط کاربری جلوگیری خواهد کرد که نتیجهی آن حفظ زیبایی رابط کاربری شما در زمان بارگذاری تصاویر خواهد شد. نکات ریز اما مهم از سایه پردازیها و تصاویری که در حین زمان اجرا در ترکیب تصاویر شما ایجاد میشوند دوری کنید. توجه داشته باشید که در صورت عدم نیاز از خاصیت smooth استفاده نکنید. فعال سازی این خاصیت موجب تولید تصاویر صاف و با کیفیت میشود که در سخت افزاهای قدرتمند توصیه میشود. در سخت افزارهای ضعیف تولید تصاویر صاف زمانبر خواهد بود و در صورتی که اندازهی تصویر واقعی نباشد بر روی نتیجهی آن تاثیری نخواهد داشت. از نقاشی و یا رسم طرح بر روی یک ناحیه به صورت پشت سر هم اجتناب کنید. از نوع Item به عنوان عنصر ریشه به جای Rectangle استفاده کنید. عناصر موقعیت با لنگر استفاده از لنگرها (anchors) به جای اتصالات (bindings) به یک آیتم موقعیت نسبتاً تاثیر بیشتری خواهد داشت. برای مثال برای اتصال موقعیت rect2 به rect1 را توجه کنید: import QtQuick 2.3 .... Rectangle { id: rect1 x: 20 width: 200; height: 200 } Rectangle { id: rect2 x: rect1.x y: rect1.y + rect1.height width: rect1.width - 20 height: 200 } .... این کار را میتوان توسط لنگرها به طور بسیار موثری انجام داد: import QtQuick 2.3 .... Rectangle { id: rect1 x: 20 width: 200; height: 200 } Rectangle { id: rect2 height: 200 anchors.left: rect1.left anchors.top: rect1.bottom anchors.right: rect1.right anchors.rightMargin: 20 } .... تنظیم موقعیت توسط اتصالات (با اختصاص دادن عبارتهای اتصال به محورهای x و y طول و ارتفاع به عنوان خواص یک شیء به جای استفاده از لنگرها) هرچند به حداکثر انعطاف پذیری اجازه میدهد اما نتیجه تولیدی آن نسبتاً کُند است. در نظر داشته باشید که اگر شیء شما به صورت داینامیک (پویا) تغییر پیدا نمیکند، روش مناسب تغییر موقعیت استفاده از خاصیتهای y، x، width و height میباشد که متناسب و وابسته به والد خود میباشد. در صورتی که میخواهید وابستگی ایجاد نشود بهتر است از لنگرها استفاده کنید. در مثال زیر، اشیاء مستطیل (Rectangle) فرزند در یک مکان مشابهی قرار گرفته اند، اما کدهای مرتبط به لنگرها (anchors) نشان میدهد که موقعیت آن شیء به صورت ثابت مقدار دهی شده است. import QtQuick 2.3 Rectangle { width: 60 height: 60 Rectangle { id: fixedPositioning x: 20 y: 20 width: 20 height: 20 } Rectangle { id: anchorPositioning anchors.fill: parent anchors.margins: 20 } } مدلها و نمایشها اکثر برنامه های کاربردی (Application) حداقل از یک مدل (Model) تغذیه داده را به نمایه (View) ارسال میکنند. بعضی از مواردی که توسعه دهندگان برای به حداکثر رساندن عملکرد به آنها باید توجه داشته باشند وجود دارد. مُدلهای سفارشی سمت سیپلاسپلاس این بسیار خوب است که شما مدلهای دادهای سفارشی خود را سمت ++C برای استفاده ار نمایهی QML بنویسید. اما باید توجه داشته باشید این کار به شدت بستگی به کاربرد آن در موقعیت خودش را دارد که برخی از دستورالعمل های کلی به شرح زیر هستند: تا جایی که ممکن است ناهمزمان باشد. تا جای ممکن بصورت ناهمزمان، تمام پروسههای پردازشی را در یک نخ با (اولیت پایین) انجام دهید. عملیات بکاند را به صورت دسته ای انجام دهید تا (به طور بالقوه آهسته) عملهای I/O و IPC به حداقل برسد. از یک پنجره مجزا برای نتایج کَش که پارامترهایش به پروفایلینگ کمک میکنند، استفاده کنید. این مهم است که توجه داشته باشیم استفاده از یک نَخ (Thread) کارآمد با کمترین اولویت توصیه میشود تا خطر قحطی (starving) را در نخ های رابط کاربری به حداقل برساند. همچنین به یاد داشته باشید که مکانیزم هماهنگ سازی و قفل کردن میتواند عامل مهمی برای عملکرد آهسته باشد، بنابراین لازم است از اعمالِ قفل غیر ضروری جلوگیری (صرف نظر) شود. نوع لیست مُدل (ListModel) در QML کیوامال (QML) یک نوع ListModel ای را فراهم میکند که میتواند برای ارسال داده به یک نوع از ListView استفاده شود. این باید برای اکثر موارد مناسب باشد و تا زمانی که به درستی استفاده شود نسبتاً عملکرد درستی داشته باشد. تجمع در داخل یک نخ عناصر ListModel را می توان در یک نخِ کاری (با اولویت پایین) در JavaScript جابجا کرد. توسعهدهنده باید صریحاً متد sync() را که به عنوان یکی از خواص موجود در ListModel میباشد را داخل یک WorkerScript صدا بزند تا تغییرات همزمان با نَخ اصلی صورت بکیرد. جهت کسب اطلاعات بیشتر مستندات WorkerScript را مطالعه کنید. لطفاً توجه داشته باشید که با استفاده از یک عنصر WorkerScript یک موتور جاوا اسکریپت جداگاه ایجاد میشود (چرا که موتور جاوا اسکریپت در هر نَخ (Thread) میباشد). این باعث افزایش مصرف حافظه خواهد شد. چرا که عناصر متعدد (چندگانه) WorkerScript همه از یک نَخ استفاده خواهند کرد. بنابراین تاثیر شدیدی در حافظهی استفاده شده توسط وُرکر دوم و سوم وارد خواهد کرد که در زمان اجرای برنامه و وُرکر اسکریپت اول تاثیر آن بسیار ناچیز خواهد بود. از نقشهای (Roles) پویا استفاده نکنید عنصر ListModel در QtQuick 2 بسیار کارآمدتر از QtQuick است. بهبود عملکرد عمدتاً از پیش فرضهای مربوط به نوع نقشها (Roles) در هر عنصر در یک مدل داده میشود. اگر نوع آن تغییر نکند، عملکرد ذخیره سازی به طور چشمگیری بهبود مییابد. اگر نوع قابلیت تغییر به صورت پویا از عنصر به عنصر دیگری را داشته باشد، بهینه سازی غیر ممکن شده و عملکرد (پرفرمنس - کارآیی) مدل به اندازهی بزرگی بدتر و کُندتر خواهد شد. بنابراین به صورت پیشفرض حالت داینامیک غیر فعال بوده و توسعهدهنده خود باید خاصیت dynamicRoles را به عنوان یکی از خاصیتهای ListModel فعال کند. البته به شدت پیشنهاد میشود برنامهی خود را از اول طراحی کنید اما این قابلیت را فعال نکنید. نمایهها (Views) توجه داشته باشید که نماینده (دلیگیتس یا delegates) باید به طور ساده حفظ شود. به اندازهی کافی از انواع QML در این خاصیتهای ضروری استفاده کنید. هرگونه قابلیت اضافه که بلافاصله مورد استفاده قرار نمیگیرد نیاز نیست. برای مثال اگر نیاز است اطلاعات بیشتری در موقع کلیک بر روی آیتم نمایش داده شود، نیاز نیست که همان لحظه ایجاد و بر روی آیتم نمایان شوند. نباید تا قبل از زمان نیاز ایجاد شوند. لیست زیر، خلاصهی خوبی از مواردی است که باید هنگام طراحی بر روی خاصیت delegate در نظر داشته باشید: عناصری که کمتر در خاصیت delegate هستند، سریعتر می توانند ایجا شوند، و بنابراین سریعتر میتوانند در نمایه (view) مشاهده و اسکرول شوند. تعداد پیوندها (اتصالات) را در delegate به حداقل تعدادشان نگه داری کنید. از لنگرها (anchors) به جای اتصال برای موقعیتهای نسبی در یک delegate استفاده شود. از به کار گیری عناصر ShaderEffect در delegate اجتناب شود. هرگز خاصیت clip را در خاصیت delegate فعال نکنید. نکته: شما میتوانید ویژگی cacheBuffer یک نمایه (view) را تنظیم کنید تا اجازه ایجاد و ارسال غیر مستقیم به delegate خارج از ناحیه قابل مشاهده را ایجاد کنید. استفاده از cacheBuffer برای delegate های نمایشی توصیه می شود. توجه داشته باشید که خاصیت delegate یک cacheBuffer اضافی را در حافظه نگه میدارد، بنابراین مقدار حاصل از استفاده cacheBuffer باید با استفاده از حافظه اضافی متعادل شود. توسعهدهندگان خود باید از معیارهای سنجش (بنچ مارکها) برای یافتن بهترین مقدار مناسب برای استفاده را انجام دهند. چرا که افزایش حافظه ناشی از استفاده cacheBuffer میتواند در بعضی از موارد نادر، باعث کاهش نرخ فریم در هنگام پیمایش (اسکلرول) شود. جلوههای بصری فناوری کیوت کوئیک ۲ شامل چند ویژگی است که به توسعهدهندگان و طراحان اجازه میدهد تا رابط کاربری فوق العاده جذاب ایجاد کنند؛ تغییرات پویا (داینامیکی) و همچنین جلوههای بصری میتوانند برای یک اثر بزرگ در برنامهی کاربردی مورد استفاده قرار گیرد. اما هنگام استفاده از بعضی از ویژگیهای QML، باید نکاتی را در نظر گرفت که میتوانند دلالت بر کارآیی (پرفرمنس) را داشته باشند. انیمیشنها به طور کلی، متحرک سازی (انیمیشن سازیِ) یک خاصیت (پراپرتی) میتواند سبب شود تا اتصالاتی که به یک خاصیت دیگر اشاره میکند را مجدداً مورد ارزیابی قرار گیرد. معمولاً این مورد مطلوب است، اما در برخی از موارد ممکن است بهتر باشد قبل از انجام متحرک سازی (انیمیشن سازی) اتصالات را غیر فعال کنید، و سپس آن انیمیشن را تکمیل کنید. از اجرای کدهای جاوا اسکریپت در طول یک انیمیشن اجتناب کنید. برای مثال، اجرای یک عبارت پیچیده جاوا اسکریپت برای هر فریم از انیمیشنِ یک خاصیت مانند x باید اجتناب شود. توسعهدهندگان باید در استفاده از انیمیشنهای اسکریپتی دقت کنند، زیرا آنها در یک نخ اصلی اجرا میشوند (در نتیجه در صورتی که اجرا و تکمیل انیمیشن بیش از حد طول بکشد)، ممکن است فریمهایی را پرش کرده و موجب کاهش کارآیی اصلی آن شود. ذَرات، پارتیکل (Particles) ماژول Qt Quick Particles اجازه میدهد تا ذراتی را برای زیبایی هرچه بهتر رابط کاربری اضافه شود. با این حال، هر پلتفرم دارای قابلیتهای سخت افزاری مختلفی است و ماژول Particles قادر به محدود کردن پارامترهای سخت افزاری شما نمیباشد. بنابراین زمانی که شما ذرات بیشتری برای تولید (رندر) میخواهید (هرچه بزرگتر می شوند)، سرعت بیشتری برای پردازش سخت افزار گرافیکی شما نیاز خواهد بود تا بتواند سرعت تولید آنها را با نرخ ۶۰ فریم بر ثانیه اجرا کند. بنابراین ذرات بیشتر خواهان پردازندههای مرکزی سریعتری میباشند. بنابراین، این بسیار مهم است که تمام ذرات و اثرات آنها را بر روی پلتفرمهای هدف خود با دقت آزمایش کنید، تا برای کالیبره کردن تعداد و اندازه ذرات قابل تولید با نرخ ۶۰ فریم به نتیجه قابل قبول برسید. لازم به ذکر است که برای جلوگیری از شبیه سازی غیر ضروری یک سیستم ذره را میتوان غیر فعال کرد (به عنوان مثال عنصری را غر قابل مشاهده کنید) این کار باعث میشود تا شبیه سازیهای غیر ضروری غیر فعال شوند. عملکرد سیستم ذرات با مقایس تعداد ذرات نگه داری میشود. پس از نمونه برداری از اثر مورد نظر، با کاهش مقدار ذرات، عملکرد آن را میتوان بهبود داد. برعکس، اگر عملکرد آن به خوبی و در حد قابل قبول باشد، میتوان تعداد ذرات را تا زمانی که در آن نقطه قرار میگیرد افزایش دهید(این کار باعث بهبود خواهد شد). همانند ShaderEffect، عملکرد سیستم ذرات تا حد زیادی وابسته به سخت افزار گرافیکی است که در حال اجرا میباشد. همچنین دقت کنید مقدار دهی loop در مصرف پردازنده بسیار موثر است، برای مثال اگر از SequentialAnimation استفاده میکنید، بهتر است مقدار loop را محدود در نظر بگیرید. در صورتی که مقدار آن برابر با Animation.Infinite باشد درصد قابل توجهی از پردازنده را درگیر خود خواهد کرد. کنترل طول عمر عنصر با تقسیم کردن یک برنامه به اجزای ساده، ماژولار، هرکدام از آنها در یک فایل QML منعکس میشوند، میتوانید زمان راه اندازی برنامه را سریعتر و کنترل بیشتری از استفاده از حافظه را به دست آورده و تعداد عناصر فعال اما غیر قابل مشاهده را در برنامه خود کاهش دهید. به طور کلی سعی کنید برای هر ماژول یا بخشی از برنامه یک سند جداگانه از QML را فراهم کنید. مقداردهی اولیه سریع (از روی تنبلی)! موتور QML برخی چیزها را به صورت هوشمندانه (یا زیرکانه) انجام میدهد تا اطمینان حاصل شود که بارگذاری و مقدار دهی اولیه اجزاء باعث نمیشود تا فریمها از بین بروند. با این حال هیچ راهی برای کاهش زمان راه اندازی بهتر از این وجود ندارد که شما کارهایی را تا زمانی که به آنها نیاز ندارید را انجام ندهید و از آنها اجتناب کنید. این ممکن است با استفاده از اجزای پرکاربردی مانند نوع Loader یا ساخت کامپوننت (جزء)های پویا (Dynamic Object Creation) انجام شود. استفاده از بارکننده (لودر - Loader) لودر یک عنصری است که اجازه میدهد بارگذاری و تخلیه پویا بر روی اجزاء انجام شود. با استفاده از ویژگی "active" در Loader، مقدار دهی اولیه میتواند تا زمان لازم انجام شود. با استفاده از تابع setSource() مقدار دهی اولیه میتواند تامید شود. تنظیم خاصیت asynchronous بر روی مقدار true میتواند تاثیر بر روی بهبود عملکرد بر روی کامپوننت (جزء) در زمان نمونه سازی داشته باشد. استفاده از سازندهی پویا توسعه دهندگان میتوانند از یک تابع Qt.createComponent() برای ایجاد یک مولفه به صورت پویا در زمان اجرا از داخل جاوا اسکریپت استفاده کنند و سپس createObject() را برای نمونه سازی آن، فراخوانی کنند. نابود کردن عناصر استفاده نشده عناصری که مخفی هستند به عنوان فرزندی از عناصر غیر بصری محسوب میشوند. برای مثال زمانی که یک زبانه از TabBar یا TabWidget انتخاب شده است و نمایش داده میشود به لایلی باید سریع مقدار دهی اولیه شوند و زمانی که از آن به مدت طولانی استفاده نمیشود و این خود باعث بارگذاری اضافی است. بنابراین در صورت استفاده از این روش جهت جلوگیری از این هزینه مداوم در زمان اجرا ( که شامل تولید انیمیشن، اتصالات، رندرینگ و غیره...) به صورت خودکار حذف میشوند. نکته: یک آیتم بارگذاری شده با یک نوع عنصر Loader ممکن است توسط تنظیمات مجدد خاصیت source یا sourceComponent آزاد شود. در حالی که موارد دیگر ممکن است به صورت صریح با فراخوانی متد destroy() بر روی آنها منتشر شود. در بعضی از موارد ممکن است لازم باشد آیتم فعال را ترک کرده و یا حداقل آن را نامرئی کنید. این کار موجب میشود سرعت برنامهی شما بهینه شود. تولید (رندرینگ) Rendering گرافیک صحنهای که برای رندر در کیوت کوئیک ۲ استفاده میشود، رابط کاربری بسیار متحرک را به صورت فیزیکی در ۶۰ فریم بر ثانیه ارائه میکند. با این حال برخی چیزها به طور چشمگیری در عملکرد رندرینگ کاهش مییابند. توسعه دهندگان باید مراقب باشند تا از این مشکلات در هر جا که ممکن است اجتناب کنند که به برخی از آنها اشاره شده است. کلیپ کردن (Clipping) کلیپ کردن به صورت پیشفرض غیرفعال است و توصیه میشود تنها زمانی که به آن نیاز دارید فعالش کنید. کلیپ کردن یک اثر بصری دارد، نه بهینه سازی! بنابراین این ویژگی پیچیدگی بیشتری را برای رندرینگ افزایش میدهد. اگر کلیپ فعال باشد، اجزای تولید شده خود و دیگر اجزای فرزندش را به محدوده خود متصل خواهد کرد. این باعث میشود رندرینگ در آن بخش متوقف شده و آن بخش از اشیاء مرتبط و منظم دیده شوند. نکته مهم این است که کلیپ کردن در داخل delegate بسیار نامناسب است و باید از این کار اجتناب شود. چرا که موجب کاهش کارآیی برنامه خواهد شد. نقاشی بیش از اندازه و عناصر نامرئی اگر شما عناصری دارید که توسط عناصر دیگری (مات) یا پوشانیده شده اند، بهتر است از خاصیت visible استفاده کرده و آن را به مقدار false تنظیم کنید. برای مثال در زبانههایی که به صورت پیشفرض یکی از آنها فعال هستند و زبانههای دیگر تا زمان انتخاب مخفی! در این صورت بهتر است آیتمهای آنها به از طرف والد آنها مخفی شوند تا در زمان اجرا بابت نمایش مواردی که مخفی هستند هزینهای نشود. شفاف در مقابل مات محتوای مبهم (مات) عموماً بسیار سریعتر از محتوای شفاف هستند. دلیل این امر این است که محتوای شفاف نیاز به ترکیب (مخلوط) کردن دارند و سیستم رندر کننده به مراتب میتواند نوع مات را بهتر بهینه سازی نماید. یک تصویر با یک پیکسل شفاف به طور کامل به عنوان یک نتیجه کاملاً شفاف تلقی میشود، حتی اگر عمدتاً مات باشد. همین امر برای نوع BorderImage با لبه های شفاف درست است. سایهها نوع ShaderEffect باعث میشود که کد درون خطی GLSL را به صورت یکپارچه در یک برنامه Qt Quick با سربار بسیار کم قرار دهید. با این حال مهم است که بدانید، که قِطعه برنامه نیاز به اجرا برای هر یک از پیکسلها در شکل تولید شده را دارد. هنگام استقرار بر روی یک سخت افزار با توان پایین، شیدرها مقدار زیادی از پیکسلها را پوشش میدهند برای جلوگیری از عملکرد ضعیف، باید یک قطعه شیدر را برای چند دستورالعمل جهت جلوگیری از پرفرمنس ضعیف نگهداری کنید. شیدرهای نوشته شده در GLSL اجازه میدهد تا تبدیلات و جلوههای پیچیدهتری را تولید کنید. با این حال باید با دقت بسیاری از آنها استفاده کرد. استفاده از ShaderEffectSource باعث از پیش رندر شدن صحنه به FBO قبل از کشیده شدن آن میشود . این سربار اضافی میتواند بسیار پرهزینه باشد. تخصیص و جمع آوری حافظه مقدار حافظهای که توسط یک برنامه اختصاص داده میشود و اینکه آن حافظه چگونه اختصاص داده میشود شامل ملاحظات بسیار مهمی هستند. صرف نظر از نگرانیهای مربوط به خارج از حافظه در دستگاههای محدود به حافظه، تخصیص حافظه در پُشته به عنوان یک عمل محاسباتی نسبتاً گران میباشد. در این میان استراتژیهای اختصاصی تخصیص حافظه میتواند باعث افزایش تقسیم دادهها در صفحات شود. خوشبختانه، جاوا اسکریپت از روش مدیریت حافظه خودکار در پُشته (Heap) در قالب GC پشتیبانی میکند که دارای برخی از مزیتها است. اما با این حال دلالت بر مهم بودن برخی موارد دارد. یک برنامه نوشته شده در QML حافظه را از هر دو پُشته از سمت مدیریت حافظه تحت ++C و JavaScript مدیریت میکند. توسعه دهنده نرمافزار باید در رابطه با هر یک از آنها به منظور به حداکثر رساند پرفرمنس آگاه باشد. نکاتی برای توسعهدهندگان برنامه QML نکات و پیشنهادات موجود در این بخش تنها در قالب دستورالعمل هستند و ممکن است در همه شرایط قابل اجرا نباشند. با استفاده از معیارهای تجربی و بررسی بنچ مارکها و همچنین آنالیز و همچنین با استفاده از ومعیارهای تجربی برنامه خودتان بهترین تصمیم ممکن را بگیرید. اگر برنامه شما شامل نمایه (View) های متعدد (به عنوان مثال زبانههای چندگانه) میباشد اما در هر زمان تنها یکی از آنها مورد نیاز است در این صورت برای کم کردن حافظه مصرفی میتوانید از روش مقداردهی سریع (از روی تنبلی) استفاده کنید ? که در بالا به آن اشاره شده است. نابود سازی اشیاء ای که مورد استفاده قرار نمیگیرند اگر شما از روش ساده بارگیری کامپوننتها و یا ساخت اشیاء به صورت پویا در طول یک عبارت جاوا اسکریپتی استفاده میکنید، بهتر است آنها را به صورت دستی توسط متد destroy() نابود کنید. این بهتر از آن است که منتظر باشید تا به صورت خودکار سیستم GC آنها را جمع آوری و نابود کند. در زمانی که نیاز نیست به صورت دستی عمل GC (بازیافت حافظه) را انجام ندهید در اکثر موارد، دستیابی به مجموعه زبالهها به منظور دستیبای به آن نیست. زیرا این کار به مدت زیادی نخهای سمت رابط کاربری را مسدود میکند. این کار باعث میشود فریمها و پرشهایی در انیمیشنهای متحرک به وجود آید که باید از اینگونه هزینه ها اجتناب شود. به طور کلی باید توجه داشته باشید که به صورت مستقیم و دستی همه جا نباید اقدام به نابود سازی حافظه اخصاص یافته شده کنید. اجتناب از اتصال پیچیده گذشته از اینکه اتصالات پیچیده موجب کاهش پرفرمنس (کارایی) میشود استفاده از آنها (برای مثال، زمانی که نیاز است ارزیابی جداگانه تحت کدهای جاوا اسکریپت شود) به صورت پیچیدهای حافظه بیشتری را در هر دو پُشته ++C و JavaScript برای بهینه سازی محاسبات اختصاص میدهند. بنابراین نیاز نیست همیشه از اتصالات پیچیده و ارزیابی آنها تحت JS استفاده کرد. اجتناب از تعریف چند نوع ضمنی یکسان اگر یک عنصر QML یک خصوصیت سفارشی تعریف شده در QML داشته باشد، آن نوع خاصی و ضمنی خود را میگیرد. این مورد در بخش بعدی بیشتر توضیح داده شده است. اگر چندین نوع ضمنی یکسان در یک جزء درون خطی تعریف شده باشند، موجب هدررفتن بخشی از حافظه خواهند شد. در این وضعیت معمولاً بهتر است که جزء را بهصورت صریح تعریف کنیم که بعدا میتواند دوباره استفاده شود. تعریف یک اخاصیت سفارشی اغلب می تواند در بهینه سازی عملکرد سودمندی داشته باشد (برای مثال، برای کاهش تعداد پیوندهایی که مورد نیاز است یا دوباره ارزیابی میشوند)، یا میتواند ماژولار بودن و قابلیت نگهداری یک جزء را بهبود بخشد. در این موارد، استفاده از خواص سفارشی پیشنهاد میشود. با این حال، نوع جدید باید، اگر از بیش از یک بار استفاده می شود، به جزء خود (فایل .qml) به منظور حفظ حافظه، تقسیم شود. استفاده مجدد از اجزای موجود اگر شما در حال تعریف یک جزء جدید هستید، لازم است دوباره بررسی کنید که چنین جزئی در پلتفرم شما وجود دارد یا خیر. در غیر این صورت شما باید موتور QML را مجبور به ساخت و ذخیره سازی نوع داده برای یک نوع که نیاز است کنید که به عنوان یک نوع تکراری که از اجزای موجود می باشد بارگذاری میشود. به جای کتابخانههای اسکریپتی پراگما از انواع تک تک (singleton) استفاده کنید. اگر از یک اسکریپت کتابخانه pragma برلی ذخیره داده های نمونه استفاده میکنید، به جای استفاده از یک نوع تک تکی از QObject استفاده کنید. نتیجه آن در کارآیی بهتر تاثیر گذار خواهد بود و باعث میشود حافظه کوچکتری در پُشتهی جاوا اسکریپت مورد استفاده قرار گیرد. اختصاص دادن حافظه در یک برنامه QML استفاده از حافظه یک برنامه مبتنی بر QML ممکن است به دو بخش تقسیم شود: استفاده از پُشته سمت ++C و پشتهی سمت JavaScript میباشد. برخی از حافظه اختصاص داده شده در هر یک از اجزاء غیرقابل اجتناب خواهند بود. به عنوان آن که توسط موتور QML یا موتور جاوا اسکریپت اختصاص داده میشود. در حالی که بقیه آن وابسته به تصمیمات گرفته شده توسط توسعه دهنده اپلیکیشن میباشد. پشته در ++C شامل موارد زیر خواهد بود: سربار ثابت و اجتناب ناپذیر از موتور QML (پیاده سازی ساختارهای داده، اطلاعات زمینه و غیره). اطلاعات هر جزء کامپایل شده و نوع دادهها، شامل هر یک از انواع و فرا داده هایی میباشد، که توسط موتور QML بسته به نوع ماژولها و کامپوننتهایی است که توسط اپلیکیشن بارگیری میشوند. هر شیءای که در دادههای سی++ (شامل مقادیرِ خاصیت) به همراه هر یک از عناصر متا آبجکت هستند که وابسته به کامپوننت (اجزای) معرفی شده توسط اپلیکیشن میباشند. هر داده ای که به طور خاص توسط QML اختصاص داده میشود که شامل کتابخانههای وارد شده نیز هستند. پشته در JavaScript شامل موارد زیر خواهد بود: سربار ثابت و اجتناب ناپذیر از موتور QML (خودش انواع از قبل ساخته شدهی جاوا اسکریپتی را دارد). سر بار ثابت شده و اجتناب ناپذیر از ادغام جاوا اسکریپت (توابع سازنده برای انواع داده های بارگذاری شده، قالبهای توابع، و غیره). اطلاعات مربوط به هر نوع و و دیگر انواع داخلی توسط موتور جاوا اسکریپت که در زمان اجرا تولید میشود. هر شیء ای که به عنوان داده جاوا اسکریپتی (خاصیتهای نوع var ، توابع جاوا اسکریپتی و هندلرهای سیگنال و عبارات بهینه نشده). متغیرهای اختصاص داده شده در زمان ارزیابی عبارت علاوه بر این، یک پشته جاوا اسکریپتی اختصاص یافته شده برای استفاده از نَخ اصلی و دیگری در پُشته جاوا اسکریپت برای استفاده در WorkerScript اختصاص یافته میشود. اگر یک اپلیکیشن از یک عنصر WorkerScript استفاده نکند متحمل به سربار گیری نخواهد شد. اندازه پشته در جاوا اسکریپت میتواند به چندین مگابایت برسد و بنابراین برنامههای نوشته شده برای دستگاه هایی که دارای محدودی حافظه هستند، ممکن است بهترین با اجتناب از عنصر WorkerScript باشد، با وجود سودمندی آن در مدلها لیستی، که به صورت یکپارچه ذخیره میشوند باشد. توجه داشته باشید که هر دو موتور QML و JavaScript به طور خوکار مخازن خود را از نوع داده های ملاحظه شده تولید خواهند کرد. هر کامپوننت (جزء) توسط یک برنامه بارگذاری میشود که یک نوع متمایز (صریح) بوده و هر عنصر (به جای کامپوننت) ویژگیهای سفارشی خود را در QML که به صورت ضمنی است تعریف میکند. مثال زیر را در نظر بگیرید: import QtQuick 2.3 Item { id: root Rectangle { id: r0 color: "red" } Rectangle { id: r1 color: "blue" width: 50 } Rectangle { id: r2 property int customProperty: 5 } Rectangle { id: r3 property string customProperty: "hello" } Rectangle { id: r4 property string customProperty: "hello" } } نمونههای قبلی مستطیلهای r0 و r1 دارای ویژگیهای اختصاصی (سفارشی) نبودند. بنابراین موتورهای جاوا اسکریپت و QML هر دو آنها را از همان نوع در نظر میگیرند. به عبارت دیگر هر دوی آنها به عنوان یک نوع صریح از Rectangle (مستطیل) در نظر گرفته میشوند. مستطیلهای r2، r3 و r4 هر یک از آنها با داشتن ویژگیهای اختصاصی خود هر کدام با انواع مختلف ضِمنی در نظر گرفته شدهاند. حتی اگر اطلاعات مربوط به ویژگیهای یکسانی داشته باشند. ملاحظات اختصاصی در عُمق حافظه هرگاه تصمیماتی در خصوص تخصیص دادن حافظه یا کارآیی آن به وجود آید، این مهم است که تاثیرات شدید در عملکرد پردازنده مرکزی و مخازن مربوط به آن، صفحه بندیهای سیستمعامل و بازیافت حافظه (GC) در جاوا اسکریپت را در نظر داشته باشید. بنابراین راه حلهای بالقوه باید با دقت بررسی شوند تا مطمئن شوید که بهترین مورد را انتخاب کردهاید. هیچ مجموعهای از دستور العملهای کلی نمیتواند یک درک جامع ای از اصول اساسی علوم رایانه را با یک دانش علمی از جزئیات پیاده سازی کرده و پلتفرمی که یک توسعهدهندهی نرمافزار در حال توسعه آن است را جایگزین کند. تقسیم بندی تقسیم بندی به عنوان یک مسأله برای توسعه در سیپلاسپلاس است. اگر توسعهدهنده برنامه هیچ نوع یا پلاگینی از سیپلاسپلاس را تعریف نکند، ممکن است آنها را در این بخش با خیال راحت نادیده بگیرند. با گذشت زمان، یک برنامه بخش بزرگی از حافظه را برای خود اختصاص داده و دادهها را به آن حافظه ارسال میکند و بعضی اوقات برخی از قسمت های آن را پس از اتمام استفاده آنها را آزاد میکند. این میتواند منجر به «حافظه آزاد» شده ای در تکههای غیر مجاور شود که نمیتواند برای برنامه های کاربردی دیگر توسط سیستمعامل مورد استفاده قرار گیرد. همچنین تاثیر شدیدی بر روی ذخیره سازی پنهان و دسترسی به ویژگیهای یک اپلیکیشن میگذارد. زیرا دادههایی که زنده هستند (در حال استفاده) هستند، ممکن است در بسیاری از صفحات مختلف حافظه فیزیکی گسترش یابند. این به نوبه خود میتواند سیستمعامل را مجبور به (swap) یا مبادله کند که میتواند سبب شود تا عمل I/O ایجاد شود که به شدت عمل آهستهای بشمار میآید. تقسیم بندی میتواند توسط دیگر موارد تخصیص دهنده حافظه، با کاهش میزان حافظهای که در هر زمان با دقتِ مدیریتِ زمان زندگیِ اشیاء مورد بررسی قرار گیرد. با تمیز کردن و باز سازی دورهای از حافظهها یا با استفاده از زمان اجرا بر روی حافظه از تجزیه آن میتوان جلوگیری کرد که توسط سیستمعامل بازیافت حافظه خودکار (GC) مانند جاوا اسکریپت ممکن است. بازیافت حافظه جاوا اسکریپت سیستم بازیافت حافظه به صورت خودکار را فراهم میکند. حافظه ای که در دسته جاوا اسکریپتی قرار دارد (بر خلاف پُشته در سیپلاسپلاس) متعلق به موتور خود جاوا اسکریپت است. این موتور به طور دورهای تمامی دادههای نا مشخص (غیر قابل استفاده) را در پُشتهی جاوا اسکریپت جمع آوری میکند. پیامدهای بازیافت حافظه بازیافت حافظه، مزایا و معایبی دارد. این به این معنی است که مدیریت عمر مفید شیء به صورت دستی اهمیت کمتری دارد. با این حال، این بدان معنی است که یک عمل بالقوه طولانی مدت ممکن است توسط موتور جاوا اسکریپت در زمانیکه که خارج از کنترل توسعهدهنده نرم افزار است آغاز شود. استفاده از پُشته در جاوا اسکریپت با دقت بسیاری توسط توسعهدهنده برنامه مورد توجه قرار می گیرد. لذا تکرار و مدت زمان بازیابی حافظه ممکن است تاثیر منفی بر تجربه نرمافزار داشته باشد. فراخوانی بازیابی حافظه یک برنامه نوشته شده در QML (به احتمال زیاد) در یک مرحلهای به بازیافت حافظه (GC) نیاز دارد. در صورتی که حجم حافظه آزاد شده کم باشد سیستم بازیافت خودکار حافظه توسط موتور جاوا اسکریپت انجام میشود. بعضی اوقات این کار در صورتی که توسعهدهندهی نرمافزار تصمیمی در مورد اینکه چه زمانی بازیافت حافظه را انجام دهند نگرفته باشد میتواند مناسب باشد. (اگر چه که معمولاً این مورد مطرح نمیشود). توسعهدهنده نرمافزار احتمالاً میداند که برنامه چه زمانی را به مدت قابل ملاحظهای بیکار است. اگر یک برنامه QML از حافظه بسیار زیادی از پُشته جاوا اسکریپت را مصرف کند، باعث میشود چرخه و تکرارهای مکرری در بازیافت حافظه صورت گیرد که در وظایف حساس بر روی کارآیی تاثیر خواهد گذاشت. مانند (لیست پیمایش، انیمیشنها، و غیره). توسعهدهنده نرمافزار ممکن است بهطور دستی به بازیافت حافظه در طول دوره صفر فعالیت کمک کند. دوره های بیکاری برای انجام بازیافت حافظه ایده آل هستند چراکه کاربر هیچگونه تضعیفی را در تجربه کاربری خود (فریمهای پرش شده، انیمیشنهای پرتحرک و نامنظم و غیره) حس نخواهدکرد؛ که این تضعیف تجربه، درنتیجه فراخوانی بازیافت حافظه به هنگام فعالیت برنامه رخ میهد. توسعهدهنده نرمافزار احتمالاً میداند که برنامه چه زمانی را به مدت قابل ملاحظهای برای بیکاری بکار میگیرد. اگر یک برنامه QML از حافظه بسیار زیادی از پُشته جاوا اسکریپت را مصرف کند، باعث میشود چرخه و تکرارهای مکرری در بازیافت حافظه صورت گیرد که در وظایف حساس بر روی کارآیی تاثیر خواهد گذاشت. مانند (لیست پیمایش، انیمیشنها، و غیره). از طرفی ممکن است توسعهدهنده با دستکاری بازیافت حافظه موجب تخریب آن شوند. بازیافت حافظه ممکن است به صورت دستی با فراخوانی gc() در جاوا اسکریپت اعمال شود. این باعث میشود یک چرخه بازیافت جامع از حافظه صورت بگیرد که ممکن است مدت زمانی بین چند صد تا بیش از هزار میلی ثانیه برای تکمیل آن سپری شود. بنابراین در صورت امکان باید از آن اجتناب شود. حافظه در مقابل کارآیی در بعضی موارد ممکن است که زمان پردازش حافظه برای سبک سنگین کردن افزایش مصرف حافظه کاهش یابد. برای مثال، ذخیره سازی نتیجه یک جستجوی نماد که در یک حلقه تنگ به یک متغیر موقت در یک عبارت جاوا اسکریپتی استفاده میشود که در بهبود ارزیابی این عبارت تاثیر قابل توجهی خواهد داشت. اما این شامل تخصیص یک متغیر موقت میباشد. در بعضی از موارد، این سبک سنگین کردن ممکن است معقول باشد (مانند موارد فوق، ک تقریباً همیشه منطقی هستند)، اما در موارد دیگر ممکن است بهتر باشد تا اجازه دهیم تا پردازش طول بکشد تا از افزایش فشار بر روی حافظه سیستم جلوگیری شود. در بعضی از موارد، تاثیر افزایش فشار بر روی حافظه میتواند شدید باشد. در برخی موارد، استفاده دوباره از حافظه ممکن است برای به دست آوردن عملکرد پیشنهادی منجر به افزایش ترافیک صفحات یا ترافیک بر روی حافظه نهان شود که باعث کاهش عملکرد شدید آن خواهد شد. این همیشه برای ارزیابی لازم است، تاثیر تعاملات با دقت به منظور تعیین اینکه بهترین راه حل در یک وضعیت خاص است مهم هستند.
-
7 امتیازبا درود، وجود کتابخانههای متعدد برای توسعهی رباتهای تلگرام برای زبانها و چهارچوبهای مختلف، و عدم وجود یک کتابخانه بهروز برای ++C و کیوت باعث شد تا توسعهی این پروژه را آغاز کنم. امیدوارم این پروژه برای توسعهدهندگان مفید واقع شود. عنوان: پروژهی TarnaBot توضیحات: یک کتابخانه بر پایه فریمورک کیوت (Qt) که به توسعهدهندگان امکان برنامهنویسی رباتهای تلگرام را میدهد. زبانها و فناوریهای استفاده شده: ++C فریمورک ها و کتابخانهها: کیوت (Qt) نسخه ۵ ابزارِ ساخت: qmake نوع پروژه: متن باز (Open source) مجوز: LGPL v3 نویسندگان: علی رشیدی وضعیت: در حال توسعه - پایدار (stable) مثالها و مستندات به زودی اضافه خواهند شد.
-
6 امتیازبا سلام، در این پست من قصد دارم به چند ویژگی استاندارد 1z اشاره کنم که به شما اجازه میده تا کُد تمیزتر، سادهتر و خواناتری را ایجاد کنید. توسعه زبانهای برنامهنویسی روز به روز بیشتر شده و سی++ به عنوان یک زبان پیچیده نیاز به این داره تا کاربران رو از لحاظ سادگی و مدرنیزه شدن سینتکس دلگرم کنه. در استاندارد جدید ۱۷ من برخی از ویژگیها رو معرفی میکنم که در تمیز نوشتن و ساده نوشتن تاثیر بسیاری دارند. ویژگی ساختارهای پیوندی این ویژگی یکی از ویژگیهای جدید سی++ است که امکان پیوند شدن نامهای مشخص و زیر اشیاء المنتهای اولیه را میدهد. به عبارت سادهتر میتوان گفت که، ساختارهای پیوندی (Structured Bindings) این توانایی را برای ما میدهد تا متغیرهای چند گانه از یک ساختار (struct) یا tuple را به هم دیگر متصل کنیم. *مهمترین هدف Structured Bindings در نسخهٔ ۱۷ ساده سازی و راحتی درک کد میباشد. سینتکس این ویژگی به صورت زیر است: auto ref-operator(optional)[identifier-list] = expression; // Or auto ref-operator(optional)[identifier-list]{expression}; // Or auto ref-operator(optional)[identifier-list](expression); اجازه دهید تا ما با استفاده ازیک مثال مزایای استفاده از ساختارهای پیوندی را با کمک tuple ببینیم: در نسخهٔ ۹۸ سیپلاسپلاس: #include <iostream> using namespace std; // Creating a structure named Point struct Point { int x; int y; }; // Driver code int main() { Point p = {1, 2}; int x_coord = p.x; int y_coord = p.y; cout << "X Coordinate : " << x_coord << endl; cout << "Y Coordinate : " << y_coord << endl; return 0; } در نسخهٔ ۱۱ و ۱۴ سیپلاسپلاس: #include <iostream> #include <tuple> using namespace std; // Creating a structure named Point struct Point { int x, y; // Default Constructor Point() : x(0), y(0) { } // Parameterized Constructor for Init List Point(int x, int y) : x(x), y(y) { } auto operator()() { // returns a tuple to make it work with std::tie return make_tuple(x, y); } }; // Driver code int main() { Point p = {1, 2}; int x_coord, y_coord; tie(x_coord, y_coord) = p(); cout << "X Coordinate : " << x_coord << endl; cout << "Y Coordinate : " << y_coord << endl; return 0; } در نسخهی ۱۷ سیپلاسپلاس: #include <iostream> using namespace std; struct Point { int x; int y; }; // Driver code int main( ) { Point p = { 1,2 }; // Structure binding auto[ x_coord, y_coord ] = p; cout << "X Coordinate : " << x_coord << endl; cout << "Y Coordinate : " << y_coord << endl; return 0; } ویژگی عبارت شرطی و حلقهٔ جدید نسخههای جدید از دستورات شرطی switch و if در سیپلاسپلاس به صورت زیر هستند: if (init; condition) و switch (init; condition) قبلاً شما باید به صورت زیر یک دستور شرطی را پیاده سازی میکردید: { auto val = GetValue(); if (condition(val)) // on success else // on false... } در این قالب مشخص است که val یک محدودهٔ جداگانه و احتمال نشتی دارد. در نسخهٔ جدید آن را میتوان به صورت زیر ساده تر و خواناتر نوشت: if (auto val = GetValue(); condition(val)) // on success else // on false... در این نسخه val فقط در داخل حوزهٔ if و else قابل مشاهده است، بنابراین در این صورت امکان نشتی نخواهد داشت. شرط ممکن است هر نوع شرط باشد و فقط وابسته به val مقدار true/false را بر نمیگرداند. خُب، چرا این نسخه مفید خواهد بود؟ فرض کنید قرار است در داخل یک رشته چند چیز را جستجو کنید: const std::string myString = "My Hello World Wow"; const auto it = myString.find("Hello"); if (it != std::string::npos) std::cout << it << " Hello\n" const auto it2 = myString.find("World"); if (it2 != std::string::npos) std::cout << it2 << " World\n" ما یا باید نامهای مختلفی را برای it استفاده کنیم و یا باید آنها را در داخل دامنهٔ جداگانه قرار دهیم. مانند مثال زیر: { const auto it = myString.find("Hello"); if (it != std::string::npos) std::cout << it << " Hello\n" } { const auto it = myString.find("World"); if (it != std::string::npos) std::cout << it << " World\n" } عبارت شرطی جدید if یک دامنه اضافی را فقط در یک خط ایجاد میکند: if (const auto it = myString.find("Hello"); it != std::string::npos) std::cout << it << " Hello\n"; if (const auto it = myString.find("World"); it != std::string::npos) std::cout << it << " World\n"; همانطور که قبلاً ذکر شد متغیر تعریف شده در عبارت if نیز در بلوک else قابل مشاهده است. بنابراین شما میتوانید آن را به صورت زیر نیز بنویسید: if (const auto it = myString.find("World"); it != std::string::npos) std::cout << it << " World\n"; else std::cout << it << " not found!!\n"; همچنین شما در استاندارد جدید میتوانید از ويژگی پیوند ساختاری در عبارت شرطی نیز استفاده کنید که قالب آن به صورت زیر است: // better together: structured bindings + if initializer if (auto [iter, succeeded] = mymap.insert(value); succeeded) { use(iter); // ok // ... } // iter and succeeded are destroyed here ویژگی Variadic Templates در نسخهٔ ۱۱ ما ویژگی خوبی به نام قالبهای متنوع یا همان (Variadic Templates) داریم که بسیار عالی است، مخصوصاً وقتی که میخواهید با تعداد نامحدود یا متغیر با توابع کار کنید. برای مثال در نسخههای قبل از ۱۱ ما مجبور بودیم تا چندین تابع را با ورودیهای مختلف پیاده سازی کنیم تا بتوانیم به نتیجهٔ مربوطه برسیم. در حال حاضر این ویژگی هنوز هم نیازمند افزودن کدهای میباشد مخصوصاً اگر میخواهید تابعی از نوع بازگشتی پیاده سازی کنید. مانند مثال زیر: auto SumCpp11(){ return 0; } template<typename T1, typename... T> auto SumCpp11(T1 s, T... ts){ return s + SumCpp11(ts...); } در نسخهٔ جدید سی++۱۷ ما میتوانیم این را بسیار ساده تر بنویسیم: template<typename ...Args> auto sum(Args ...args) { return (args + ... + 0); } و یا حتی ساده تر... template<typename ...Args> auto sum2(Args ...args) { return (args + ...); } این تابع فوقالعاده است! ورودیهای متغیر با نوع بازگشتی یکی از پر کاربردترین توابعی است که در نسخههای قبل پیاده سازی آن پیچیده بود. ویژگی متغیرهای درون خطی (Inline variables) در قبل از سی++۱۷ ما میتوانستیم از کلمهٔ کلیدی inline جهت بهینهسازی در زمان کامپال برای توابع استفاده کنیم. حال در نسخهٔ ۱۷ قابلیت تعریف inline برای متغیرها نیز فراهم شده. فرض کنید قرار است متغیری را تعریف کنیم که به صورت ایستا و عمومی مورد استفاده قرار بگیرد. در قبل از نسخهٔ ۱۷ تعریف آن به این صورت که متغیر در فایل هدر و سورس اعلان و تعریف شوند: #ifndef MYCLASS_H #define MYCLASS_H class MyClass { public: MyClass(); static const int myVariable; }; #endif // MYCLASS_H فایل سورس #include "myclass.h" MyClass::MyClass() { } const int MyClass::myVariable = 17; و در نهایت تابع و فایل main: #include <iostream> #include "myclass.h" int main() { std::cout << "My global variable is : " << MyClass::myVariable << std::endl; return 0; } در استاندارد جدید تعریف تابع در همان زمان اعلان به صورت ایستا و عمومی امکان پذیر شده است. برای مثال: #ifndef MYCLASS_H #define MYCLASS_H class MyClass { public: MyClass(); inline static const int myVariable = 17; }; #endif // MYCLASS_H همین تعریف برای اعلان متغیر از نوع ایستا و عمومی کافی است. این کار باعث میشود نیازی برای تعریف مقدار متعیر در فایل سورس نباشد. مثالهای دیگر : struct MyClass { static const int sValue; }; inline int const MyClass::sValue = 777; و یا ساده تر از آن به شکل زیر: struct MyClass { inline static const int sValue = 777; };
-
6 امتیازدر این پُست قصد دارم در رابطه با نحوهٔ نصب و اجرای برنامههای تحت کیوت تحت موارد زیر را توضیح دهم. راهنمای فرایند نصب و استقرار برنامه بر روی پلتفرم Windows راهنمای فرایند نصب و استقرار برنامه بر روی پلتفرم macOS راهنمای فرایند نصب و استقرار برنامه بر روی پلتفرم Linux راهنمای فرایند نصب و استقرار برنامه بر روی پلتفرم Android راهنمای فرایند نصب و استقرار برنامه بر روی پلتفرم iOS قبل از هر چیز لازم است بدانید که برای نصب و راه اندازیِ برنامههای نوشته شده تحتِ سیپلاسپلاس و کتابخانههایِ آن باید پیشنیازات آنها درقالب فایلهایی از کتابخانه در کنار برنامه قرار بگیرد. راهنمای فرایند نصب و استقرار برنامه بر روی پلتفرم Windows در این محیط نسبت به نوع و نسخهٔ Qt و کامپایلری که مورد استفاده قرار گرفته است باید توجه داشته باشیم که هنگام کامپایلر و خروجی گرفتن متناسب با سیستم مقصد آن را تهیه کنیم، برای مثال نوع معماری یعنی x64 یا x86 بودن یک سیستم بسیار مهم است. مواردی که باید به آنها هنگام کامپایل توجه کنیم: مشخص سازی نوع کامپایل برنامه حالت یا همان Mode ای که برنامه روی آن ساخته میشود، اگر برنامه بر روی Debug ساخته میشود تمامی موارد بعدی بر اساس دیباگ تعیین و در غیر اینصورت بر اساس نوع Release مشخص خواهند شد. نوع معماری خروجی در برنامه، باید توجه داشته باشید برنامههای 32 بیتی توسط کامپایلرهای x86 یا 32 بیتی تهیه میشوند و برنامههای 64 بیتی توسط کامپایلر های x64 که خود نیازمند سیستم و بستر برنامهنویسی میباشند که 64 بیتی هستند، یعنی اگر نیاز باشد برنامه شما 64 بیتی کامپایل شود ابتدا باید سیستم عامل و نسخه کامپایلر محیط توسعه از آن پشتیبانی کند. انواع ماژولهای استفاده شده در کتابخانه Qt مهم است، به عنوان مثال در حالت عادی ماژول Qt5Core نیاز است ولی اگر در پروژه شما از ماژولهای دیگری مانند Network استفاده شده باشد در این حالت نیاز خواهید داشت فایل یا ماژول مربوط به آن را وارد برنامه کنید که شامل Qt5Network میباشد که لیست کاملی از ماژولها را بر اساس نیاز در ادامه مشخص خواهیم کرد که بر چه اساسی چه نوع ماژول و چه فایلی باید همراه برنامه موجود باشد. شروع کامپایل و گسترش برنامه: معمولاً نسخه های آزمایشی یک محصول در حالت Debug جهت بررسی و آنالیز خطاهای موجود در آن میباشد که توسط تیم توسعهدهنده یا افرادی که میتوانند در باگ گیری آن همیاری نمایند استفاده خواهند کرد، بنابراین بر فرض اینکه ما قرار است یک نسخه استاندارد و نهایی از محصول را در اختیار کاربر قرار دهیم از حالت Release استفاده خواهیم کرد. در بخش Projects میتوان نوع کامپایلر و مسیر خروجی از آن را مشخص کرد، دقت کنید که در این بخش قسمت Build بر روی حالت Release باشد، در این مثال ما از کامپایلر MSVC2017 و نسخه ۶۴ بیتی آن استفاده کردهایم که مسیر خروجی آن مشخص است. همانند مک و لینوکس در ویندوز نیز ابزاری با نام windeployqt وجود دارد که در مسیر QTDIR/bin/windeployqt میباشد. توسط این ابزار میتوان برنامه را در قالب یک پکیج جمع آوری و مستقر ساخت. برای مثال ما برنامه ای ساخته ایم که در مسیر مورد نظر MyAppRoot//C:/Users/Compez/Desktop میباشد. با دستور cd به مسیر فوق خواهیم رفت: cd C:/Qt/Qt5.11.0/5.11/msvc2017_64/MyAppRoot البته قرار است در این مسیر خروجی فایل بعد از کامپایل ایجاد شود که با غیر فعال سازی امکان Shadow Build این ممکن خواهد شد که فایل مربوطه در مسیر ریشه برنامه ایجاد شود. با فرض اینکه بعد از کامپایل فایل MyApplication.app در مسیر ذکر شده موجود باشد دستور زیر را در ترمینال وارد خواهیم کرد: C:/Qt/Qt5.11.0/5.11/msvc2017_64/bin/windeployqt MyApplication.exe دقت کنید که اگر نیاز باشد با استفاده از گزینههای موجود در ابزار برنامه خود را مستقر سازید کافی است دستور ایجاد را به صورت زیر وارد کنید: C:/Qt/Qt5.11.0/5.11/msvc2017_64/bin/windeployqt MyApplication.app –verbose=3 –no-plugins در ویندوز بر خلاف ایستگاههای یونیکس فراهم آوردن تمامی فایلها در کنار برنامه صورت خواهد گرفت. اما بعد از اجرای دستور فوق برنامه به تنهایی قابل اجرا نخواهد٬ لذا فایلهای msvcp140.dll و vcruntime140.dl نیاز هستند تا در کنار برنامه قرار گیرند. این فایلها در تمامی نرمافزار های بزرگ در کنار برنامه موجود هستند مگر اینکه به صورت جدا پکیج مربوط به آن را نصب کنید که توصیه نمیشود. توجه داشته باشید که فایلهایی که قبل از پسوند .dll آخر حرف آنها به d ختم میشود نشانگر آن است که مربوط به نسخه دیباگ هستند. در صورتی که در حالت Release برنامه خود را کامپایل میکنید فایلهایی را در کنار برنامه خود قرار دهید که حرف آخر آنها به d ختم نشده باشد. برای مثال فایل QtCored.dll مخصوص نسخه دیباگ بوده و فایل QtCore.dll مخصوص نسخه ریلیز. بعد از کامپایل برنامه و اجرای خروجی آن در ویندوزی که بر روی آن Qt و سیپلاسپلاس نصب نیست مسلما با خطاهای زیر مواجه خواهیم شد: خطاهای فوق بیانگر این است که فایلهای فوق در کنار پروژه یا در هسته سیستم عامل پوشه windows/system32 و یا windows/SysWow64 نصب نشده است که در ادامه برای حل این خطا راهکار ارائه داده شده است. بنابراین به مسیر زیر بروید : C:/Program Files (x86)/Microsoft Visual Studio 2017/Enterprise/VC/Redist/14.x.x/onecore/x64/Microsoft.VC150.CRT سپس فایلهای موجود در پوشه را کپی و در کنار برنامه قرار دهید در این صورت برنامه بدون هیچ خطایی اجرا خواهد شد. مگر اینکه به جز کتابخانه Qt و STL از کتابخانههای دیگری استفاده کرده باشید که در این صورت هم باید فایلهای مربوط به آنها را در کنار برنامه قرار دهید.
-
6 امتیازتوابع Image Filtering شاید در تصویرمان بخواهیم عملیات زوم کردن را انجام دهیم در این صورت ما از توابع pyrUp،pyrDownیا تابع buildPyramid استفاده کنیمکهتابع buildPyramid تا هر چند برابر که بخواهیم تصویر را دور میکند اما بیش از حد ان باعث نابودی پیکسل های تصویر میشود. تابع pyrUp: تصویر را نزدیک میکند(ZoomIn) این تابع الگوریتم متفاوتی دارد و باید طبق این الگوریتم پیش رفت تا مشکلی پیش نیاید الگوریتم این تابع به این صورت است که میگوید شما میخواهید تصویر را دوبرابر کنید پس باید در پارمتر سومی که سایز را از مامیخواهد سطر و ستون تصویر ضرب در2 شود اینگونه سطر و ستون دوبرابر خواهند شد و خروجی مورد نظر را میدهد اما اگر در مقداری به جز مقدار 2 ضرب یا بعلاوه شود در این صورت تصویر انقدر بزرگ میشود که امکان نمایش ان وجود ندارد البته هر چند برای دوبرابر کردن تصویر که سایز ضرب در 2 میشود هم محدودیت وجود دارد و تا حد مشخصی میشود تصویر را نزدیک کرد بعد از ان با خطا مواجه میشویم یک مثال از این تابع را مشاهده کنید: #include <stdio.h> #include <stack> using namespace cv; Mat output_image; Mat image_read; void Zoom_In() { pyrUp(image_read, output_image, Size(image_read.cols * 2, image_read.rows * 2)); imshow("Zoom In", output_image); image_read = output_image; } void Zoom_Out() { pyrDown(image_read, output_image, Size(image_read.cols / 2, image_read.rows / 2)); imshow("Zoom Out", output_image); image_read = output_image; } void ZoomIn_And_ZoomOut(int position, void* user) { std::cout << "Position: " << position << " " << " user data " <<(int)user<< std::endl; } int main() { void* userdata = (void*)10; TrackbarCallback zoom_in = (TrackbarCallback)Zoom_In; TrackbarCallback zoom_out = (TrackbarCallback)Zoom_Out; image_read = imread("C:\\Users\\Mohamad4030\\Desktop\\c9ac_d2ynkbk.jpg", IMREAD_COLOR); imshow("befor",image_read);//befor filtering ShowWindow(GetConsoleWindow(), SW_HIDE); createTrackbar("TrackBar1", "befor", 0, 10,zoom_in); waitKey(0); } تابع createTrackBar: یک اسلایدربار را به یک پنجره متصل میکند ورودی اول نام اسلایدر بار ورودی دوم نام پنجره برای متصل شدن ورودی سوم حداقل مقدار اسلایدربار ورودی چهارم حداکثر مقدار ورودی پنجم یک رویداد برای اینکه اگر موقعیت اسلایدربار تعغیر کرد چه کاری صورت گیرد که اینجا ما میتوانیم به دو صورت این ورودی را بدهیم با موقعیت و دیتاهای کاربر که باید بصورت اشارگر باشد و در خود تابع به نوع مناسب تبدیل شود یا اینکه یک TrackbarCallback تعریف کرده همونطور که در کد میبینید و تابع را نوشته و تبدیل میکنیم که تابع ما ZoomIn است ورودی اخر این تابع دیتای های کاربر هست که به پارامتر void* user منتقل میشود در تابع ZoomIn دقت کنید که باید بعد از عملیات زوم image_read برابر با output_image قرار بگیرد تا در عملیات بعد سایز image_read که در پارامتر سوم مورد نیاز است برای زوم بعدی مورد استفاده قرار گیرد. حاصل اجرای کد بالا بصورت زیر خواهد بود: تابع pyrDown: برای بتوانیم تصویر رادور کنیم(ZoomOut) از این تابع استفاده میکنیم برای اینکه از سطر و ستون تصویر بکاهیم و تصویر را تا اندازه ی مشخص دور کنیم باید اینجا سطر و ستون تقسیم بر 2 شود که اگر به عنوان مثال ضرب در 2 شود تصویر نزدیک میشود در همان حالت اگر تصویر تقسیم بر 2 شود به حالت اولیه خود برمیگردد یک مثال از این تابع را مشاهده کنید: #include <opencv2\opencv.hpp> #include <Windows.h> #include <iostream> #include <stdio.h> #include <stack> using namespace cv; Mat output_image; Mat image_read; void Zoom_In() { pyrUp(image_read, output_image, Size(image_read.cols * 2, image_read.rows * 2)); imshow("Zoom In", output_image); image_read = output_image; } void Zoom_Out() { pyrDown(image_read, output_image, Size(image_read.cols / 2, image_read.rows / 2)); imshow("Zoom Out", output_image); image_read = output_image; } void ZoomIn_And_ZoomOut(int position, void* user) { std::cout << "Position: " << position << " " << " user data " <<(int)user<< std::endl; } int main() { void* userdata = (void*)10; TrackbarCallback zoom_in = (TrackbarCallback)Zoom_In; TrackbarCallback zoom_out = (TrackbarCallback)Zoom_Out; image_read = imread("C:\\Users\\Mohamad4030\\Desktop\\c9ac_d2ynkbk.jpg", IMREAD_COLOR); imshow("befor",image_read);//befor filtering ShowWindow(GetConsoleWindow(), SW_HIDE); createTrackbar("TrackBar1", "befor", 0, 10,zoom_in); createTrackbar("TracBar2", "befor", 0, 10, zoom_out); waitKey(0); } حاصل اجرای کد بالا بصورت زیر خواهد بود: تابع buildPyramid: کار تابع pyrDown راانجام میدهد این کار توسط پارامتر سوم صورت میگیرد فقط تنها نکته ای که وجود دارد پارامتر دوم این تابع یک InputOutputOfArray که منظورش یک ورودی و خروجی از ارایه است دریافت می کند یعنی باید یک ارایه ای دریافت کند که ورودی و خروجی ان فقط از همان ارایه باشد در دو تابع ذکر شده ما امدیم وبعد از عملیات تصویر اصلی را برابر تصویر که عملیات روی ان صورت گرفته قرار میدادیم تا در عملیات بعدی نتیجه مطلوب را دریافت کنیم اما در اینجا فقط با دادن مقداری که میخواهیم عملیات ZoomOut را انجام دهیم تصویر را دور میکند یک مثال از این تابع مشاهده کنید: #include <opencv2\opencv.hpp> #include <Windows.h> #include <iostream> #include <stdio.h> #include <stack> using namespace cv; Mat output_image; Mat image_read; /*void Zoom_In() { pyrUp(image_read, output_image, Size(image_read.cols * 2, image_read.rows * 2)); imshow("Zoom In", output_image); image_read = output_image; } void Zoom_Out() { pyrDown(image_read, output_image, Size(image_read.cols / 2, image_read.rows / 2)); imshow("Zoom Out", output_image); image_read = output_image; } void ZoomIn_And_ZoomOut(int position, void* user) { std::cout << "Position: " << position << " " << " user data " <<(int)user<< std::endl; }*/ int main() { vector<Mat> vecmat; image_read = imread("C:\\Users\\Mohamad4030\\Desktop\\c9ac_d2ynkbk.jpg", IMREAD_COLOR); buildPyramid(image_read, vecmat,4); for (int i = 0; i < vecmat.size(); i++) imshow("ZoomIn"+i, vecmat[i]); ShowWindow(GetConsoleWindow(), SW_HIDE); waitKey(0); } دقت کنید که کلاس vector از خود کتابخانه ی OpenCV است و باید از همین کلاس برای این تابع استفاده کنید جز این با خطا مواجه میشوید. حاصل اجرای کد بالا بصورت زیر است:
-
5 امتیازاگر شما توسعه دهندهٔ ++C هستید، توصیه میکنم این سری از مقالات را دنبال کنید زیرا در این تاپیک قصد دارم به چکیدهای از آخرین تغییرات مرتبط با سیپلاسپلاس پیشرفته اشاره کنم. بنابراین در بخش اول، مهمترین موارد منسوخ شده، اشکلات رفع شده و ویژگیهای جدید در استانداردهای اخیر را پوشش خواهیم داد که به صورت جزئی خواهد بود و سپس نسبت به هر کدام در مقالات جداگانه به کاربردهای پیشرفتهتر و جزئیات بیشتری اشاره خواهیم کرد. قبل از شروع، اگر میخواهید به لیستی از تغییرات و ویژگیهای کامل در استانداردها دسترسی داشته باشید به مقالهٔ زیر مراجعه کنید. در مقالهٔ فوق به لیست ویژگیهای جدید در استاندارد ۱۱، ۱۴، ۱۷ و ۲۰ اشاره شده است. در نظر داشته باشید که بزرگترین بهروز رسانی سی++ در ده سالِ اخیر مربوط به استاندارد ۲۰ است. این نسخه از زبان تقریباً 2.5 برابر بزرگتر از سی++ ۱۰ سال پیش است! این در حالی است که استاندارد ۱۷ تقریباً ۸۰٪ بزرگتر از استاندارد ۰۳ است. به عنوان مثال، طبق مستندات رسمی پیشنویسهها تغییرات استاندارد از ۸۷۹ صفحه به ۱۸۳۴ صفحه در این استاندارد رسیده است! چیزی حدود ۱۰۰۰ صفحه بیشتر از نسخههای قبلی ? تمامی این بهبودها خبر از بهتر شدن و در عین حال پیچیده شدن زبان اما همراه با سادهتر و سریعتر شدن آن میدهد. اما مشکلی که میتواند رخ دهد در این است که یادگیری آن و بهروزرسانی کدها نیز میتواند دردسر ساز باشد. بنابراین، برای پوشش دادن جزئیات و بهروزرسانیهای بیشتر در این مقاله سعی خواهم کرد که مهمترین موارد را معرفی کنم. جزئیات ++C نسخه ۱۷ (بهبودها و تغییرات) بیایید به آرامی شروع کنیم، امروز ما به عناصر حذف شده و یا به موارد بهبود یافتهٔ کتابخانه استاندارد بپردازیم. معرفی به صورت سلسله مراتبی عناصر حذف شده و توسعه یافته (در این بحث) شفاف سازی در زبان قالبها ویژگیها تغییرات اول کتابخانه تغییرات دوم کتابخانه مستندات و لینکها قبل از هر چیز، اگر شما خودتان میخواهید استاندارد جدید را کاوش کنید آخرین پیش نویسه را در این بخش مطالعه کنید. در صورتی که میخواهید بدانید کدام کامپایلر از ویژگیهای جدید پشتیبانی میکند، در این بخش آن را پیگیری کنید. علاوه بر این، لیستی از توصیفهای مختصر از تمامی ویژگیهای زبان سیپلاسپلاس ۱۷ تهیه شده است که در این بخش میتوانید آن را ببینید که در قالب PDF از طرف مرجع رسمی میباشد. مواردی که ترجیح داده شده است که حذف شوند حذف تریگراف تریگرافها کاراکترهای ویژه ترتیبی هستند که در موقع عدم پشتیبانی سیستم از نوع ۷ بیتی اَسکی (ASCII) همانند ایزو 646 استفاه شوند. برای مثال =?? کاراکتر ویژهای مانند # تولید شده را در قالب -?? تولید میکند. تمامی مجموعه کاراکترهای اصلی سیپلاسپلاس در قالب 7 بیتی اسکی قرار دارند. موضوع فوق به ندرت مورد استفاده قرار میگیرد، بنابراین حذف آن ممکن است به ترجمه ساده کد کمک کند. اگر شما میخواهید اطلاعات بیشتری در رابطه با کارآیی تیرگرافها در سی++ کسب کنید به این لینک مراجعه کنید. ---------------------------------------------------------------------------- | trigraph | replacement | trigraph | replacement | trigraph | replacement | ---------------------------------------------------------------------------- | ??= | # | ??( | [ | ??< | { | | ??/ | \ | ??) | ] | ??> | } | | ??’ | ˆ | ??! | | | ??- | ˜ | ---------------------------------------------------------------------------- شما جزئیات بیشتر را میتوانید در سند N4086 بیابید. اگر شما واقعاً به هر نحوی به گرافها در ویژوال استودیو نیاز دارید، نگاهی به مشخصه /Zc:trigraphs در بخش پیکربندی داشته باشید. همچنین، کامپایلرهای دیگر ممکن است مواردی را پشتیبانی نکنند. وضعیت انجام شده کنونی در کامپایلر های GCC:5.1 و Clang:3.5 میباشد. حذف کلمه کلیدی register کلمه کلیدی register در استاندارد 2011 سیپلاسپلاس منسوخ شده است و دیگر استفاده از آن معنایی ندارد. این کلمه کلیدی در حال حاضر حذف شده است. این کلمه کلیدی محفوظ است و ممکن است در نسخه های بعدی باز نویسی شود (مثلا autokeyword به عنوان یک چیز قدرتمند مجددا مورد استفاده قرار گرفته است). جزئیات بیشتر در رابطه با این مورد در P0001R1 قابل مشاهده است. البته فعلا در MSVC انجام نشده است اما در کامپایلرهای GCC 7.0 و Clang 3.8 انجام شده است. حذف Operator++ bool این اپراتور برای زمان بسیار زیادی است که منسوخ شده است! در سی پلاس پلاس ۹۸ تصمیم بر آن گرفته بودند که از آن استفاده کنند اما در نسخه ۱۷ سیپلاسپلاس کمیته موافقت خود را جهت حذف آن از زبان اعلام کرده است. جزئیات بیشتر در رابطه با این مورد در P0002R1 قابل مشاهده است. البته فعلا در MSVC انجام نشده است اما در کامپایلرهای GCC 7.0 و Clang 3.8 انجام شده است. حذف مشخصات استثنایی از استاندارد ۱۷ در سی پلاس پلاس ۱۷، مشخصات استثنایی بخشی از نوع سیستمی خواهند بود (به P0012R1 نگاه کنید). با این حال، استاندارد شامل مشخصات استثنایی قدیمی و منسوخ شده اند که به نظر غیرعلمی و غیرقابل استفاده است. void fooThrowsInt(int a) throw(int) { printf_s("can throw ints\n"); if (a == 0) throw 1; } کد بالا در سیپلاسپلاس ۱۱ رد (منسوخ شده است). تنها اعلامیه استثنایی علمی throw() است، به این معنی است که این کد چیزی را در قالب throw انجام نخواهد داد. اما از سیپلاسپلاس ۱۱ به اینور، برنامه نویسان توصیه کرده اند که کسی از آن استفاده نکند. برای مثال در کامپایلر Clang 4.0 شما باید خطای زیر را دریافت کنید: error: ISO C++1z does not allow dynamic exception specifications [-Wdynamic-exception-spec] note: use 'noexcept(false)' instead جزئیات بیشتر در رابطه با این مورد در P0003R5 قابل مشاهده است. البته فعلا در MSVC انجام نشده است اما در کامپایلرهای GCC 7.0 و Clang 3.8 انجام شده است. حذف auto_ptr این یکی از به روز رسانیهای خوبی است که در سیپلاسپلاس ۱۱، ما اشاره گرهای هوشمند را دریافت کردیم : unique_ptr,shared_ptr و weak_ptr. با تشکر از این حرکتی که کمیته انجام داده بود، معنای واقعی این به روز رسانی در این بود که زبان میتواند پشتیبانی مناسبی از انتقال منابع منحصربفرد را داشته باشد. در این میان auto_ptr یک چیز قدیمی و نادرست در زبان بود به نا به دلایلی auto_ptr در این جا منسوخ شده است و باید به صورت خودکار به unique_ptr تبدیل شود. توجه داشته باشیم که auto_ptr مدت کوتاهی است که از سیپلاسپلاس ۱۱ به اینور منسوخ شده است و بسیاری از کامپایلر ها منسوخ شدن آن را گزارش میدهند که به صورت زیر خواهد بود: warning: 'template<class> class std::auto_ptr' is deprecated در حال حاضر آن به وضعیت نامناسب تبدیل شده است، و اساساً کد شما کامپایل نخواهد شد. در اینجا خطا از طرف MSVC 2017 زمانی که از گزینه /std::c++latest استفاده کنید اعلام خواهد شد. error C2039: 'auto_ptr': is not a member of 'std' اگر شما نیاز به کمک از تبدیل از auto_ptr به unique_ptr دارید، میتوانید Clang Tidy را بررسی کنید، زیرا آن عمل تبدیل خودکار را انجام خواهد داد. اطلاعات بیشتر در سند N4190 موجود است. همچنین موارد مرتبط دیگری با سند N4190 وجود دارند که در کتابخانه خذف شده اند مانند: unary_function/binary_function ptr_fun() mem_fun()/mem_fun_ref() bind1st()/bind2nd() random_shuffle قوانین جدید خودکار برای Direct-List-Initialization از سی پلاس پلاس ۱۱ به اینور که ما یک مشکل بزرگی در این رابطه داشتیم: auto x { 1 }; از initializer_list اینطور نتیجهگیری شده است. با استاندارد جدید، ما میتوانیم این مشکل را حل کنیم. بنابراین آن میتواند به عنوان نوع int که اکثر مردم تصور میکنند شناسایی شود. برای اینکه این اتفاق بیافتد، ما نیاز داریم که دو روش تخصیص مقدار اولیه را درک کنیم: کپی و مستقیم. auto x = foo(); // copy-initialization auto x{foo}; // direct-initialization, initializes an // initializer_list (until C++17) int x = foo(); // copy-initialization int x{foo}; // direct-initialization برای مقدار دهی اولیه، سیپلاسپلاس ۱۷ قوانین جدیدی را معرفی میکند: For a braced-init-list with only a single element, auto deduction will deduce from that entry; For a braced-init-list with more than one element, auto deduction will be ill-formed. برای مثال: auto x1 = { 1, 2 }; // decltype(x1) is std::initializer_list<int> auto x2 = { 1, 2.0 }; // error: cannot deduce element type auto x3{ 1, 2 }; // error: not a single element auto x4 = { 3 }; // decltype(x4) is std::initializer_list<int> auto x5{ 3 }; // decltype(x5) is int جزئیات بیشتر را در سند N3922 میتوانید مشاهده کنید. همچنین جزئیات در رابطه با فهرست خودکار موجود هستند که توسط جناب آقای Ville Voutilainen اشاره شده است. این اضافات در سیپلاسپلاس از زمان MSVC 14.0، GCC 5.0 و Clang 3.8 کار میکنند. گزینه static_assert بدون هیچ نوع پیغامی این واضح است که، این به شما این امکان را می دهد که فقط بدون داشتن گذراندن پیام، نسخه دارای پیغام در دسترس خواهد بود. این سازگاری با سایر موارد مانند BOOST_STATIC_ASSERT وجود دارد. static_assert(std::is_arithmetic_v<T>, "T must be arithmetic"); static_assert(std::is_arithmetic_v<T>); // no message needed since C++17 جزئیات بیشتر در سند N3928 در دسترس است. پشتیبانی شده در MSVC 2017 ٬ GCC 6.0 و Clang 2.5. انواع مختلف شروع و پایان در محدوده حلقه از سیپلاسپلاس ۱۱ به بعد، محدوده مبتنی بر حلقه ها به صورت داخلی تعریف شده است: { auto && __range = for-range-initializer; for ( auto __begin = begin-expr, __end = end-expr; __begin != __end; ++__begin ) { for-range-declaration = *__begin; statement } } همانطور که میبینید، __begin و __end دارای نوع مشابه هستند. این ممکن است باعث مشکلاتی شود. برای مثال زمانی که شما چیزی شبیه یک نگهبان (محافظ) که از نوع داده دیگری است را داشته باشید مشکل ساز خواهد بود. در سیپلاسپلاس ۱۷ آن به صورت زیر تغییر کرده است: { auto && __range = for-range-initializer; auto __begin = begin-expr; auto __end = end-expr; for ( ; __begin != __end; ++__begin ) { for-range-declaration = *__begin; statement } } انواع __begin و __end ممکن است متفاوت باشد چرا که فقط اپراتور مقایسه مورد نیاز است. این تغییر کلی باعث میشود که این ویژگی تجربه بیشتری را در این زمینه برای کاربران ارائه دهند. جزئیات بیشتر در P0184R0، پشتیبانی شده در MSVC 2017 ،GCC 6.0 و Clang 3.6.
-
5 امتیازاگرچه که زبان برنامهنویسی سیپلاسپلاس به عنوان یک زبان بسیار قدرتمند و قدیمی شناخته شده است، اما کتابخانهٔ استاندارد و پیشفرض آن برخی از موارد واقعاً مهم را به تازگی تعبیه کرده است. ویژگیهایی که در زبانهایی مثل جاوا و یا سیشارپ داتنت سالهاست وجود دارند. به هر حال این ویژگیها در سی++ ۱۷ موجود شدهاند و این یک بهبود و پیشرفت بسیار خوب است. برای مثال ما الآن فایلسیستم استانداردی را در اختیار داریم. این ویژگی به عنوان یک کتابخانه، امکان برای انجام عملیات بر روی سیستمفایلها و اجزای آنها مانند، مسیرها، فایلها و پوشهها را فراهم میکند. کتابخانهٔ فایلسیستم در فایل سرآیند <filesystem> قرار گرفته است که توسط فضای نام مخصوص خود std::filesystem قابل فراخوانی است. به مثال زیر توجه کنید: namespace fs = std::filesystem; استفاده از این کتابخانه بسیار ساده و کاربردی است، بنابراین اگر بخواهیم به سادگی مسیری از یک ریشه را به دست آوریم، کد آن به صورت زیر خواهد بود: #include <iostream> #include <filesystem> namespace fs = std::filesystem; int main() { fs::path p = fs::current_path(); std::cout << "The current path " << p << " decomposes into:\n" << "root name " << p.root_name() << '\n' << "root directory " << p.root_directory() << '\n' << "relative path " << p.relative_path() << '\n'; } فراخوانی کتابخانه، نمونهسازی از کلاس current_path و سپس چاپ نام، ریشه و مسیر مربوطهٔ آن صورت گرفته است. بنابراین این کتابخانه دارای کلاسهای زیر است که توضیح و کاربرد هر کدام را آوردهایم: کلاس path، این کلاس امکان کار با مسیرها را فراهم میکند، در واقع برای نمایش یا مشاهدهٔ یک مسیر از این کلاس استفاده خواهیم کرد. کلاس filesystem_error یک شیء استثناء در اثر سربارگذاری بیشاز حد کتابخانهٔ فایلسیستم ایجاد میکند، در واقع برای مدیریت خطاها کاربردی خواهد بود. کلاس directory_entry برای کنترل ورودی یک مسیر استفاده میشود، برای مثال بررسی وجود یا عدم وجود در زیر مجموعههای این کلاس امکانپذیر است. کلاس directory_iterator یک تکرار کننده از محتوای یک مسیر (دایرکتوری) را ارائه میکند. کلاس recursive_directory_iterator یک تکرار کننده از محتوایت یک مسیر یا زیر مسیرهای آن را ارائه میکند. کلاس file_status نوع فایل و مجوزهای آن را ارائه میکند. کلاس space_info اطلاعات مربوط به فضای آزاد و موجود در سیستمفایل را ارائه میکند. کلاس file_type اطلاعات مربوط به نوع فایل را ارائه میکند. کلاس perms مجوزهای سیستمفایل را شناسایی میکند. کلاس perm_options معانی هر یک از عملیات مرتبط با مجوزها را ارائه میکند. کلاس copy_options معانی عملیات کپی را مشخص میکند. کلاس directory_options معانی عملیات مربوط به مسیر (دایرکتوری) را مشخص میکند. کلاس file_time_type مقادیر زمانی مربوط به فایل را ارائه میکند. هر یک از کلاسهای فوق دارای متدها و توابعی هستند که در مدیریت فایلسیستم بسیار کاربردی و مفید خواهد بود. در کلاس path شما میتوانید با متدهای مفیدی کار کنید، برای مثال کد زیر پسوند یک فایل موجود که در مسیر به آن اشاره میشود را، در صورت وجود ارائه خواهد کرد. fs::path("/foo/bar.txt").extension(); اگر مسیر فوق دارای فایل ذکر شده باشد، مقدار برگشتی آن .txt خواهد بود. و یا اگر نیاز باشد نام فایل را ارائه کند کافی است از متد file_name آن استفاده کنید! به مثالهای زیر توجه کنید: #include <iostream> #include <filesystem> namespace fs = std::filesystem; int main() { std::cout << fs::path("/foo/bar.txt").filename() << '\n' << fs::path("/foo/.bar").filename() << '\n' << fs::path("/foo/bar/").filename() << '\n' << fs::path("/foo/.").filename() << '\n' << fs::path("/foo/..").filename() << '\n' << fs::path(".").filename() << '\n' << fs::path("..").filename() << '\n' << fs::path("/").filename() << '\n' << fs::path("//host").filename() << '\n'; } همچنین جهت مدیریت خطا و دریافت یک کد یا پیغام خطا به کد زیر توجه کنید: try { cout << fs::file_size("path&file"); } catch (fs::filesystem_error &e) { cout << "Error Message = " << e.what() << " with Code : " << e.code(); } در صورتی که خطایی رخ دهد، کد خطا ساطع خواهد شد، جهت نمایش پیام خطا از تابع what و دریافت کد خطا از تابع code استفاده میشود. این مقاله ادامه دارد...
-
5 امتیازبا سلام، طبق بررسیهای لازم تغییراتی در گروههای کاربری اعمال شده است که از این پس کاربرانی که به عنوان کاربران فعال در حوزهٔ یادگیری و مشارکت در بحثها فعال میکنند از گروه پیشفرض کاربران عادی به کاربران رسمی تغییر دسترسی خواهند داشت. طبق آخرین اصلاحیه در سند( شرایط کسب مجوز فعالیتی و ارتقا حسابکاربری) ، کاربران عضو در این گروه دسترسی لازم برای ارسال تصویر، افزودن امضاء و همچنین عدم نیاز به تایید مطالب توسط مدیریت را خواهند داشت.
-
5 امتیازسلام و درود، ? این پست صرفاً جنبهی مشاوره و به اشتراک گذاری تجربیات را دارد (بنابراین نحویِ بیان آن عامیانه است). من @کامبیز اسدزاده : Kambiz Asadzadeh : علاوه بر برنامهنویسی و علاقهی شدیدی که دنیای تکنولوژی و مخصوصاً مهندسی کامپیوتر و به ویژه برنامهنویسی در حوزهی استارتآپی دارم، سالهاست که به عنوان منتور فنیِ استارتآپها در رویدادها، جلسات و دورههمیهای بسیاری شرکت و در محور رُشد فردی فنی فعالیت به استارتآپهای بسیاری کمک کرده ام. با توجه به منتورینگ انواع مختلف استارتآپها در حوزههای IT مشکلات، سوالات و موارد بسیاری رو شناسایی و برای آنها راهکارهایی رو ارائه دادهام که به نوبهی خودم برخی از آنها را در اختیار شما قرار خواهم داد. بهتره قبل از هر چیز تعریفی از منتور (Mentor) و منتورینگ داشته باشیم! بنابراین مقالهی زیر را حتماً مطالعه کنید. حال با توجه به تجربیات مربوط به این حوزه، لازم دونستم بخشی از این راهکارها رو در اختیار کسانی قرار بدم که مُدام در ذهن خود دنبال پاسخی برای چگونکیهای رسیدن به یک مهارت مطلوب فردی هستن. مدتی هست من در گروهها و شبکههای اجتماعی بسیاری مشاهده میکنم که افراد تازه کار به دنبال این هستند که چگونه و به چه شیوهای میتونن برنامهنویسی حرفهای و مفید را یاد بگیرند. پاسخ این سوال پیچیده نیست، اما شاید خصوصیاتی را که باید بر روی آنها تمرکز داشته باشید رو به خوبی نمیشناسید! من به شما کمک میکنم تا در این مسیر مسائلی که واقعاً باید به آنها دقت کنید رو شناخته و اونها رو در نظر بگیرید. خصوصیات یک برنامهنویس حرفهای چیست؟ علاقه و استعداد در حوزهی برنامهنویسی (داشتن ارادهی قوی). سِمِج و کُنجکاو بودن. شکست ناپذیر (خستگی ناپذیر). مخالف هر گونه بهانه و تنبلی - به کار گیری روشهای صحیح حل مسائل و رسیدن به پاسخ سوالات. رقابت با هیچکس به جز دیروز خودِت! (رقیبت باید خودت باشی نه شخصِ خاصی) از دیگران الگو بگیر اما با کسی به جز خودت رقابت نکن. کم توقع از لحاظ کمک گرفتن از دیگران بر روی مسائل ساده باش (پر توقع از لحاظ رسیدن به پاسخ با تلاشهای فردی باش). تعصب نداشتن بر یک حوزه یا زبان یا هر ابزاری (زبانهای برنامهنویسی لوازم و ابزارهای جعبهابزار یک برنامهنویس هستند). هدف داشتن (هدف مفید - نه مُخرب). آینده نگر بودن (همیشه احتمالات رو در نظر بگیر و چشم بسته دنبال چیزی نباشید) و حرف هر کسی رو در بیان اول بدون تحقیق (سند) قبول نکن. حرف شنوی و استفاده از تجربیات دیگران بسیار خوب هست (اما باید مطمئن باشید که اون پیشنهاد صحیح هست نه غلط!) حالا ممکن پیشنهاد دهنده استاد دانشگاه باشه یا میتونه یکی از ما داخل شبکههای اجتماعی باشه! (بهتره دنبال منتور باشید). همیشه یک قدم از چیزی که هستید جولو تر باشید. حرفهای باش! حرفهایهای برنامهنویسی رو با اخلاقِ خوبشون باید شناخت. عدم حسادت و غرور در آموزشِ آموختهها و تجربیات یکی از بهترین نکات حرفهای بودن است. من چطور میتونم یک برنامهنویس حرفهای بشم؟ پاسخ، با توجه با خصوصیات بالا، یک برنامهنویس با تلاش مستمر و متکی به دانش و مستندات صحیح میتونه با مرور زمان مهارت خودش رو افزایش و تجربیات و سوابش و رزومش رو قوی کنه. به هیچ عنوان راه صد ساله را یک شبه نمیتونه بره! آیا دانشگاه در برنامهنویسِ مفید شدن مهم است؟ این سوال بسیار زیاد به گوش میخوره، اما حقیقت اینه که دانشگاه به عنوان یک ابزار ساخت و پیشرفت فردی بشما نمیاد! متاسفانه دانشگاهها و دانشجویانی که با هدف التماس به اساتید و دیگر افراد به دنبال پاس کردن دروس دانشگاهی هستن هیچ شانسِ موفقیتی در رسیدن به یک حرفهای شدن رو ندارن! نتیجهی این شیوه از یادگیری و آموزش چیزی به جز فارغالتحصیل شدن همراه با یک کاغذ پاره نخواهد بود و هیچ جایی در بازار و دنیای واقعی نخواهد داشت. البته منظور از این صحبتها این نیست که دانشگاه مفید نبوده و تاثیری در موفقیت نداره، اما حقیقت اینه که علم واقعیِ برنامهنویسی با توجه به نظام آموزشی و شرایطی که وجود داره به دست نمیاد. چطور میتوانم به پاسخ سوالاتی که دارم برسم؟ خوشبختانه دنیای مُدرن امروزی زمینهای برای برقراری ارتباط بین یکدیگر را به خوبی فراهم کرده، در صورتی که شما سعی خودتون رو کردین اما نتونستین مشکلی که با اون مواجه شدین رو حل کنید، جای نگرانی نداره! همهی ما یک استاد مشترک داریم (اسمش گوگل Google) هست. شما میتونید با جستجو در این موتور جستجوگر به ۱۰۰٪ پاسخهای خود برسید. نکته: سعی کنید سوالات خودتون رو به زبان علمی بپرسید (انگلیسی) حتی اگه زبان شما دست و پا شکسته باشه درصد موفقیت و رسیدن به پاسخ بهتر و سریعتر در این حالت بسیار زیاده. بنابراین شما میتونید پاسخ سوالات خودتون رو خیلی راحت با چند کلمهی مشخص بپرسید مثل نمونههای زیر: Why should I learn C++ in 2019? How to declare an array in C++? How to declare a string in Java? Why do we need pure virtual function in C++? How do I create a class in Visual Studio 2017? How long will it take to learn Python? مطمئن باشید جستجوگر گوگل تحت هوش مصنوعی خودش بهترین و نزدیکترین پاسخها رو نسبت به سوال شما پیشنهاد خواهد داد! این کار باعث میشه حتی شمایی که به سوال پُرسی مغرور هستید یا حتی شمایی که به خودتون زحمت نمیدین جستجو کنید به راحتی به پاسخهایی برسید که قراره اون رو از کسی بپرسید! یک برنامهنویس حرفهای رو چطور میشه شناخت؟ یک برنامهنویس حرفهای ادعای تو خالی ندره! هر زمان که دیدین یک برنامهنویس از دانش خودش ادعا میکنه مطمئن باشید اونوطور که باید به تکامل نسبی در این علوم نرسیده! دنیای برنامهنویسی نامحدود و بسیار گسترده هست. برنامهنویسِ حرفهای معمولاً مشتاق به آموزش و یاری دیگران هم داره، معمولاً از تجربیات حرفهای خودشون در اختیار دیگران قرار میدن. البته این بستگی به شرایط هم داره (ممکنه کسی به خاطر مشغلهی زندگی روزمره) نتونه اونطور که باید به دیگران کمک کنه (شاید هم اصلاً علاقهای به یاد دادن نداره ?) شاید هم اعتماد به نفس کافی نداشته باشه که همهی اینها طبیعی است. اما Github و سایتهای مرجع، مقالات، کتابها و نمونهکارها نیز نمونه مثال خوبی برای پیدا کردن منابع به اشتراکگذاری چنین افرادی هست که میتونه در شناخت مهارتهاش ملاک باشه. صحبتهای شخصی مثل استیو جابز رو در کنفرانس Stanford سال ۲۰۰۵ پیگیر باشید ببینید تنها رابطش با دانشگاه چی بوده. البته منظورم این نیست که خدایی نکرده دانشگاه رو بیخیال بشید خیر! چون خیلیها خصوصیات بالارو ندارند و بهتره تشریف ببرن دانشگاه و همونجا شاید به کمک کاغذ پاره یه چیزی شدن ? رضایت به یک حقوق کارمندی هم دلیل بدی نیست...! اما اگه میخوای دنیا رو بسازی باید فراتز از چهارچوب محدودی که برات ساختن تفکر کنی! خلاصهی این صحبتها از نظر من = تلاش مکرر در قالب (خودآموزی) هست باید به خودت، فرصت و نعمتی که خالقِت بهت داده اطمینان و اعتقاد داشته باشی). إنَّ لِكُلِّ شَيءٍ زَكاةً ، وزَكاةُ العِلمِ أن يُعَلِّمَهُ أهلَهُ. امام صادق عليه السلام: هرچيزى زكاتى دارد و زكات دانش، آموختن آن است به اهلش. به فرموده رسول خدا (صلی الله علیه و آله): یا عالم باش یا در حال آموختن دانش و وقت خود را در بیهودگی و خوشگذرانی صرف نکن. نظرات دیگر... آنتونی جی. دی آنجلو: اشتیاقتان برای یادگیری را توسعه دهید، تا هرگز در راه رشد و تعالی متوقف نشوید. آلبرت اینشتین: تنها چیزی که در یادگیری من تداخل ایجاد میکند، تحصیلاتم است. وینستون چرچیل: من شخصا همیشه آماده یادگیری هستم، اگرچه دوست ندارم همیشه تحت تعلیم باشم. افلاطون: دانشی که همراه با اجبار کسب شود در ذهن نمیماند. Education is the most powerful weapon which you can use to change the world. - Nelson Mandela I have no special talent. I am only passionately curious. - Albert Einstein A person who won't read has no advantage over one who can't read. - Mark Twain احتمال بهروز رسانی و ادامهی این پست وجود دارد...
-
5 امتیازسلام، کتابخانههای Win32 و MFC هرچند کتابخانههای قدرتمندی هستند اما باید در نظر داشته باشید اینها اختصاصی برای پلفترم ویندوز بوده و بر اساس API های ویندوز ارائه شدن و مسلماً کاربردهای آنچنان بهروز و چند منظورهای مثل Qt رو ندارند. کتابخانهٔ پیشنهادی خود مایکروسافت در قالب چهارچوب داتنت است که برای سی++ هم UWP قابل استفاده بوده و شما میتونید رابط کاربری مدرن رو هم با WPF توسعه دهید (اما انتظار نداشته باشید در حد Qt خارقالعاده باشه). با توجه به اینکه شخصاً تعامل خوبی با داتنت و سیشارپ دارم و در مواقعی که صلاح میدونم ازش استفاده میکنم، نیاز هست تا شمارو در جریان یک واقعیت قرار بدم (که سوال بسیاری از دوستان بوده)! شما برای اینکه برنامهای رو تحت هر زبانی اجرا کنید مسلماً نیاز به یک سری کتابخانهها و پیش نیازاتی خواهید داشت! برای مثال در سیشارپ شما نیاز به داتنت دارید و در سی++ نیاز به STL، Qt، Boost و غیره! حالا کتابخانهٔ پیشفرض سی++ STL و پیشفرض سیشارپ Net. هست! حالا با توجه به اینکه شما یک برنامهٔ ساده ز نوع "سلام دنیا!" بنویسید! چیزی که در سی++ ارائه خواهد شد حدود چند کیلوبایت است که برای اجرای اون تنها نیاز به فایلهای msvcr و msvcp و یا vcruntime خواهید بود که جمعاً حدود ۱ تا ۲ مگابایت نیستند! اما برعکس در سیشارپ شما بخوای همین برنامهٔ ساده رو بنویسی خبری از این سادگی نیست! نیازمند پکیج حجیمی از داتنت خواهی بود که باید نصبش کنی. در ویندوز وقتی شما با سیشارپ برنامهنویسی میکنید به دلیل اینکه چهارچوب .Net و SDKهای مربوط به داتنت بر روی سیستمعامل مستقر شدهاند نیازی نیست تا کتابخانههای مربوط به داتنت رو در کنار برنامهٔ خودتون قرار بدین (چون اینها در خود سیستمعامل نصب میشوند نه در کنار برنامه). دقت کنید آیا بدون نصب پکیج (Microsoft .NET Framework Redistributable) میتونید برنامههای مربوطه رو اجرا کنید؟ پاسخش مسلماً خیر خواهد بود! این پکیج حداقل بعد از نصب چیزی حدود ۲۰۰ تا ۷۰۰ مگابایت و حتی بیشتر کتابخانهٔ داتنت استخراج خواهد کرد و این یعنی در کنار فایل اجرایی یک برنامهٔ ساده از نوع "سلام دنیا!" چنین حجم بزرگی از کتابخانه نیاز خواهد بود! اما شما متوجه این نمیشید چون به صورت پیشفرض موقع نصب برخی از ابزارهای اختصاصی مایکروسافت مثل ویژوال استودیو، آفیس و غیره این پکیج نصب میشود! البته خارج از لطف هم نیست در برخی از نسخههای نهایی ویندوز مثل ویندوز ۱۰ بخش هستهٔ کتابخانه همراه با هستهٔ سیستمعامل ارائه میشه و آنچنان مثل قبل نیاز نصب بخش عظیم کتابخانه نیست. اما با این حال شما حتماً به پکیج مربوطه جهت اجرای تمامی قابلیتهای برنامهٔ خودتون نیاز خواهید داشت که اصلاً قابل مقایسه با یک برنامهٔ ۱ تا ۲ مگابایتی تحت سی++ نیست. حالا با توجه به این آیا حجمی معادل ۸ تا ۲۰ مگابایت واقعاً مشکل محسوب میشود؟! شما فرض کن کتابخانهٔ کیوت رو در قالب یک SDK روی هستهٔ سیستمعامل خودت نصب کرده باشی! در این صورت همون فایل اجرایی چند کیلوبایتی نهایت حجم تولید شده از یک برنامهٔ ساده است. تعداد فایلها مربوط به همون کتابخانه هستش! آیا میدونید تعداد فایلهای داتنت بسیار بیشتر و در یک کلام چند برابر کتابخانهٔ کیوت است!؟ برای اینکه متوجه واقعیت (پنهان) شوید به این مسیر بروید: C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework وحشتناکه نه؟! مایکروسافت به همین راحتی سر برنامهنویسها شیره میماله و اونها رو قانع کرده. اگر کمی زیرک و حرفهای به این مسائل باشید خواهید فهمید که در پشت این مزیت خوب چه چیزی هست! در شناخهتر بودن محیط VS شکی نیست، اما این محیط توسعه یک محیط انحصاری برای پلتفرم ویندوز است. محیط توسعهٔ Qt در هماهنگی بالا با خود کتابخانه در قالب چهارچوب مخصوصاً پشتیبانی از سیستمعاملهای دیگه بسیار بهتر عمل میکنه. در مورد شباهتش به Win32 هم به خاطر درگیری مستقیم شما با کتابخانه هست. در رابطه با اینکه رابط کاربری رو با سیشارپ بنویسید و بکاند رو با سی++ کاملاً مخالفم! چون دارین خودتون رو گول میزنید! اگه قرار هست این کارو بکنید خب با همون VS تحت داتنت و C++/CLR کدنویسی کنید که تحت داتنت خواهد بود. راهحل بهتر اینه که واقعیت رو بپذیرید و قبول کنید که هر کار خارقالعادهای نیاز به تعامل بیشتری خواهد داشت. اگر میخواهید در قالب سرعت، قدرت، دسترسی، تعامل و خارج از هرگونه محدودیت برنامهنویسی کنید سی++ رو باید با تمامی سختیهاش بپذیرید! در غیر این صورت هیچ روشی برای قانع کردن خودتون وجود نداره. درضمن پاسخ اصلی به عنوان سوال : به صورت پیشنهادی فریمورک Qt هست. کتابخانههای دیگری هم هستند مثل wxWidgets.
-
5 امتیازکُد خود را به صورت زیر تغییر دهید تا در یک خط درصد پیشرفت برای شما چاپ شود: #include <iostream> #include <chrono> #include <thread> int main (void){ for(unsigned int index =10 ; index <= 100 ; index+=10){ std::this_thread::sleep_for(std::chrono::milliseconds(500)); std::cout << "Download from dl.dotwaves.com/source/cell\t" << index << "%" << "\r"; std::cout.flush(); } return 0; } از thread و chrono صرفاً جهت تاخیر استفاده کردم.
-
5 امتیازدر کتابخانهی SFML فونتها میتوانند از طریق فایل، حافظه و یا جریان ورودی مشخصی بارگذاری شوند و توسط رایجترین فونتها پشتیبانی میشوند. جهت اعلان یک فونت جدید در این کتابخانه کافی است کُد زیر را در نظر داشته باشید: sf::Font font; در ادامه برای بارگذاری یک فونت به صورت زیر عمل میکنیم: font.loadFromFile("arial.ttf"); در قالب یک دستور شرطی: // Load it from a file if (!font.loadFromFile("arial.ttf")) { // error... } برای استفاده از فونت و قالبهای سفارشی نیاز است تا از کلاس sf::Text نمونه گیری شود، بنابراین در ادامه مثال زیر نشان میدهد که نمونهای از کلاس Text ایجاد و با فونت مربوطه ترکیب شده است. sf::Text MyText; کلاس sf::Text دارای توابع عضوی مانند setFont، setCharacterSize، setStyle و موارد مشابه دیگری میباشد که در تولید ظاهر سفارشی بر روی یک متن اعمال میشوند. در ادامه مثال فوق نمونهای از نحوهی ترکیب این کلاس میباشد. sf::Text MyText; MyText.setFont(font); MyText.setString("Hello, My name is Kambiz :)"); MyText.setCharacterSize(14); MyText.setStyle(sf::Text::Regular); MyText.setColor(sf::Color::White); توجه داشته باشید که برای رسم محتوای مورد نظر باید توسط متُد draw آن را به کلاس RenderWindow ارسال کنید. برای این کار کافی است از تابع draw استفاده شود به صورت زیر: window.draw(MyText); کد نهایی این مثال به صورت زیر است: #include <SFML/Window.hpp> #include <SFML/Graphics.hpp> #include <iostream> int main() { sf::RenderWindow window(sf::VideoMode(640, 480), "Hello world!"); while (window.isOpen()) { sf::Event event; while (window.pollEvent(event)) { if (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape)) window.close(); } sf::Font font; font.loadFromFile("arial.ttf"); // Create a text sf::Text MyText; MyText.setFont(font); MyText.setString("Hello, My name is Kambiz :)"); MyText.setCharacterSize(14); MyText.setStyle(sf::Text::Regular); MyText.setColor(sf::Color::White); window.clear(sf::Color::Black); window.draw(MyText); window.display(); } return 0; } برنامه را کامپایل و اجرا کنید، پیغام شما در سطر اول پنجرهی تولید شده نمایش داده خواهد شد.
-
5 امتیازدر این قسمت قصد داریم تا کمی با مفهوم Process و Thread آشنا شویم . Process : در آغاز برنامه ها بصورت فایلهایی بر روی هارد درایو قرار دارند . برای اجرا شدن آنها ، این فایلها از هارد به حافظه اصلی (یعنی رم) منتقل میشوند و کتابخانه های مورد نیاز درون آن لود میشوند و ..... سپس برنامه اجرا میگردد . در یک تعریف کلی از Process میتوان گفت یک برنامه اجرا شده در سیستم عامل میباشد که خود از واحدی کوچکتر به نام Thread (در ادامه توضیح داده میشود) تشکیل شده که کوچکترین واحد پردازشی در ویندوز میباشد که برای محاسبه به داخل CPU فرستاده میشود . در شکل زیر میتوانید حالت کلی یک Process را مشاهده کنید . از ویژگی یک Process میتوان به دارا بودن آدرس مجازی منحصر به فرد خود اشاره کرد و همچنین وجود PID منحصر به فرد که با فعال شدن هر Process این مقدار عددی به آن نسبت داده میشود تا برای رجوع کردن به Process از این عدد منحصر به فرد بجای نام آن استفاده شود. نکته دیگر در مورد این است که اگر یک Process در درون خود Process دیگری را بسازد ، در آنها رابطه پدر و فرزندی بوجود می آید و در نتیجه آن به وجود آمدن دو Thread و در نتیجه امکان استفاده از حالت پردازش همزمانی میشود . که البته API های ویندوز این امکان را به ما میدهند که حالت انتظار والد را هم انتخاب کنیم تا حالت پردازش همزمانی بوجود نیاید . دستورات کاربردی : (CMD) 1- مشاهده پروسس های در حال اجرا با دستور زیر tasklist 2-بستن یک Process taskkill به عنوان مثال : taskkill /f /pid 9876 Thread : همانطور که در بالا تشریح کردیم هر Process از حداقل یک Thread تشکیل شده تا از آن به عنوان واحد اجرایی برای خود استفاده کند . در واقع Process بدون Thread از دید سیستم عامل دلیلی برای ادامه کار ندارد و پروسس را از بین میبرد . یکی از کاربرد های Thread ایجاد پردازش همزمان در Process ها هست ، هر چند میتوان با ایجاد چند Process نیز به پردازش همزمان رسید اما برای ارتباط و گرفتن خروجی از هر Thread و استفاده در Thread دیگر به مشکل خورده (هرچند با روش هایی میتوان میان آنها حافظه به اشتراک گذاشت) . از Thread میتوان برای بهینه تر کردن برنامه استفاده کرد ، Thread در ویندوز کوچک ترین واحد پردازش میباشد که توسط برنامه نویس درون یک برنامه تعریف شده و سپس با فراخوانی API مناسب Thread ساخته و در صف Thread ها برای ورود به پردازنده قرار میگیرند . هر Thread شامل یک stack و یک TLS(Thread Local Storage) میباشد.(در شکل قسمت Process قابل مشاهده میباشد) . هر Thread که برای اجرا وارد پردازنده میگردد Task نامیده میشود . ویندوز ، سیستم عاملی چند برنامه ای (Multiprogramming) و چند وظیفه ای (Multitasking) را پشتیبانی میکند . در ویندوز برای پیاده سازی چند وظیفه ای از مدل (Multithreading) استفاده میشود . شکل زیر نشان دهنده Thread و رابطه آن را با CPU در حالت کلی نمایش میدهد.
-
4 امتیازدرود بر شما؛ برای اینکار میتوانید شما از QScrollArea استفاده کنید. این کلاس یک منطقهٔنمایش Widgetها و یک QScrollBar را به شما میدهد، و شئ را که میخواهید Scroll کنید را باید به عنوان Child Widget به آن معرفی کنید. برای مثال : #include <QApplication> #include <QDialog> #include <QGroupBox> #include <QList> #include <QScrollArea> #include <QTextEdit> #include <QVBoxLayout> int main(int argc, char** argv) { QApplication application(argc, argv); QDialog dialog; QVBoxLayout layout; QScrollArea scroll(&dialog); QGroupBox groupedArea; QList<QTextEdit*> widgets; for (int i {}; i < 20; ++i) { widgets.append(new QTextEdit); layout.addWidget(widgets.at(i)); } scroll.setWidget(&groupedArea); scroll.setWidgetResizable(true); groupedArea.setLayout(&layout); dialog.show(); return application.exec(); } دقّت کنید که باید حتماً تابع setWidgetResizable را با مقدار true برای تغییر اندازهٔ مناسب Widget فراخوانی کنید. خروجی حاصل از کد بالا : با تشکر از آقایرضوی.
-
4 امتیازسلام .امیدوارم اشتراک گذاری ها و اطلاع رسانی هاتون حالا حالا ها ادامه داشته باشه... خدا قوت
-
4 امتیازهمانطور که میدانید، در سیپلاسپلاس برای ساخت یک کلاس انتزاعی (در قالب یک ساختار) یا همان Interface تحت کلمات کلیدی virtual امکانپذیر است. به طور کلی کلاسی که متُدهای آن به صورت مجازی اعلان میشوند و شامل هیچ تعریف قبلی نیستند به عنوان کلاس انتزاعی (Abstract) یاد میشوند. برای مثال کلاس زیر را در نظر بگیرید: class Person { public: Person(); virtual ~Person(); virtual void print() = 0; //... }; کلاس Person به عنوان یک کلاس انتزاعی تعریف شد است. چرا که اعضای این کلاس فقط اعلان شده اند و به تنهایی هیچ کاری یا واکنشی را نسبت به خود ندارند. کلمهٔ کلیدی virtual برای تعریف یک تابع از نوع مجازی ضروری است و اَصل پلئومورفیسم (چند ریختی / چند شکلی) را دربر دارد. در اصل اگر قرار باشد کلاسی بنویسید که مربوط به یک ماشین باشد (هر ماشین چه از نوع زمینی، چه از نوع صنعتی، و چه از نوعهای دیگر) دارای کلید استارت (روشن/خاموش)، دارای قدرت موتور و یک سری ویژگیهایی است که ممکن است در هر یک از آنها یکسان و یا متفاوت عمل کند. برای این منظور بهتر است کلاسی به صورت انتزاعی پیاده سازی شده و سپس در هر بخش هر یک از متدها را نسبت به نیاز سفارشی سازی کنیم. فرض میکنیم که نیاز است در یک بازی کلاسی برای دریافت اطلاعات یک خودرو، هواپیمای جنگنده و یا غیره... ایجاد شود. کلاس انتزاعی ما درای ویژگیهای ثابت غیر قابل توسعه و ویژگیهایی دارای قابلیت بازتعریف (جهت توسعه توسط کاربر) را فراهم کرده ایم. به مثال زیر دقت کنید: class Machine { public: Machine() {} virtual ~Machine() {} enum class Start {ON, OFF}; virtual bool start(const Start &start) const final { return true; } virtual std::string name(const std::string &nameValue) const final { return nameValue; } virtual int gears(const int &gears) const final { return gears; }; virtual int power(const int &powerValue) const { return powerValue; } virtual int cylinders(const int &totalValue) const final { return totalValue; } virtual int length(const int &lengthValue) const final { return lengthValue; } virtual int width(const int &widthValue) const final { return widthValue; } virtual std::string engineType() const = 0; }; class Porsche : public Machine { public: enum class EngineType { eSuper, eJuniur, e64, e356, e550, e911 }; enum class Color { White, Black, Red, Blue, Green }; Porsche(EngineType type) { etype = type; } ~Porsche() {} std::string color(const Porsche::Color &colorValue) const { switch (colorValue) { case Color::Black : eColor = "Black"; break; case Color::White : eColor = "White"; break; case Color::Blue : eColor = "Blue"; break; case Color::Red : eColor = "Red"; break; case Color::Green : eColor = "Green"; break; } return eColor; }; std::string engineType() const override { switch (etype) { case EngineType::eSuper : eTypeResult = "Super"; break; case EngineType::eJuniur : eTypeResult = "Juniur"; break; case EngineType::e64 : eTypeResult = "64"; break; case EngineType::e356 : eTypeResult = "356"; break; case EngineType::e550 : eTypeResult = "550"; break; case EngineType::e911 : eTypeResult = "911 Turbo"; break; } return eTypeResult; } private: EngineType etype; mutable std::string eTypeResult; mutable std::string eColor; }; class Aircraft : public Machine { public: enum class EngineType { e2SI, e3W, eAce, eSaturn}; Aircraft(EngineType type) { etype = type; } ~Aircraft() {} int power(const int &powerValue) const override { return powerValue; } std::string engineType() const override { switch (etype) { case EngineType::e2SI : eTypeResult = "2SI"; break; case EngineType::e3W : eTypeResult = "3W"; break; case EngineType::eAce : eTypeResult = "ACE"; break; case EngineType::eSaturn : eTypeResult = "Saturn AL-31 Series"; break; } return eTypeResult; } private: EngineType etype; mutable std::string eTypeResult; }; کلاس Machine دارای مشخصههایی از نوع سطح دسترسی final و pure میباشد که توابع از نوع دسترسی final یک بار برای تمامی کلاسهای ماشینها تعریف شده و توابع pure برای توسعه در نظر گرفته شده اند. در ادامه ما کلاسی برای خودروی Porsche و کلاسی را برای هواپیمای جنگنده Aircraft در نظر گرفتهایم که دارای ویژگیهای اختصاصی باز تعریف شده تحت نامهای engineType و غیره میباشد. تابع اول برای مشخص سازی نوع موتور ماشین (برای خودرو و هواپیما) و تابع بعدی برای مشخص سازی نوع کد رنگ پیاده سازی شده است. دقت کنید که تابع engineType از کلاس والد مشتق و باز توسعه یافته است که توسط کلمهٔ کلیدی override مشخص شده است. این کلمه به کامپایلر اعلان میکند که تابع تعریف شده دقیقاً همان تابع تعریف شده در کلاس والد است (با همان پارامتر و همان نام و همان نوع) در صورتی که این کلمه استفاده نشود تابع باز تعریف شده توسط کامپایلر خطا گرفته خواهد شد. این کلمه کلیدی برای هشدار به کاربری است که قرار است بر اساس کلاس والد کلاس مخصوص خود را توسعه دهد و صرفاً جهت اطلاع رسانی توسط کامپایلر به کاربر مورد استفاده قرار میگیرد. توابع از نوع دسترسی final توابعی هستند که کاربر به هیچ عنوان نمیتواند آنها را دستکاری و باز توسعه دهد. برای مثال تابع name به دلیل اینکه نام در تمامی ماشینها از نوع و ورودی یکسانی برخوردار هستند به صورت ثابت تعریف شده است تا کاربر نتواند این ساختار را به هم بزند. زمانی از final استفاده کنید که قرار نباشد ساختار اصلی متدی از کلاس مشتق شده تغییر یابد. همانطور که مشخص است در کلاس پایه ما توابعی را به صورت ثابت تعریف کرده ایم که نیازی نباشد توسعه دهنده مجدداً ساختاری را تولید کند که ممکن نیست خارج از این قالب باشد. حال وقتی قرار باشد وضعیت روشن بودن یا خاموش بودن یک خودرو را بررسی کنیم کافی است متد start را صدا بزنیم، این خاصیت در هواپیمای جنگنده هم وجود دارد بنابراین در هر دوی آنها یکسان است. اما ممکن است برخی از ویژگیها متفاوت باشد. برای مثال قدرت موتور یک خودرو با یک هواپیمای جندگنده یکسان نیست اما ساختار کلاس آنها مسلماً یکی است. بنابراین کافی است از کلاس Machine مشتق گرفته و در کلاس خودرو و هواپیمای جنگنده آنها را به آن صورتی که نیاز داریم باز تعریف (توسعه) دهیم. نتیجهٔ بر اساس نیازی که از کلاس والد داشتهایم به صورت زیر خواهد بود: Car Start Status : 1 Name : Cayman Engine Type : 911 Turbo Total Gears : 8 Power : 6300 Rpm Total Cylinders : 6 Color : Red Width : 1939 mm Length : 4855 mm Aircraft Start Status : 1 Name : Su 35 Engine Type : Saturn AL-31 Series روشی که در مورد آن توضیح دادیم، در پیاده سازی انواع پروژههای بزرگ و پیچیده (در صنعت بازیسازی، نرمافزارهای یکپارچه و غیره...) کاربرد بسیاری دارید. به عنوان مثال یک موتور بازی سازی پیشرفته و یا کتابخانهها و فریمورکهای توسعه محصول از چنین ویژگیهایی برخوردار میباشند. این پُست ممکن است بهروز رسانی شود.?
-
4 امتیازامروز میخوام برای شروع کار نمونه مثال ساده ای رو که بخشی از کامپوننتهای پروژه Jupiter برای شرکتمون بود قرار بدم. این نمونه شامل یک کنترل ورودی InputBox و Button با یک افکت و انیمیشن ملایم سفارشی شده است که قابلیتهای شناور ماوس، واکنش دادن به ورودی و وضعیت نتیجهی ورودی میباشد که ظاهری مشابه و حتی بهتر از Bootstrap 4.x را دارد. در این مثال فرم به صورت سفارشی به ورودی زبان، قالب ایمیل و تلفن حساس است. فرم در حالت عادی مقدار ورودی (نوع زبان) به غیر از فارسی نامعتبر تشخیص داده میشود. تایید ورودیهای معتبر ویژگیهای title، placeHolder، language، email و mobile در کنترل InputBox قابل تنظیم هستند. به عنوان مثال زمانی که شما مشخصهی email را برابر true قرار دهید میتوانید مقدار ورودی پست الکترونیکی را ارزیابی کنید. مثال : Controls.InputBox { id:email; title: "آدرس ایمیل"; email: true; placeHolder: "info@iostream.ir" } مثال : Controls.InputBox { id:firstname; title: "نام"; language: true; placeHolder: "کامبیز"; } Controls.InputBox { id:lastname; title: "نام خانوادگی"; language: true; placeHolder: "اسدزاده" } Controls.InputBox { id:mobile; title: "شماره تلفن همراه"; mobile: true; placeHolder: "09140000000" } Controls.InputBox { id:email; title: "آدرس ایمیل"; email: true; placeHolder: "info@iostream.ir" } مقادیر پرچم به صورت پیشفرض برابر با false هستند. زمانی که شما مقدار یکی از مشخصههای بالا را مشخص نکنید آن false در نظر گرفته میشود. مشخصهی پست الکترونیکی شماره تلفنهای همراه اول و ایرانسل را پشتیبانی میکند. شما میتوانید برای مشاهده منبع کُد و همچنین نحوهی برنامهنویسی این مثال فایل ضمیمه را دریافت کنید.? Jupiter-Component(InputBox).zip
-
4 امتیازساده ترین تعریفی که میشه گفت: اینترنت اشیاء (Internet of Things) به طیف گستردهای از وسایلی که در اطرافمون وجود دارن و این قابلیت رو دارن که به شبکه اینترنت متصل بشن و توسط اپلیکیشنهای موجود در تلفنهای هوشمند و تبلتها کنترل و مدیریت بشن، اینترنت اشیا گفته میشه! اما اینترنت اشیاء فقط به این موارد ختم نمیشه. فواید IoT اونقدر زیاده که حتی میتونه به روند نزولی مرگ و میرها منجر بشه! بریم تا چند مثال کوچیک از این فناوری بزرگ داشته باشیم. ? یک یخچال هوشمند در نظر بگیرید. این یخچال با توجه به سنسورها و پردازندههایی که درونش نصب هست میتونه یک سری هشدارهایی رو منتقل کنه! مثلا میتونه در زمانی که دربش بازه، فیلتر آبش نیاز به تعویض داره، ماده غذایی داخل یخچال کمه و یا حتی زمانی که یک ماده غذیی چرب و خطرناکی خریداری بشه هشدار بده! اما این یخچال هنوز به دنیای شبکه متصل نیست? حالا یک یخچال IoT در نظر بگیرین. این یخچال با توجه به این که به دنیای شبکه متصل میتونه برای قیمت غذا های پایین جستجو کنه، اگه فیلتر آبش نیاز به تعویض داشت سفارش بده و یا مواد غذایی که در روزها یا هفتههای آینده مورد نیازه رو پیشبینی کنه، سفارش بده و داخل سایتهای مختلف برای قیمتها به جستجو بپردازه. مثالی از یک خودرو IoT: میتونیم این خودرو رو از راه دور راه اندازی و به اون مکانی که حضور داریم کنترل و هدایت کنیم! یا اگر تصادفی صورت گرفت خود خودرو به پلیس زنگ بزنه! کاربرد اینترنت اشیا اونقدر زیاد هست که در روند بهبود بازده تولید کارخونهها، مانیتور و کنترل کردن سلامت افراد یک جامعه کمک کنه. اما این نکته رو هم باید در نظر گرفت که در اینترنت اشیا هم محدودیتهایی وجود داره. ? و اما ساختار کلی اینترنت اشیاء چگونه است؟ تجهیزات: شامل قطعات سخت افزاری (سنسور ها و عملگرها) شبکه: شبکهها و یا کانال های ارتباطی شامل : شبکههای سلولی، شبکههای بی سیم ابر: ذخیره سازی دادها و امینت اطلاعات برنامههای کاربردی: سیستمهای تحلیلی، تراکنشی روند کلی تبادل اطلاعات در اینترنت اشیا به این صورت هست: مرحله اول تجهیزات و سنسورها: به این صورت که سنسورها میان دادهها و اطلاعات از اشیا مورد نظر اندازهگیری میکنن و بعد اونها رو به مرحله بعد برای پردازش منتقل میکنن. توی پردازش محلی یک سری برد وجود داره که یک سلسه مراحلی جهت پردازش بر روی اطلاعات اولیه که سنسورها دریافت کردن رو انجام میدن و نتایج ذخیره میکنن. مرحله بعد شبکه (Network) : اطلاعات پردازش شده توسط شبکهها موجود به اینترنت فرستاده میشه و در مرحله بعد این اطلاعات به فضای ابری (cloud) منتقل میشن و روی اونها پردازشهایی صورت میگیره و برای مدت طولانی این اطلاعات ذخیره سازی میشن. در ادامه و تکمیل این موضوع به مزایا و معایب هر کدوم از این پروتکلهای زیر و همینطور معرفی برد آردوینو و رسبری پای و معایب و مزایای هر کدوم، و همینطور پر استفادهترین زبانهای برنامه نویسی در صنعت (IoT) میپردازیم. شبکه و اینترنت (IoT Gateway) پرتکل های مهم در اینترنت اشیا؟! COAP☆ MQTT☆ HTTP☆ XMPP☆ امیدوارم مفید بوده باشه?
-
4 امتیازهمانطور که میدانید کتابخانهی OpenCV کتابخانهای قدرتمند در زمینه پردازش است این پردازش شامل مواردی مانند پردازش تصویر، پردازش ویدیو، سیستم تشخیص چهره ، تشخیص حرکت، الگورریتمهای گوناگون مانند الگوریتم گراف و... است. بیشتر تمرکز این کتابخانه بر روی پردازش تصویر است که میتوان گفت به خوبی در این زمینه نمایان شده است. برای اینکه بتوانیم از این کتابخانه استفاده کنیم باید آن را در محیطی که کدنویسی میکنیم وارد کنیم که محیط مورد نظر در این اموزش ویژال استویو است. برای این منظور ویژوال استودیو رو باز کنید و New Project رو انتخاب کنید از پنجره ای که باز میشود قسمت Other Languages و ++Visual C و General را انتخاب کنید در این قسمت باید یک پروژه خالی بسازید پس Empty Project و نام و مسیر پروژه را انتخاب کنید و Ok را بزنید پس از ان از قسمت View و Solution Explorer را انتخاب کنید روی پروژه خود کلیک راست کنید و گزینه Manage NuGet Packages را انتخاب کنید در اینجا باید به اینترنت متصل باشید تا بتوان کتابخانه ی مورد نظر را دانلود کرد در کادر بالای پنجره باز شده عبارت OpenCV را بنویسید و پس از جستجو اخرین نسخه از این کتابخانه را دانلود کنید مراحل نصب و پیکربندی پس از دانلود بصورت خودکار انجام میشود پس از نصب ما میتوانیم کد نویسی خود را با این کتابخانه شروع کنیم برای اینکه مطمئن شویم کتابخانه بصورت صحیح نصب شده است باید ان را تست کنیم برای این کار به یک فایل منبع نیاز داریم پس بر روی پوشه ی Source کلیک راست کرده گزینه Add را انتخاب کرده سپس بر روی گزینه New Item کلیک کرده و در پنجره باز شده ++File C را انتخاب کنید در پایین پنجره نام فایل را انتخاب کنید و Ok را بزنید اکنون کد زیر را در برنامه خود وارد کنید و اجرا کنید : #include <opencv2\opencv.hpp> #include <Windows.h> using namespace cv; int main() { Mat image_read = imread("beautiful-sunset-sunrise-photo-5.jpg", IMREAD_COLOR); imshow("Show", image_read); ShowWindow(GetConsoleWindow(), SW_HIDE); waitKey(0); } در ورودی اول تابع imread مسیر تصویر را بدهید که تصویر مورد نظر در این مثال در پوشه پروژه است.
-
4 امتیازمعمولاً برای استفاده از آیکونها در برنامه از تصاویر با فرمتهای png, svg, gif استقبال میشود، اما بعضاً نیاز است نسبت به دستگاهها و صفحههای نمایشی با کیفیت بسیار بالا تصاویر با تعداد پیکسل متناسب با صفحه مورد استفاده قرار گیرند. اما روشی وجود دارد که میتوان با حجم کمتر و کیفیت بسیار بالاتری از تصاویر برداری مانند SVG و یا فونتهای آیکونیک استفاده کرد. این فناوری در وب، موبایل و دسکتاپ مورد استقبال قرار میگیرد و ما در این بخش قرار است راجع به نحوهی استفاده از فونتهای آیکونی در پروژههای تحت فناوری کیوت کوئیک و QML صحبت کنیم. قبل از هر چیز لازم است فونت آیکونیک مورد نظر خود را دریافت و بر روی پروژه خود اعمال کنید. برای این منظور ما FontAwesome را پیشنهاد میکنیم. جهت دریافت نسخه به روز آن را از این بخش دریافت کنید. وارد محیط Qt Creator شوید و پروژهی خود را از نوع Qt Quick ایجاد کنید، در بخش qrc فونتهای دسکتاپ را به پروژه اضافه کنید. سپس وارد فایل main.qml شده و نوع تعریف فونت را اعلان کنید. به صورت زیر: FontLoader { id:fontAwesomeStandard source: "qrc:/font/Font Awesome 5 Free-Regular-400.otf" } FontLoader { id:fontAwesomeBrand source: "qrc:/font/Font Awesome 5 Brands-Regular-400.otf" } FontLoader { id:fontAwesomeSolid source: "qrc:/font/Font Awesome 5 Free-Solid-900.otf" } توجه داشته باشید که کُدهای یونیک را با کاراکتر u ترکیب کنید. برای مثال کد f007 شناسه آیکون کاربری میباشد که در اینجا باید به صورت u\f007 نوشته شود. Text { text: "\uf007" font.family: fontAwesomeSolid.name verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter font.pixelSize: 128 anchors.centerIn: parent } کُدهای مختص آیکونها نسبت به نوع فایل فونت متفاوت هستند، کد مرتبط با آیکون کاربر در داخل فایل Free-Solid میباشد که باید به آنها توجه کنید. برای به دست آوردن کدهای آیکونیک از طریق این آدرس اقدام کنید. برای مثال فایل Brand دارای آیکونهای برندیگ است که کد آن به صورت زیر خواهد بود. Text { text: "\uf369" font.family: fontAwesomeBrand.name verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter font.pixelSize: 128 anchors.centerIn: parent } در ادامه میتوانید فایل ضمیمه شده پروژه را دریافت نمایید. FontAwesome.zip
-
3 امتیازاین تاپیک جهت معرفی و اطلاع رسانی در رابطه با اهداف نسخههای جدید، بهروزرسانیها، تاریخ انتشار و موارد مرتبط با آن ایجاد شده است. در این تاپیک به موضوعات مرتبط خواهیم پرداخت. جهت شروع نسخهٔ ۵.۱۲.۰ کیوت با پشتیبانی LTS را معرفی میکنیم. همانطور که میدانید کمپانی و تیم توسعهدهنده با فعالیتهای بسیار زیاد خود مُدام در حال بهروز رسانی و حل مشکلات بازخورد شده از سمت کاربران برای این کتابخانه هستند. بر خلاف نسخههای پیشین نسخههای سری ۵ با بهروزرسانیهای پیدرپر مواجه شده است که شاید این بزرگترین تمایز تیم توسعه دهنده در نسخههای قبلی است. کتابخانهٔ کیوت معمولاً در نسخههای اصلی از ویژگیها و تغییرات چشمگیری مواجه میشود که میتوان آنها را در تغییرات یا افزوده شدن به ماژولهای هسته، فرعی و افزونههای آن اشاره کرد. البته به این مورد نیز باید اشاره کنیم که این بهروزرسانیها تنها برای خود کتابخانه نبوده و معمولاً محیط توسعهٔ آن نیز همراه خود بهروزرسانی و حتی به صورت جداگانه منتشر میشود که در اینجا تاپیک مخصوص آن آورده شده است. از آنجایی که انتظار میرود کیوت در نسخهٔ ۵.۱۲.۰ با بهروزرسانیهای اساسی آمده است. یکی از مهمترین آنها تغییر بر روی کامپایلرها و پشتیبانی کامل از استانداردهای جدید C++ است. در این نسخه کامپایلرهای GCC به نسخهٔ ۸ و کامپایلرهای Clang به نسخهٔ ۷ و مهمتر از همه در محیط ویندوز بهروز رسانی MinGW به نسخهٔ ۷ بوده است. البته ناگفته نماند با توجه به تغییرات اخیر گوگل در NDK که اعلام کرده است کامپایلر پیشفرض GCC به Clang تغییر کرده است این تغییر نیز در کیوت اعمال و با هماهنگی ۱۰۰٪ از ویژگیهای جدید توسعه اندروید هماهنگ شده است. بنابراین شما در بخش کیتها شاهد وجود کامپایلرهای متعددی خواهید بود که بهروز رسانی شده اند. نکتهٔ مهم برای توسعه دهندگان ویندوز : اگر به خاطر داشته باشید در نسخههای ۵.۱۰.۰ به بعد کامپایلر ۳۲ بیتی MSVC به طور غیر منتظرهای حذف شده بود که با بازخورد کاربران روبرو و در نهایت در این نسخه نسخهٔ ۳۲ بیتی کامپایلر MSVC افزوده شده است. مهمترین بهروزرسانیهای کیوت ۵.۱۲.۰ ویژگیهای اضافه شده به هسته: افزوده شدن ویژگی جدید CBOR به عنوان فرمت جدید همانند JSon برای سریالیز دادهها. افزوده شدن متد hashLength برای QCryptographicHash که طول خروجی هَش شده را بر میگرداند. افزوده شدن متد wildcardToRegularExpression به QRegularExpression جهت معرفی راحتتر کد کاربر. افزوده شدن متد anchoredPattern به QRegularExpression جهت پیاده سازی تطبیق کد کاربر. افزوده شدن QRegularExpression برای کلاس QSortFilterProxyModel ویژگیها و تغییرات در QtGui افزوده شدن پشتیبانی از ویژگی Windows UI Automation در WinRT QPA برای برنامههای مبتنی بر UWP که آن را قادر میسازد تا با ابزارهای قابل دسترس در سمت UI دسترسی داشته باشند. جایگزین شدن ویژگیهای مرتبط با دستگاههای ورودی mouse، touchpad، touchscreen و tablet با ویژگیهای متحد بر پایهٔ ویندوز ۸ و جدیدتر. افزوده شدن QGradient جدید بر پایه https://webgradients.com افزوده شدن فرمتهای 4xU16 ،RGBA64 به QImage جهت خواندن فرمتهای PNG و TIFF و همچنین امکان آپلود و گرفتن آنها از OpenGL. ویژگیها و تغییرات در QtNetwork افزوده شدن DTLS برای پشتیبانی از UDP افزوده شدن یک بازنگری مجدد برای ترنسفر ایمن در بکاِند. افزوده شدن پشتیبانی از ALPN در پروتکل HTTP/2 جهت امنیت ترنسفر اطلاعات. افزوده شدن پشتیبانی از ویژگی PKCS#8 در بکاِند عمومی (WinRT و ترنسفر اطلاعات) افزوده شدن QPasswordDigestor به عنوان یک فضای نام که شامل توابعی برای استخراج کلید بر پایه رمزعبور میباشد (در حال حاضر PBKDF1 و PBKDF2) در دسترس هستند. ویژگیها و تغییرات در QtQml پشتیبانی از موتور نسخهٔ ۸ جاوا اسکریپت فراهم شده است (ECMAScript 7) ماژول ECMAScript میتواند به طور مستقیم توسط QJSEngine::importModule() بارگذاری شود و میتواند فایلهای .qml را در زمان استفاده از فایلهای .mjs را فراهم سازد. ویژگیها و تغییرات در QtQuick نوعهای Pointer Handlers به Input Handlers تغییر نام پیدا کردهاند (البته ویژگیهای مربوط به این دسته در این شاخه وجود دارند) و اکنون به طور کامل به عنوان یک ویژگی پشتیبانی شده در یک کلاس QML تحت Qt Quick پشتیبانی میشود. (رابطهای برنامهنویسی سمت سیپلاسپلاس برای آنها هنوز عمومی نشده است). نوع HoverHandler نوع جدیدی برای شناسایی ویژگی Mouse hover می باشد. این ویژگی میتواند شناور ماوس را در موارد عمیقی شناسایی کند. بر خلاف MouseArea، شما میتوانید چندین آیتم با HoverHandler به صورت همزمان قرار دهید (برای مثال نوار کناری (SideBar) و یک دکمه بر روی آن. نوع DragHandler به عنوان یک نوع چند-نقطهای بشمار میرود. اگر شما مقدار minimumPointCount را به ۲ تغییر دهید، به کشیده شدن تنها با دو انگشت واکنش نشان خواهد داد. این ویژگی میتواند به مراتب آزادیهای بیشتری را در توسعه به شما ارائه دهد. کشیده شدن توسط یک انگشت میتواند یک حرکت خاص را انجام دهد و کشیده شدن توسط دو انگشت میتواند کارهای دیگری را انجام دهد (به عنوان مثال زاویهٔ شیب را تغییر دهد). افزوده شدن پشتیبانی از مخازن از پیش تولید شدن جهت سرعت بخشید به اجرا در زمان استارتآپ. افزوده شدم آیتم TableView به عنوان یک نوع دیگری از نوع Item View همانند ListView که بر خلاف آن ویژگی چند ستونه شدن را دارا میباشد. بر خلاف Qt Quick 1.x ویژگی ظاهری برای آن طراحی نشده است. اما جای آن فراهم شده است تا توسط delegates ها بتوانید بر اساس تقاضا آنها را فراهم کنید. ویژگی DelegateChooser به عنوان پیش نمایشی از تکنولوژی ارائه شده است که به عنوان delegate های Item Views ها مانند TableView بسته به مقادیر آنها کاربرد دارد. ویژگیها و تغییرات در QtQuick Controls 2.x کنترل Dial ویژگی inputMode را اضافه کرده است. که دو روش جدید جهت تعامل به صورت عمودی و افقی را فراهم میکند. این ویژگیهای ورودی از یک سیستم ورودی نسبی استفاده میکنند. به این معنی است که بر خلاف سیستم ورودی مطلق قبلی، اغییرات در موقیع شماره گیری به آن اعمال میشود. این ویژگی در نتیجهٔ آن تاثیر میگدارد و باعث میشود شماره گیر پرش کمتری داشته و آن را از عملیاتی که ممکن است مضر باشد تضمین کند. کنترل Popup ویژگیهای leftInset، bottomInset، topInset و rightInset را به بخش پس زمینه مشابه کنترلهای paddings در contentItem اضافه کرده است. اضافه شدن خاصیتهای implicitWidth و impliciyHeight ویژگیهای implicitHeaderWidth و implicitContentWidth و غیره برای ساده سازی پیوندهای اندازهٔ ضمنی و پیچیده ارائه شده است. در کنترلهای SwipeView و DialogButtonBox خاصیتهای contentWidth و contentHeight افزوده شده است. در کنترل RageSlider خاصیت valueAt() به عنوان تابع اضافه شده است، که اجازه میدهد تا مقادیر در هر زمان از تغییر برای tooltip بهروز و تنظیم شوند. در کنترل RangeSlider خاصیتهای first.mode() و second.mode() به عنوان سیگنالهایی مشابه سیگنال moved() اضافه شدهاند. در آیتم پایه Control، در صورتی که به صراحت مشخص شده باشد، baselineOffset به صورت خودکار فاصلهٔ بالای کنترل و baselineOffset از contentItem را کنترل میکند. مشخص سازی استایل برای این کنترل نیاز نیست. در کنترل Popup، خاصیتهای anchors.centetIn به عنوان یک راه حل مناسب اجازه تنظیم مرکز یک popup را میدهد. آیتم QQuickStyle، افزوده شدن ویژگیهای stylePathList() و addStylePath() به عنوان مدیریت فهرستی از سبکهای موجود در کیوت کوئیک کنترل ۲ را فراهم میکند. کنترل Slider، RangeSlider ویژگی touchDragThreshold را برای پیکربندی آستانهٔ شروع کشیدن (لمس) لغزنده فراهم میکند. کشیدن ماوس در این ویژگی تاثیری ندارد. در کنترلهای TextArea و TextField خاصیت placeHolderTextColor برای راحتی کار برای افزودن رنگ در متن پیشفرض و نمایشی در پس زمینهٔ کنترل اضافه شده است. در ویژگی Material، یک سری موارد مورد استفادهٔ انبوه برای استفاده از این سبک در پلتفرمهای دسکتاپ افزوده شده است.برخی از کنترلها از ارتفاع و اندازهٔ قلم کوچکتری استفاده میکنند. جهت پیکربندی آن نیز میتوان از متغیر QT_QUICK_CONTROLS_MATERIAL_VARIANT جهت مشخص سازی تراکم و یا با تنظیم Variant=Dense در فایل پیکربندی qtquickcontrols2.conf استفاده کرد. کنترل DialogBoxButton خاصیت buttonLayout به آن اضافه شده است که میتواند برای ترتیب و مرتب ساختن دکمهها از آن استفاده شود. کنترل Tumbler، تابع positionViewAtIndex() را اضافه کرده است که میتواند عملکرد توابع مربوط به PathView و ListView را بسته به مقدار آنها بسته بندی کند. این امکان اجازه میدهد تا مقدار currentIndex بدون انیمیشن تغییر یابد. در Control و Popup، خاصیتهای horizontalPadding و verticalPadding به عنوان روش مناسب جهت تنظیم جپ و راست و یا بالا و پایین فاصلهها در یک حرکت در نظر گرفته شده است. کنترل Tooltip، روشهای show() و hide() را برای نمایش پارامترهای خاص اضافه کرده است. ویژگیها و تغییرات در QtSerialBus افزوده شدن یک افزونهٔ مجازی CAN برای شبیه سازی CAN بدون سختافزار. افزوده شدن گزینههای پیکربندی برای canbusutil برای عنوان برای تنظیم میزان بیتریت. افزوده شدن CAN FD به پلاگین PeakCAN. افزوده شدن توابع readAllFrames() و clear() به QCanBusDevice. ویژگیها و تغییرات در QtWebEngine بهروز رسانی شده به Chromium 69 رابط QWebEngineUrlScheme برای تنظیم و پیکربندی نوع و امنیت در طرحهای سفارشی URL. ویژگیهای WebActions در معرض QML قرار گرفتهاند. اکنون میتوان صفحههاتی که آنها را خوانده وی ا از آنها دانلودی صورت گرفته است را خواند. گواهینامههای SSL از این پس پشتیبانی میشوند. خواندن آنها از تنظیمات macOS و Windows و بانک اطلاعاتی NSS در Linux امکانپذیر است. ویژگیها و تغییرات در Qt Labs Platform در آیتمهای Menu، MenuItem و SystemtryIcon خاصیت iconName و iconSource منسوخ شده است. در آیتمهای Menu، MenuItem و SystemtryIcon خاصیت icon.mask افزوده شده است. ویژگیها و تغییرات در Qt Virtual Keyboard یک رابط واسط برای کلید مجازی تعریف شده است. تمامی روشهای ورودی فعلی و برخی از ویژگیهای ویژهٔ لایههای آن مانند Hunspell، OpebWnn و غیره به ویژگیهای اضافی منتقل شدهاند. این ویژگی اجازه میدهد تا ساخت و سازهای نوع سوم بدون دستکاری ورودیهای پیشفرض این ماژول صورت بگیرد. با معرفی این ماژول افزونههای اضافی میتوانند با آن لینک شوند. این ماژول رابطهای برنامهنویسی لازم ++C را برای ایجاد یک روش ورودی جدید فراهم میکند. افزوده شدن گزینهٔ build time به امکان محدود سازی تمامی سبکها در پلاگین را فراهم میکند. پشتیبانی از MyScript برای تشخیص دست نویس اضافه شده است. ویژگی تشخیص Vietnamese در دست خط اضافه شده است. افزوده شدن لایههای جدید، آلبانی، آمریکایی، انگلیسی، فرانسوی، کانادایی، اندونزیایی، مالایی، پرتغال برزیبی، اسلواکی، اسلوونیایی، اسپانیایی مکزیکی، تایلندی، ترکی، ویتنامی و اکراینی. لایههای بیشتر در بارهٔ زبان روسی نیز اضافه شده است. برخی از لغت نامهها به صورت پیش فرض تحت یک افزونه اضافه شدهاند. فرهنک لغت کاربری Hunspell افزوده شده است. ویژگیها و تغییرات در Qt Bluetooth افزوده شدن توانایی جهت کشف دادهها از طریف QBluetoothDeviceDiscovery ویژگیها و تغییرات در Qt 3D افزوده شدن ویژگی جهت بارگیری درون یک فایل که شامل نام و شناسهٔ مشخصی است در بخش نمایه به عنوان انیمیشن فراهم شده است. فعال شدن منحنیهای ثابت در انیمیشن. رفع مشکلات مربتط با QNodes ها در برخی شرایط. رفع و بهبود در نمایش بافتها در اشیاء نوع TextureImage دیگر به عنوان فرزند بافت در نظر گرفته نمیشود. زمانی که در یک حلقهٔ شبیه سازی شده قرار گرفته نشود، استفاده از پردازنده کاهش پیدا خواهد کرد. نوع EntityLoader از این پس قادر به بارگیری از یک Component به خوبی یک فایل است. پشتیبانی از سیستم رندرینگ OpenGL ES 3.1 فراهم شده است. عملکردها و یک سری باگها در بخش بک اند رفع و کارآیی آن بهبود داده شده است. ویژگیها و تغییرات در Qt Wayland Compositor افزوده شدن پشتیبانی از نسخهٔ پایدار xdg-shell (همچنین نسخهٔ ناپایدر ۵ آن منسوخ شده است). پشتیبانی از xdg-decoration-unstable-v1 برای سمت سرور جهت اعمال دکوراسیون پنجرهها اعمال شده است. ویژگیها و تغییرات در Qt WebSocket تابع "bytesToWrite" به این ماژول افزوده شده است. ویژگیها و تغییرات در Qt Location پلاگین MapboxGL بهروزرسانی شده و پشتیبانی از QNX7 فراهم شده است. حذف خاصیتهای add و remove و افزوده شدن آن به MapItemView آیتم MapItemView هماکنون کلاس MapItemGroup را طبقه بندی میکند و به خودی خوب غیر قابل تغییر میباشد. در حال حاضر PlaceSearchModel اجازه میدهد تا مدل به صورت پراکنده پُر شود. ویژگی Map.visibleArea جهت محدود کردن مناطق قابل مشاهده بر روی نقشه اضافه شده است. ویژگی geoShape در آیتمهای مربوط به MapItem به صورت R/W تنظیم شده است و یک تنظیم کننده مجازی در کلاس پایه دارد. پشتیبانی از نگهدارندهٔ حفرهها در QGeoPolygon فراهم شده است. افزوده شدن پشتیبانی از Route Legs به پلاگین. ویژگیها و تغییرات در Qt Test خطاهای مربوط به std::tuple در زمان استفاده از QCOMPARE تشخیص داده میشوند. ماژولهای جدید افزوده شدن ماژول Qt Remote Objects با پشتیبانی کامل. افزوده شدن پلاگین Qt WebGL Streaming با پشتیبانی از استریم در مرورگر و اپلیکیشنهای تحت وب. تغییرات مرتبط با پلتفرمها در QTimeZone از ICU در صورتی که در دسترس باشد استفاده میکند (اولویت استفاده با Api مایکروسافت میباشد). در سیستمعامل macOS پشتیبانی از QSurfaceType::MetalSurface فراهم شده است. در macOS پشتیبانی از QSurfaceType::VulkanSurface و QVulkanWindow از طریق MoltenVK فراهم شده است. در Wayland نسخهٔ پایدار xdg-shell افزوده و نسخهٔ ناپایدار ۵ آن منسوخ شده است. با استفاده از پنجرههای پیشفرض نمایش آنها زیباتر و بهتر شده است. پشتیبانی از ویژگیهای اضافی xdg-decoration-unstable-v1 و xdg-output-unstable-v1 فراهم شده است. فناوریهای جدید به عنوان پیشنمایش ویژگی Qt for WebAssembly امکان این را فراهم میسازد تا برنامههای تحت کیوت در بستر مرورگر با استفاده از WebAssembly اجرا شوند. تغییرات مرتبط با Qt for Automation ویژگی Qt MQTT پشتیبانی کامل از پروتکل MQTT سطح ۵ ویژگی Qt KNX پشتیبانی از KNXnet/IP Core نسخهٔ ۲ پشتیبانی از KNXnet/IP Routing نسخهٔ ۱ پشتیبانی از KNXnet/IP Tunneling نسخهٔ ۲ پشتیبانی از KNXnet/IP و برقراری ارتباط از طریق TCP پشتیبانی از KNXnet/IP Secure به صورت پیش نمایش از فناوری ویژگی Qt OPC UA پشتیبانی از Eventsها افزوده شدن رابطهای برنامهنویسی جهت خواندن به صورت دستهای افزوده شدن رابطهای برنامهنویسی جهت نوشتن به صورت دستهای افزوده شدن یک TranslateBrowsePathsToNodeIds به رابطهای برنامهنویسی رابطهای مرورگری بهبود یافته شده پشتیبانی از انواع Argument و ExpandedNodeId نودها میتوانند از این پس از به وسیلهٔ ExpandedNodeId استفاده شوند. پشتیبانی از آرایه های چند بعدی بهبود یافته است. پشتیبانی از خواندن و نوشتن اشیاء اضافی فراهم شده است. ماژولهای منسوخ (حذف در نسخههای بعدی) ماژول Qt Script ماژول Qt Quick Controls 1 ماژول Qt Canvas 3D
-
3 امتیازبه نام خدا با سلام خدمت دوستان گرامی. از آنجایی که کامپایل هر کتابخانه مرتبط با زبان C++ در ویندوز نکات و فوت و فن خاص خود را دارد لذا تصمیم بر آن شد تا در اینجا به نحوه کامپایل کتابخانه Curl در این سیستم عامل بپردازیم. مشخصات کلی کامپایلر و کتابخانه به شرح زیر میباشد: Curl: 7.68.0 Microsoft Build Tools: 15.9.18 Compiler and OS Architectures: x64 ابتدا به این سایت رفته و کد منبع Curl را دریافت نمایید، دقت کنید که باینری کتابخانه Curl برای ویندوز موجود است ولی با کامپایلر MinGW برای ویندوز کامپایل شده که مطلوب ما نمیباشد. به دلیل اعلام نویسندگان Curl در رابطه با نگهداری ضعیف در پشتیبانی از CMake لذا به شکل مستقیم از کنسول مایکروسافت و Makefile سازگار با آن یعنی Makefile.vc استفاده خواهد شد. پس از دریافت و استخراج محتویات، میبایست کنسولx64 Native Tools Command Prompt for VS 2017 را باز کرده و دستورات زیر را مطابق شکل در آن وارد میکنیم: F: cd F:\curl-7.68.0\winbuild که دستور اول برای تغییر درایور و دستور دوم نشانی محل استخراج کتابخانه Curl روی سیستم نگارنده مطلب میباشد. سپس دستور زیر را وارد میکنیم: nmake /f Makefile.vc mode=dll که در دستور بالا /f مشخص کننده نشانی makefileمورد نظر و modeمشخص کننده نحوه کامپایل کتابخانه به شکل ایستا یا پویا را شامل میشود که در اینجا کتابخانه به شکل پویا کامپایل میشود. چنانچه مایل باشیم کتابخانه به شکل ایستا کامپایل شود میبایست دستور زیر را وارد کنیم: nmake /f Makefile.vc mode=static پس از ورود دستور بالا کتابخانه در مسیر F:\curl-7.68.0\ پوشهای با نام buildsساخته و فایلهای حاصل از کامپایل را در آن ذخیره میکند که در تصویر زیر نتیجه نهایی کامپایل آورده شده است. حال یک پروژه ساده از نوع Plain C++ Application در Qt Creator به منظور آزمایش کامپایل صحیح کتابخانه Curl ایجاد میکنیم. قطعه کد زیر را در فایل main.cpp وارد میکنیم: #include <curl\curl.h> int main() { CURL *curl; curl = curl_easy_init(); curl_easy_cleanup(curl); return 0; } و درنهایت در فایل CMake پروژه دستورات زیر را وارد میکنیم: cmake_minimum_required(VERSION 3.5) project(Curl LANGUAGES CXX) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) add_executable(Curl main.cpp) target_include_directories(Curl PRIVATE "F:/curl-7.68.0/builds/libcurl-vc-x64-release-dll-ipv6-sspi-winssl/include") target_link_libraries(Curl PRIVATE "F:/curl-7.68.0/builds/libcurl-vc-x64-release-dll-ipv6-sspi-winssl/lib/libcurl.lib") در گام آخر نیاز است تا فایل dll حاصل از کامپایل کتابخانه را در کنار فایل اجرایی پروژه قرار داده تا برنامه بدون مشکل اجرا شود این فایل در شاخه bin واقع در پوشه builds محل کامپایل کتابخانه موجود میباشد. چنانچه کتابخانه را به شکل ایستا کامپایل کرده باشیم نیاز است تا ماکرو CURL_STATICLIB را قبل از ورود هرگونه فایل سرآیند کتابخانه Curl مطابق زیر تعریف کنیم: #define CURL_STATICLIB متن کامل کد با رعایت نکته گفته شده چنین میباشد: #define CURL_STATICLIB #include <curl\curl.h> int main() { CURL *curl; curl = curl_easy_init(); curl_easy_cleanup(curl); return 0; } چنانچه مشکل یا ایرادی در نوشته بالا ملاحظه نمودید، نگارنده مطلب را بی خبر نگذارید. سپاس فراوان.
-
3 امتیازWindows Access Control List (ACL) قسمت اول (مفاهیم) مباحث مورد بررسی در این مقاله: Access Control Access Control Model Access Control Components مقدمه: در این مقاله ما تلاش میکنیم که چگونگی اجرای امنیت در سیستم عامل های ویندوز را یادبگیریم. Access Control یکی از مهمترین و اساسی ترین مباحث در Windows SDK Platform از دسته امنیتی می باشد. ما با Access Control که در ویندوز استفاده میشود شروع می کنیم و سپس در هر بخش ، به جزئیات بیشتری می پردازیم. در این مسیر ما توابع موجود برای دستکاری و تعامل با شیئ های متنوع ویندوز در بحث امنیت را نیز بررسی می کنیم. برنامه کاربردی در بخش های بعدی ارائه خواهد شد. برنامه نمونه، برنامه سطح پایین به زبان C ، بدون هیچ رابط کاربری گرافیکی (GUI) برای یادگیری بهتر می باشد. Access Control: در سند های ماکروسافت (MSDN) ذکر شده است که در آغاز، سیستم عامل های ویندوز از استاندارد منسوخ کلاس C2 پیروی می کردند. Access Control به این موضوع اشاره میکند که چه کسی به چه منابعی از سیستم عامل میتواند دسترسی داشته باشد. برنامه ها توابع کنترل سطح دسترسی را فراخوانی می کنند تا تنظیم کنند که چه کسی میتواند به منابع خاصی دسترسی داشته باشد، یا اینکه دسترسی به منابع فراهم شده توسط برنامه ها را کنترل کند. Access Control Model: Access Control Model شما را قادر می سازد توانایی یک فرایند را برای دسترسی به securable object ها یا انجام کارهای مختلف مدیریت سیستم، کنترل کنید. یک فرایند، یک security context است که یک برنامه در آن اجرا می شود. معمولا security context با کاربر مرتبط است، بنابر این تمام برنامه ها تحت token فرایند، با permissions و privilegesصاحب کاربر اجرا می شوند. Access Control Components: دو مولفه اساسی در مدل کنترل دسترسی وجود دارد: Access tokens: که شامل اطلاعاتی در مورد کاربر داخل شده می باشد. Security descriptors: که حاوی اطلاعات امنیتی است که از یک securable object محافظت می کند. زمانی که یک کاربر وارد سیستم می شود، سیستم نام و رمز عبور کاربر را تایید می کند. اگر ورود به سیستم موفقیت آمیز بود، سیستم یک access token تولید می کند. هر فرایندی که به نمایندگی از این کاربر اجرا می شود یک نسخه از این access token را خواهد داشت. access token از شناسه های امنیتی (SID) تشکیل شده که حساب کاربری (user account) و هر حساب گروهی (group accounts) را که کاربر به آن تعلق دارد را شناسایی می کند. این شناسه حاوی لیستی از privileges است که توسط کاربر یا گروه کاربرها نگهداری می شوند. سیستم زمانی که یه فرایند سعی می کند تا به یک securable object دسترسی پیدا کند یا درخواست گرفتن امتیاز administration را می دهد، از این نشانه برای شناسایی کاربر استفاده میکند. وقتی یک securable object ایجاد می شود، سیستم به آن security descriptor اختصاصی می دهد که حاوی اطلاعات امنیتی است که توسط سازنده آن مشخص شده است، یا اگر توسط سازنده مشخص نشده باشد اطلاعات امنیتی پیش فرض را به آن اختصاص می دهد. برنامه ها می توانند از توابع برای بازیابی و تنظیم اطلاعات امنیتی برای یک شئ موجود استفاده کنند. security descriptor مالک شئ را مشخص می کند و میتواند شامل access control lists (ACLs) زیر باشد: Discretionary access control list (DACL): کاربرها و گروه هایی را که اجازه دسترسی به شئ را دارند یا ندارند مشخص می کنند. System access control list (SACL): که نحوه کنترل حسابرسی سیستم را برای دسترسی به شئ کنترل می کند. یک ACL از لیستی از access control entries (ACEs) تشکیل شده. هر ACE یک مجموعه حقوق دسترسی را مشخص می کند که شامل یک SID می شود که یک سرپرست برای کسی که حق اجازه دادن، رد کردن یا حسابرسی را می دهد، مشخص میکند. یک حساب کاربری (user account)، گروه کاربری (group account)، جلسه ورود (logon session) میتواند یک سرپرست باشد. یک جلسه ورود زمانی آغاز می شود که کاربر وارد کامپیتر شود. تمام فرایندها در یک logon session دارای primary access token شبیه به یکدیگر می باشند. access token شامل اطلاعات درباره security context جلسه ورود ، شامل SID کاربر، شناسه ورود به سیستم و logon SID می باشد. تصویر زیر نشان می دهد که وقتی یک کاربر وارد سیستم می شود چه اتفاقی می افتد. به خاطر داشته باشید که کاربر نکته مهمی نیست، بلکه نام کاربری و رمزعبور وی در سیستم ایجاد شده است. کاربر تنها به عنوان یک شئ در ویندوز اعتبار دارد. یک access token یک شئ است که security context یک فرایند یا ریسمان را توصیف می کند. اطلاعات داخل token شامل هویت و امتیازات یک حساب کاربر مرتبط با فرایند یا ریسمان می باشد. زمانی که یک کاربر وارد سیستم می شود، سیستم رمز ورود کاربر را با اطلاعات ذخیره شده در پایگاه داده امنیتی خود مقایسه کرده، و آن را تایید یا رد میکند. اگر رمز ورود تایید گردد، سیستم یکaccess token تولید میکند. هر فرایندی از طرف این کاربر اجرا گردد یک کپی از این access token را دارد. سیستم از این access token برای شناسایی کاربر، زمانی که یک ریسمان با یک شئ قابل اطمینان در تعامل است یا تلاش می کند که یک کار سیستمی را انجام دهد که به امتیاز (خاصی) نیاز دارد استفاده میکند. access token ها از اطلاعات زیر تشکیل شدند: SID صاحب حساب. SID های گروه هایی که کاربر عضو آن هستند. SID ورود به سیستم نشان دهنده logon session اخیر می باشد. لیستی از privilege هایی که توسط کاربر یا گروه های کاربر در اختیار دارد. صاحب SID. SID برای primary group. DACL پیشفرض، که سیستم از آن استفاده می کند، زمانی استفاده می شود که کاربر یک securable object، بدون مشخص کردن یک security descriptor می سازد. منبع access token. اینکه آیا token یک token اصلی است یا جعل هویت است (primary or impersonation). لیست اختیاری محدود کننده SID ها(optional list of restricting SIDs). سطح جعل هویت جاری. سایر آمار. هر primary token یک access token است که معمولا فقط به وسیله هسته ویندوز ساخته می شود. ممکن است آن به یک فرآیند اختصاص داده شود تا اطلاعات امنیتی پیش فرض برای آن فرآیند را نشان دهد. impersonation token یک access token است که برای گرفتن اطلاعات امنیتی یک فرآیند کلاینت ایجاد شده است و به سرور اجازه می دهد تا فرایند کلاینت را در عملیات امنیتی جعل هویت کند. هر فرایند یک primary token دارد که security context حساب کاربر که با فرایند مرتبط است را توصیف میکند. به صورت پیشفرض، سیستم از primary token زمانی استفاده می کند که یک ریسمان یک فرایند با یک securable object در تعامل باشد. علاوه بر این، یک ریسمان می تواند یک حساب کاربر را جعل هویت کند. جعل هویت به ریسمان اجازه می دهد با استفاده از security context با securable object ها در تعامل باشد. ریسمانی که کلاینت را جعل هویت می کند هر دو خاصیت primary token و impersonation token را دارد. شما می توانید با فراخوانی تابع OpenProcessToken() هندل primary token فرایند را بازیابی کنید. AdjustTokenGroups(): اطلاعات گروه را در access token تغییر می دهد. AdjustTokenPrivileges(): یک (یا چند) privilege را در access token فعال یا غیر فعال می کند. CheckTokenMembership(): مشخص میکند که یک SID مشخص شده در یک access token فعال است یا خیر. CreateRestrictedToken(): یک access token جدید می سازد که یک نسخه محدود شده از access token موجود می باشد. restricted token های شده می توانند SID های غیر فعال، privilege های پاک شده، و یک لیست از SID های محدود شده داشته باشند. DuplicateToken(): یک access token جدید از روی access token موجود می سازد. DuplicateTokenEx(): یک primary token یا impersonation token می سازد که یک نسخه از یک access token موجود را کپی می کند. GetTokenInformation(): اطلاعات یک access token را بازیابی می کند. IsTokenRestricted(): مشخص میکند که آیا یک token یک لیست از SID های محدود کننده دارد یا نه. OpenProcessToken(): هندل یک primary access token که مربوط به به یک فرایند است را بازیابی می کند. OpenThreadToken(): هندل یک impersonation access token که مربوط به به یک نخ است را بازیابی می کند. SetThreadToken():به یک نخ یک impersonation token را حذف یا اختصاص می دهد . SetTokenInformation(): صاحب token، primary group یا DACL پیشفرض را تغییر می دهد. تابع های access token از ساختار های زیر برای توصیف کامپوننت های access token استفاده می کنند. TOKEN_CONTROL: اطلاعاتی که یک access token را مشخص می کند. TOKEN_DEFAULT_DACL: عضو DACL پیش فرض سیستم که از آن در security descriptors اشیائ جدیدی که توسط نخ ها ساخته می شود استفاده می کند. TOKEN_GROUPS: یک (یا چند) SID و ویژگی های group SID ها در access token را مشخص می کند. TOKEN_OWNER: مالک پیش فرض SID برای توصیف کننده اشیائ جدید. TOKEN_PRIMARY_GROUP: یک primary group SID پیش فرض برای توصیف کننده امنیت شئ جدید. TOKEN_PRIVILEGES: یک privilege مرتبط با یک access token. همچنین مشخص می کند که آیا privilege ها فعال شده اند یا خیر. TOKEN_SOURCE: منبع access token. TOKEN_STATISTICS: آمار مرتبط با یک access token. TOKEN_USER: SID کاربر مرتبط با access token. تابع های access token از enumeration type های زیر استفاده می کنند. TOKEN_INFORMATION_CLASS: نوع اطلاعاتی که قرار است ازaccess token گرفته شود یا تنظیم شود را مشخص می کند. TOKEN_TYPE: نوع access tokenرا مشخص میکند که قرار است از نوع primary یا impersonation باشد. تصاویر دیگر از ساختار token: مثال: Privilege: حق سیستم برای انجام کارهای مختلف مربوط به سیستم مانند خاموش کردن سیستم، بارگیری دیوایس درایور یا تغییر زمان سیستم. access token کاربر، شامل یک لیست از privilege ها که به وسیله کاربر یا گروه کاربر ها نگه داری می شود. securable object: یک شئ است که می تواند یک security descriptor داشته باشد. هر چیزی در ویندوز که Windows objects نام گرفته باشد securable است. برخی اشیاء بی نام، مانند اشیاء process و thread، هم نیز می توانند security descriptors داشته باشند. برای اکثر securable object میتوانید یک security descriptor در هنگام فراخوانی تابع سازنده شئ مشخص کنید. برای مثال می توانید security descriptor را در توابع CreatFile و CreatProcess مشخص کنید. به علاوه، تابع های امنیتی ویندوز شما را قادر می سازند تا اطلاعات امنیتی securable objects سیستم عامل های دیگر را گرفته یا تنظیم کنید. security context: ویژگی های امنیتی یا قانون هایی که در حال حاضر قابل اجرا هستند. برای مثال، کاربر فعلی که وارد سیستم شده است یا شماره شناسایی شخصی که با یک کارت هوشمند وارد شده. security descriptor: ساختار و داده های همراه که شامل اطلاعات امنیتی برای یکsecurable object است. security descriptor صاحب شئ و primary group را مشخص می کند. همچنین میتواند حاوی یک DACL (که دسترسی به یک شئ را کنترل می کند)، و یک SACL (برای کنترل دستیابی به شئ) است. پایان قسمت اول
-
3 امتیازپاسخ به این سوأل صرفاً از نظر نوع زبان کافی نیست و شاید منطقی نباشد. و چون ساختار و قوانین تحت چهارچوب مشخصی برای این موضوع نداریم، از نظر من دلایل بسیاری وجود دارد که بر روی قیمتگذاری میتواند تأثیرگذار باشد که به آنها اشاره میکنم: تجربه و کیفیت خدماتِ قابل ارائهی فرد یا شرکت توسعهدهنده جهت انجام آن اینکه شخص یا شرکت مربوطه بتواند تضمین کند یا آسودگی خاطر را به مشتری بدهد که پروژهی آن در زمان مشخص با نتیجهی قابل قبول ارائه خواهد شد بسیار مهم است، قطعاً اطمینان خاطر و جلوگیری از احتمالات دوبارهکاری و نا رضایتی خودش ارزشمند خواهد بود که ممکن است در هزینهی نهایی پروژه موثر باشد. تضامین و خدمات پس از فروش «پشتیبانی، بهروزرسانی و غیره» هرچند پشتیبانی و بهروزرسانی محصولات نرمافزاری یکی از مراحل توسعه و چرخهی نرمافزار است، اما در دسترس بودن و تضمین پشتیبانی از سمت توسعهدهنده قطعاً در هزینههای آن نسبت به دیگر موارد متفاوت خواهد بود. نوع قرارداد و مذاکراتی که ممکن است طرفین در قبال تعهد به آنها هزینههایی را اضافه کند معمولاً در قراردادهای طرفین به نکاتی اشاره میشود، مانند: در دسترس بودن منبعکد «سورسکد» و یا مستند سازی غیر معمول و اختصاصی که حتماً در قیمت نهایی یک محصول و پروژه موثر خواهد بود. محدودیتها و دلایل قانع کننده برای انتخاب یک ابزار و نیاز به دانش و مهارتهای تخصصی ممکن است پروژهای که به شما پیشنهاد میشود، با یک سری محدودیتهای فنی بر اساس نوع زبان، مهارت و بسترهای پیادهسازی مواجه باشد که با توجه به ارائهی راهکارهای مناسب توسط متخصص «توسعهدهنده» که واقعاً نیاز به تجربه و دانش در حل آن است وابسته خواهد بود. در چنین حالتهای ارزش حل مسائل میتواند در خود پروژه تأثیر بگذارد. در نهایت بعد از بررسی موارد این چنینی که من تنها به برخی از آنها اشاره کردم، میتوانید به خروجیها و نتایج حاصل از خود ابزار که در اینجا «++C» است اشاره کرده و مشتری را نسبت به آن قانع کنید. برای مثال، ویژگیِ چند-سکویی خود به تنهایی یک مزیت بسیار بزرگ است که میتواند در حذف هزینههای احتمالی مانند بازنویسی در زمان توسعه و بهروز رسانی در قالب سکوهای مختلف موثر باشد. نوع مذاکره در ساخت و توسعه در قالب زمان مشخص برای سادهسازی مسئله و حل بایدها و نبایدها نیز مشخص سازی یک نرخ یا رنج قیمت برای کار بر روی پروژه میتواند موثر باشد. برای مثال، بر اساس تعداد ساعت و زمان مشخص در روز میتوانید یک محاسبهی مشخصی برای مشتری خود انتقال دهید تا هم زمان تحویل و هم مدت زمات مورد نیاز برای توسعه را بداند. دربارهی همین موضوع چند-سکویی که تنها یک ویژگی از مزایای سیپلاسپلاس است مثالی بزنم: فرض کنید قرار است مشتری یک نرمافزار تحت موبایل از شما درخواست کند، در این صورت اگر قرار باشد منطقی مذاکره کنید، بهتر است مشتری را متوجه این سازید که برای ساخت یک اپلیکیشن در سکوهای مختلف مانند iOS، Android و غیره نیاز به تخصص، زمان و هزینههای جدا از هم است. اما اگر شما به عنوانی توسعهدهندهی تمام عیار فولاِستک هستید، میتوانید مشتری را قانع کنید که صرفاً با یکپارچهسازی کدهای توسعه و ساختار بهینهی برنامههای نوشته شدهی تحت سی++ از صرف هزینههای احتمالی جهت توسعه جلوگیری میکنید و حتی در آینده نیازی نیست هزینههای اضافه بر مشتری تحمیل کنید. در این رابطه باید به یک هزینهی قابل قبول همراه با حفظ ارزشهای وارده را مطرح کنید. برای مثال، اگر قرار است یک اپلیکیشن برای دو پلتفرم مختلف توسعه یابد، اگر قیمتی بابت یک نرمافزار در دو سکوی مختلف استعلام و یا تخمین زده شده باشد، بهتر است شما با در نظر گرفتن نصف و یا حداکثر دو سوم آن همان کارها را با حفظ ارزشهای فنی و کاربری مشتری انجام دهید. بر اساس چنین مواردی نیازی به افزایش یا کاهش هزینهها در یک پلتفرم وجود ندارد چرا که تنها کاری که انجام خواهید داد همگردانی «کامپایل» کدها بر روی پلتفرم دیگر خواهد بود.
-
3 امتیازآموزش زبان برنامهنویسی سوئیفت - جلسه چهارم مواردی که در این جلسه یاد خواهید گرفت: کامنتها، دو ویژگی نوعهای داده Int، آپِریِترها ( Operators )، کلمات کلیدی break,continue,fallthrough کامنتها در زبان برنامهنویسی سوئیفت مثل اکثر زبانهای برنامهنویسی دیگر، از کامنتها استفادهای زیادی میشود و معمولا برای اهدافی کامنتها استفاده میشوند و میتوانند شامل موارد زیر باشند: برای غیرفعال کردن موقتی یک قسمت یا بخشی از کُد برای توضیح دادن کدها برای دیگر برنامهنویسان یا توسعهدهندگان یا توضیح کد برای اینکه در مراجعات بعدی به پروژه کارکرد همان قسمتی که کامنت کردید را متوجه شوید انواع کامنتها در زبان برنامهنویسی سوئیفت؛ تَک خطی ( single-line ) چند خطی ( multi-line ) در کامنت تک خطی، با گذاشتن دو علامت // میتوانید توضیحات خود را فقط در همان خط درمورد کُد مورد نظر بنویسید و بعد از آن کامنت شما در واقع در حال تعریف دستور جدید هستید! این کامنت، به این صورت استفاده میشود؛ let _web_site_name : String = "www.iostream.ir" print(_web_site_name) // Ouput the string of www.iostream.ir در مثال بالا همانطور که مشاهده میکنید از کامنت تک خطی استفاده کردیم، و بعد از این کامنت شما نمیتوانید انتظار داشته باشید که در خط جدید دوباره حالت کامنتگذاری برای شما همچنان فعال باشد! چرا که در خط بعدی دستوری جدید داریم نه کامنتی ادامهی کامنت قبل!. و اما کامنت چند خطی که میتوانید در تعداد خطهای بیشتر، توضیحات خود را بنویسید؛ let _web_site_name : String = "www.iostream.ir" /* We can also use from of print("String.. and \(_web_site_name)") */ print(_web_site_name) در مثال بالا که مشاهده میکنید، شما هیچ محدودیتی برای اضافه کردن توضیحات بیشتر برای خود کدهای خود ندارید و تا هر چند خط توضیحات که مدنظرتان بود، میتوانید استفاده کنید. دو ویژگی نوع دادهی Int اگر بخواهیم کوچکترین و بزرگترین عدد موجود از نوع دادهی Int را بدست آوریم، از دو ویژگی max,min استفاده میکنیم. هر دو ویژگی به همراه مثال در زیر آورده شدهاند؛ print("Max => \(Int.max)") print("Min => \(Int.min)") با اجرای کدهای بالا، بزرگترین مقدار موجود نوع دادهی Int و همچنین کوچکترین آن به شما نمایش داده خواهد شد. آپِریِترها ( Operators ) آپریترها در هر زبان برنامهنویسی به عنوان پایه و اساس محاسبات و در بعضی موارد برای کارهای دیگر استفاده میشوند. محاسباتی مانند، جمع، تفریق،تقسیم،ضرب و باقی مانده و ... در سوئیفت این 8 دسته آپریتر وجود دارد: اِنتسابی ( Assigment Operator ) محاسباتی ( Arithmetic Oprerator ) باقیمانده ( Remainder Operator ) مُرکب ( Compound Assigment Operator ) مقایسهای ( Comparison Operators ) ترِنِری ( Ternary Conditonal Operators ) دامِنه ( Range Operator ) منطقی ( Logical Operators ) اینها، کل آپریترها در سوئیفت هستند که هر کدام عمل مخصوص به خود را انجام میدهند. در مثالهای زیر هر کدام از اینها را به همراه مثال برای شما آوردهایم. آپریتر اِنتسابی ( Assigment Operator ) اگر ما یک مقداری را به متغییری انتساب میدهیم، عملا داریم از آپِریِتر انتساب ( = ) استفاده میکنیم. چرا که کدنویسی از سمت چپ شروع میشود و این هم کاملا منطقی هم است که مقدار دهی به یک متغییر از سمت چپ صورت میگیرد و مقدار سمت راست را درون خود ذخیره میکند. به این مثال دقت کنید؛ let _web_site_name : String = "www.iostream.ir" // Assigment Operator ( = ) print("Type of \(type(of : _web_site_name ) and the website of name \(_web_site_name)") در مثال بالا مشاهده میکنید که مقدار www.iostream.ir که یک مقدار رشتهای/متنی است را در متغیر web_site_name ذخیره میکنیم. این کار با استفاده از این علامت ( = ) انجام شده است. در خط بعد هم نوع متغییر و مقدار موجود در متغییر web_site_name که ذخیره شده است را نمایش میدهیم. آپریترهای محاسباتی ( Arithmetic Oprerator ) در قسمتهایی از پروژه پیش آمده که ما باید محاسباتی را انجام بدهیم. این کار با استفاده از این آپریترها انجام میشود. که شامل: +،-،/،* و ٪ هستند. برای هر کدام از اینها، مثالهایی در زیر آورده شده است؛ جمع ( + ) var number_one, number_two : Int8 number_one = 50 number_two = 50 print("Result = > ", number_one + number_two) // Output the number 100 در مثال بالا همان طور که مشاهده میکنید، ابتدا دوم متغییر با نوع Int8 تعریف کردهایم و سپس در خطوط بعد به آنها مقادیر ۵۰ را دادهایم. در نهایت عمل جمع ( + ) را روی آنها به صورت مستقیم انجام داده و نمایش میدهیم. یا اگر سادهتر بخواهیم تعریف کنیم، آپریتر ( + ) عمل جمع کردن اعداد و یا متصل کردن دو رشته را بر عهده دارند؛ var web_site_name, platform_name : String web_site_name = " www.iostream.ir :)" platform_name = " www.fanoox.com ;)" print("Binding two string => ", web_site_name + platform_name) // Ouput the website name and platform name => www.iostream.ir :) www.fanoox.com ;) و به همین راحتی میتوانید تا بینهایت عمل جمع و متصل کردن رشتهها را انجام دهید. تنها نکتهای که باید توجه داشته باشید این است که سوئیفت در برخورد با اعداد و این آپریتر، آن عبارت را محاسباتی در نظر میگیرد و در برخورد دو یا چند رشته، آن عبارت را عمل متصل کردن و الحالق ( Concatentation ) در نظر میگیرد. تفریق ( - ) برای کم کردن دو مقدار عددی از هم استفاده میشود؛ var number_one, number_two : Int8 number_one = 80 number_two = 30 print("Result => ", number_one - number_two) // Output the number 50 مثال بالا به خوبی نشان میدهد که دو مقدار ۸۰ و ۳۰ از هم کم شده و در نتیجه، خروجی برابر ۵۰ خواهد بود. ضرب ( * ) عمل ضرب کردن دو عدد را انجام میدهد؛ var number_one, number_two : Int8 number_one = 50 number_two = 20 print("Result => ", number_one * number_two) // Output the number 1000 دقت کنید که نباید به حرف ( x ) که شبیه به ضرب در ریاضیات است اشتباه گرفته شود. تقسیم ( / ) عمل تقسیم کردن دو عدد را انجام میدهد؛ var number_one, number_two : Double number_one = 50.0 number_two = 20.0 print("Result => ", number_one / number_two) // Output the number 2.5 در محاسباتی که عمل تقسیم را انجام میدهیم باید به این نکته دقت کنیم که اگر پروژهی ما عملا برای محاسبات کار خاصی است باید از نوع دادهی Double یا Float استفاده کنیم که البته در محاسبات معمولی، نوع دادهی Float جوابگوی نیاز ما هم هست، اما در محاسباتی که نیاز به دقت بالایی دارند باید از نوع دادهی Double استفاده کنیم. باقیمانده ( ٪ ) توجه داشته باشید که این علامت را با درصد که شبیه همین است اشتباه نگیرید! چرا که در دنیای واقعی ما، علامت درصد برای نشان دادن مقداری از چیزی در یک محصول یا خدمات است ولی در دنیای کامپیوتر و برنامهنویسی این علامت، به معنای باقی ماندهی بین دو عدد است که بعد از تقسیمهای پیدرپی که صورت میگیرد، بدست میآید. این باقی مانده یا ۰ است یا ۱ ( حتما شما هم عاشق صفر و یکی هستید که اساس کار کامپیوتر و سیستم شما را تشکیل میدهد! ). این مثال را ببینید تا بهتر متوجه این موضوع شوید؛ var number_one, number_two : Int8 number_one = 10 number_two = 2 print("Result => ", number_one % number_two) // Output the number 0 اگر جزئیتر بخواهیم وارد شویم به این صورت است که ابتدا عدد ۱۰ بر ۲ تقسیم ( / ) شده و سپس حاصلی که بدست میآید ۵ است و سپس دوباره ۵ تقسیم بر ۲ شده و ۲ بدست میآید و در اینجا باقیمانده ۲ ٪ ۲ میشود ۰. آپِریِترهای مُرکب ( Compound Assigment Operator ) که شامل عبارتهای کوتاهشده یا به اصطلاح میانبری برای عمل انتساب و محاسبه را فراهم میکند که شامل: =+،=-،=*،=/،=٪ است. در زیر توضیح مختصر به همراه یک مثال آورده شده است. انتساب و جمع ( =+ ) در این حالت ما هم عمل انتساب را داریم و هم عمل جمع، با یک تیر دو نشان بزنید! به مثال زیر دقت کنید. var number_one : Int8 = 50 number_one += 50 print("Result =>", number_one) // Output the number 100 در خط دوم که ما با آن کار داریم، متغییر number_one مقدار ۵۰ را هم به آن اضافه به خودش اضافه کرده و در نهایت در خود متغییر number_one ذخیره و نتیجه ۱۰۰ نمایش داده میشود. که بدون استفاده از میانبر، به این شکل بود؛ var number_one : Int8 = 50 number_one = number_one + 50 print("Result =>", number_one) // Output the number 100 حتی میتوانیم برای اتصال یک رشته به رشتهی دیگر استفاده کنیم؛ var web_site_name : String = "www.iostream.ir :) " web_site_name += " www.fanoox.com ;) " print("Result =>" web_site_name) // Ouput the web site of name => www.iostream.ir :) www.fanoox.com ;) که در شکل ساده به این شکل نوشته میشد؛ var _web_site_name_and_platform_name : String = "www.iostream.ir :) " + " www.fanoox.com ;) " print("Result => ", _web_site_name_and_platform_name) // Ouput the web site of name and platform name => www.iostream.ir :) www.fanoox.com ;) انتساب و تفریق ( - ) مقدار سمت راست را از مقدار سمت چپ کم میکند و نتیجه در همان متغییر ذخیره خواهد شد؛ var number : Int8 = 80 number -= 30 print("Result =>", number) // Ouput the number 50 مقدار ۸۰ که مقدار فعلی متغییر number است، از مقدار ۳۰ که در سمت راست متغییر قرار دارد، کم میشود و در نهایت مقدار ۵۰ در همان متغییر یعنی number ذخیره خواهد شد. انتساب و ضرب ( =* ) ضرب مقدار سمت راست در مقدار فعلی متغییر سمت چپ را انجام میدهد؛ var number : Int8 = 80 number *= 30 print("Result =>", number) // Ouput the number 2400 انتساب و تقسیم ( / ) مشابه آپِریِتر تقسیم ( / )، تقسیم مقدار سمت راست را به متغییر سمت چپ انجام میدهد؛ var number : Int8 = 10 number /= 2 print("Result =>", number) // Ouput the number 5 انتساب و باقیمانده ( ٪ ) عمل باقیماندهی دو عدد که شامل مقدار فعلی متغییر سمت چپ و مقدار سمت را است را محاسبه کرده و در متغییر سمت چپ ذخیره میکند؛ var number : Int8 = 10 number ٪= 5 print("Result =>", number) // Ouput the number 0 آپِریِترهای مقایسهای ( Comparison Operators ) برای مقایسهی بین دو مقدار و در نتیجه به دست آوردن مقدار True یا False مورد استفاده قرار میگیرند. بیشترین استفادهی آنها در شرطها است، اما میتوان به صورت مستقیم هم از آنها هم استفاده کرد. این آپِریِترها شامل ==،=!،>،<،=<،=>،==!،=== هستند. برای هر کدام مثالی در زیر آورده شده است. مساوی ( == ) برای مقایسه دو مقدار استفاده میکنیم که در صورتی که مقادیر دو طرف مساوی باشند، مقدار True و در غیر اینصورت مقدار False برگشت داده خواهد شد؛ print("True and False => ", 2 == 2) // Output the true print("True and False => ", 2 == 3) // Output the false در مثال بالا به دلیل اینکه ۲ با ۲ برابر است، مقدار نمایش داده شده، true است. و در خط بعدی به این دلیل که مقدار ۲ برابر با ۳ نیست، مقدار false نمایش داده میشود.همچنین میتوانید در شرطها و حلقهها هم استفاده کنید: if 2 == 2 { print("Ok!") }else { print("NO!") } // Ouput the string Ok! نامساوی ( =! ) اگر مقدار برابر با مقدار مقابل خودش نباشد، نتیجه true و در غیر اینصورت نتیجه false خواهد بود. علامت ! ( نَقیض ) دقیقا معنا و مفهوم ( == ) را عوض میکند ( یعنی اگر مقداری true باشد، برعکس شده ( false ) و اگر false باشد ( true ) میشود. print("True and False => ", 2 != 3) // Output the true print("True and False => ", 2 != 2) // Output the false در مثال بالا، ۲ مساوی ۳ نیست و این درست است!. در خط بعدی ۲ برابر با ۲ است و این درست است! که در نتیجه، برعکس آن یعنی false نمایش داده میشود. کوچکتر ( > ) اگر مقدار سمت چپ کوچکتر از مقدار سمت راست بود، نتیجه true و در غیر اینصورت نتیجه false است؛ print("The operator ( < ) => ", 1 < 2) // Output the boolean true print("The operator ( < ) => ", 2 < 1) // Output the boolean false بزرگتر ( < ) اگر مقدار سمت چپ بزرگتر از مقدار سمت راست بود، نتیجه true و در غیر اینصورت نتیجه false خواهد بود؛ print("The operator ( > ) => ", 1 > 2) // Output the boolean false print("The operator ( > ) => ", 2 > 1) // Output the boolean true بزرگتر یا مساوی ( =< ) اگر مقدار سمت چپ، بزرگتر یا مساوی مقدار سمت راست بود، نتیجه true است، در غیر اینصورت، نتیجه false خواهد بود؛ print("The operator ( >= ) => ", 1 >= 1) // Output the boolean true print("The operator ( >= ) => ", 1 >= 2) // Output the boolean false کوچکتر یا مساوی ( => ) اگر مقدار سمت چپ، کوچکتر یا مساوی مقدار سمت راست بود، نتیجه true است، در غیر اینصورت، نتیجه false است؛ print("The operator ( <= ) => ", 1 <= 2) // Output the boolean false print("The operator ( <= ) => ", 1 <= 1) // Output the boolean true نکته: اولویت مساوی ( = ) در این مورد بالاتر از بزرگتر < یا کوچکتر > است و بنابراین در حلقهها اگر این آپِریِتر باشد، اولویت با آن است. مقایسهی دو شئ ( === ) برای مقایسهی دو شئ ( object ) استفاده میشود. اگر هر دو شئ از یک مرجع ( refrence ) باشند یا به عبارت دیگر شئهای ساخته شده در حافظهی به نام Heap با تمام ویژگیها و متغییرها نگهداری شوند و اگر شئ دیگر از همان حافظهای که یک شئ دیگر استفاده میکند وجود داشته باشد، این آپِریِتر درمورد آن دو شئ نتیجهی true و در غیر اینصورت نتیجهی false را نمایش میدهد. در مبحث شئگرایی بیشتر در این مورد صحبت خواهیم کرد، در حال حاضر فقط همین را که بدانید، کافیست. به مثال زیر دقت کنید: class WebsitePlatform { var website_name, platform_name : String init(web_name : String, platform : String) { self.website_name = web_name self.platform_name = platform } } let _web_site_and_platform_one = WebSitePlatform(web_name : "www.iostream.ir", platform : "www.fanoox.com") let _web_site_and_platform_two = WebSitePlatform(web_name : "www.iostream.ir", platform : "www.fanoox.com") if _website_and_platform_one === _website_and_platform_two { print("This is refrence!") }else { print("No,this is not refrence!") } اگر این قطعه کد را اجرا کنید، به شما پیغام NO, this is not refrence را میدهد! چرا که هر دو شئ به صورت جداگانه در حافظهی Heap ذخیره شدهاند و هیچکدام به دیگر ارجاعی ندارد و به اصطلاح با هم ارتباطی ندارند و اگر ما بیایم به این شکل عمل کنیم، آنوقت دیگر یک ارجاع داریم به یک شئ مشخص؛ class WebsiteAndPlatform { var website_name, platform_name : String init(web_name : String, platform : String) { self.website_name = web_name self.platform_name = platform } } let _website_and_platform_one = WebSiteAndPlatform(web_name : "www.iostream.ir", platform : "www.fanoox.com") let _website_and_platform_two = _website_and_platform_one if _website_and_platform_one === _website_and_platform_two { print("This is refrence!") }else { print("No,this is not refrence!") } به جای ایجاد شئ جدید، همان شئ اول را به متغییر دوم انتساب میدهیم که در واقع الان دو شئ داریم که شئ دومی به شئ اولی اشاره میکند. یعنی اینکه الان با هم در ارتباط هستند و شئ دومی ارجاعیست به شئ اول؛ نتیجه خروجی هم This is refrence است. نامساوی بودن دو شئ ( ==! ) اگر دو شئ از یک مرجع نبودند، و هر کدام در حافظهای جداگانه نگهداری میشوند، نتیجه به صورت true و اگر دو شئ از یک مرجع بودند، نتیجه false خواهد بود. کاملا برعکس علامت ( === ). به مثال زیر دقت کنید: class WebsiteAndPlatform { var website_name, platform_name : String init(web_name : String, platform : String) { self.website_name = web_name self.platform_name = platform } } let _website_and_platform_one = WebSiteAndPlatform(web_name : "www.iostream.ir", platform : "www.fanoox.com") let _website_and_platform_two = WebSiteAndPlatform(web_name : "www.iostream.ir", platform : "www.fanoox.com") if _website_and_platform_one !== _website_and_platform_two { print("This is refrence!") }else { print("No,this is not refrence!") } مثال بالا هم که کاملا واضح است! اینکه اگر دو شئ با هم ارجاعی نداشتند، پس نتیجه true است و در غیر اینصورت اگر ارجاع داشتند، نتیجه false و شرط آخر اجرا خواهد شد که No, this is not refrence است. آپریتر ترِنِری ( Ternary Conditonal Operators ) سه قسمت دارد؛ مسئله/شرط مقدار اول مقدار دوم ابتدا شرط قرار خواهد گرفت و سپس به دنبال آن آپِریِتر ? و بعد از آن جواب اول که در صورت درست بودن شرط، برگشت داده میشود و علامت کالُن ( : ) بعد از جواب اول قرار میگیرد که در صورتی که نتیجه نادرست یا false باشد، مقدار بعد ( : ) برگشت داده میشود. به مثال زیر توجه کنید؛ let _website_name_and_platform_name : String = 2 > 1? "www.iostream.ir" : "www.fanoox.com" print("Result =>", _website_name_and_platform_name) // Output the www.iostream.ir در مثال بالا همانطور که مشاهده میکنید، ابتدا شرط یا مسئله قرار میگیرد و سپس مقدار بعد آپِریِتر ? و مقدار اول و دوم که با ( : ) از هم جدا میشوند. در این مثال نتیجه، www.iostream.ir است، چرا که ۲ بزرگتر از ۱ است و این کاملا منطقی است که نتیجهی true دارد. آپریتر دامِنه ( Range Operator ) بیشتر در حلقهها استفاده میشود و نحوهی کار آن را در جلسهی قبل توضیح داده شده است؛ for index_number_one in 0...20 { print(index_number_one, separator : " ",terminator : "") // Output the number 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 } for index_number_two in 0..<20 { print(index_number_two, separator : " ",terminator : "") // Output the number 0 1 2 3 4 5 6 7 8 9 10 11 12 13 15 16 17 18 19 } آپریترهای منطقی ( Logical Operators ) شامل !،&&،|| هستند که بیشتر استفادهی آنها در حلقههاست، اما شما میتوانید در هر جایی از پروژهی خودتان که نیاز به آنها داشتید، استفاده کنید. نَقیض ( ! ) کار آن، برعکس کردن یا نقض کردن یک مقدار است که امکان دارد true یا false باشد. به عنوان مثال اگه مقدار متغییری true است و این آپِریِتر را در ابتدای آن مقدار قرار بدهید، خروجی برابر است با false. و همین مورد هم برعکس صدق میکند، یعنی اگر شما مقدار متغییری false داشتید، با گذاشتن این عبارت در ابتدای متغییر، نتیجه true خواهد شد؛ var isname_website_iostream : Bool = false print(!is_name_website_iostream) // Output the bool true isname_website_iostream = true print(!isname_website_iostream) // Output the bool false درست بودن دو یا چند شرط ( && ) اگر در شرط یا عبارتی بخواهیم دو شرط را بررسی کنیم که هر دو هم حتما باید درست ( true ) باشند از این آپِریِتر استفاده خواهیم کرد؛ let web_sitename, platform_name : String web_sitename = "www.iostream.ir" platform_name = "www.fanoox.com" if web_sitename == "www.iostream.ir" && platform_name == "www.fanoox.com" { print(web_sitename, platform_name) } else { print("None") } در قطعه کد بالا، هر دو شرط مبنی بر اینکه دو مقدار متغییر تعریف شده باید برابر با مقدار تعیین شده در شرط باشند تا مقادیر چاپ شوند. در غیر اینصورت با خروجی None روبرور خواهیم شد. درست بودن حداقل یک شرط ( || ) اگر یکی از شرطها در بین چندین شرط که برقرار است و به عبارتی نتیجه درست ( true ) داشته باشد، وارد بدنهی شرطه خواهد شد و دستورات را اجرا میکند. اگه تمامی شرطها نادرست ( false ) باشند، دستورات داخل بدنه اجرا نخواهند شد؛ var web_sitename, platform_name : String web_sitename = "www.iostream.ir" platform_name = "www.fanoox.com" if web_sitename == "www.iostream.ir" || platform_name == "www.fanoox.ir" { print(web_sitename, platform_name) } else { print("None") } در مثال بالا شرط دوم برقرار نیست! چرا که متغییر platform_name با مقدار سمت راست آن برابر نیست. اما از آنجایی که از ( || ) استفاده کردهایم، پس شرط اول درست بوده و دستورات داخل بدنهی شرط if اجرا خواهند شد. کلمات کلیدی continue,break,fallthrough کلمهی کلید continue اگر بخواهیم در یک حلقه در یک جایی به بعد دستورات اجرا نشوند و حلقه مقدار فعلی را نادیده بگیرد، از این کلمهی کلید کمک خواهیم گرفت؛ for index in 0...20 { if index == 5 { continue } print(index) } /* Output the number 0 1 2 3 4 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 */ همانطور که در مثال بالا مشاهده میکنید، در حلقهی for شرط داخل حلقه بر این مبنا است که هر زمانی که متغییر index مساوی مقدار ۵ شد، به ادامهی دستورات پایان بده ( continue ) و مجدد حلقه را از سر بگیر. به همین خاطر است که عدد ۵ نمایش داده نشده است. کلمهی کلید break با این کلمهی کلید به راحتی میتوانید هر جایی از حلقه که دیگر نیازی نداشتید ادامه پیدا کنید، حلقه را متوقف یا به اصطلاح بشکنید!. با این کار دیگر حلقه تکرار نشده و دستورات بعد از حلقه اجرا خواهند شد؛ for index in 0...5 { if index == 2 { break } print(index) } /* Output the number 0 1 */ کلمهی کلید fallthrough شاید در جایی از دستور شرطی switch لازم داشتید که caseهای بعدی هم اجرا شوند. با این کلمهی کلیدی میتوانید این کار را انجام دهید؛ let _number : Int8 = 1 switch _number { case 2: print(2) case 1: print(1) fallthrough case 3: print(3) fallthrough default: print("None") } بعد از هر caseی که میخواهید اجرا شود باید این کلمهی کلیدی را قرار دهید. امیدوایم این جلسه هم مورد رضایت شما عزیزان قرار گرفته باشد.
-
3 امتیازداخل یک ترد غیر از ترد اصلی برنامه تمام فایلها رو rename کنید. زیاد کردن تعداد تردها برای عملیات IO روی فایل خصوصاً در این مورد هیچ کمکی نمیکنه که هیچ، به احتمال زیاد سرعت رو هم پایین میاره.
-
3 امتیازاگر این بار مشکل خاصی نتراشند انشاءالله در نسخهٔ ۵٬۱۳ تقویم فارسی خواهیم داشت. تغییرات مربوطه تکمیل شدهاند و از طریق آدرس زیر در دسترس هستند: Gerrit Code Review
-
3 امتیازسلام خب اول برات delete رو میگم که ساده تره ?. شما یه توی برنامه نویسی شئ گرا که کار با کلاس ها (class) پیش میاد. همانطوری که میدونید توابعی به صورت پیشفرض کامپایلر داخل کلاس تعریف میکنه. که یکی از این توابع اسمش سازنده (constructor) هست که وظیفه مقدار دهی کلاس را داره. این مثال رو در نظربگیرید : #include <iostream> class JustForTest{ private : int ClassVariable; public : JustForTest(const int& input) : ClassVariable(input){ } int ReturnClassVariable(){ return this->ClassVariable; } }; int main(){ JustForTest Object(10); std::cout << Object.ReturnClassVariable () << std::endl; return 0; } خب کاری که داخل این کلاس انجام شده اینکه یه کلاس به اسم JustForTeste تعریف شده که دارای یه متغیر و دو تابع عضو هست. که یکی از توابع ، تابع سازنده کلاس هست. این برنامه در اجرا هیچ مشکلی نداره و دقیقا همان چیزی که ما انتظار داریم را چاپ میکنه ، که مقدار ده هست. حالا مشکل وقتی پیش میاد که برنامه نویسی بیاد و از کلاس شما استفاده کنه و سهواً مقداری از نوع char به سازنده کلاس ارسال کنه : int main(){ JustForTest Object('3'); std::cout << Object.ReturnClassVariable () << std::endl; return 0; } بر خلاف انتظارمان این کد هم کامپایل میشه ، چرا که خود char نوعی از int هست. و مسلما خروجی نامناسبی هم داره. برای اینکه این مشکل رفع بشه اغلب برنامه نویس ها از این روش استفاده میکنن : class JustForTest{ private : int ClassVariable; JustForTest(const char& input){ } public : JustForTest(const int& input) : ClassVariable(input){ } int ReturnClassVariable(){ return this->ClassVariable; } }; به این صورت که سازنده ای با ورودی char را با نوع دسترسی private تعریف میکنن که باعث میشه برنامه نویس های دیگر نتوانن مقدار از نوع char به تابع شما ارسال کنن. اما ! واضحه که این روش زیاد جالب نیست و باعث ناخوانی و زشتی کد هم میشه. لذا بهتره که با استفاده از قابلیتی که سی پلاس پلاس فراهم کرده استفاده کنیم و این سازنده را از کلاس حذف کنیم. که این کار با استفاده از کلمه کلیدی delete صورت میگیره : class JustForTest{ private : int ClassVariable; public : JustForTest(const int& input) : ClassVariable(input){ } JustForTest(const char& input) = delete; int ReturnClassVariable(){ return this->ClassVariable; } }; به همین سادگی و بدون خون ریزی و اما کلمه کلیدی explicit : تقریبا ماننده همون مثالی هست که برای کلمه کلیدی delete در قسمت بالا زدم. همانطوری که دیدید با اینکه ما مقدار char به تابع سازنده کلاس ارسال کردیم بدون مشکل برنامه کامپایل و اجرا شد. اما اتفاقی که پشت صحنه افتاده این بوده که : کامپایلر خودش مقدار char را به int تبدیل (cast) کرده. برای اینکه از این تبدیل جلوگیری کنیم. از کلمه کلیدی explicit قبل از تابع سازنده استفاده میکنیم : #include <iostream> class JustForTest{ private : int ClassVariable; public : explicit JustForTest(const int& input) : ClassVariable(input){ } int ReturnClassVariable(){ return this->ClassVariable; } }; int main(){ JustForTest Object = '3'; std::cout << Object.ReturnClassVariable () << std::endl; return 0; } برنامه ی بالا کامپایل نخواهد شد. چرا که هیچ تابع سازنده ای با پارامتر char پیدا نشده ! اما ممکنه که سوال بپرسید : پس فرق explicit با delete در چی هست ؟ جواب سوال : اگه کمی به کد دقت کنید متوجه میشید که ما با استفاده از Copy initialization (یعنی استفاده از = برای مقدار دهی) سازنده کلاس را مقدار دادیم. ولی درصورتی که از direct یا uniform initialization استفاده کنیم کد ما همچنان کامپایل میشود.. مثال : int main(){ JustForTest Object('3'); std::cout << Object.ReturnClassVariable () << std::endl; return 0; } خب برای اینکه به طور کلی ما تابع سازنده ای با پارامتر char را محدود کنیم باید از کلمه کلیدی delete استفاده کنیم. خلاصه : کلمه کلیدی explicit برای محدود کردن تبدیل نوع در پارامتر کلاس هست. اما این در زمانی اتفاق می افتد که ما از copy initialization برای مقداردهی سازنده کلاس استفاده کنیم. و در صورت استفاده از direct یا uniform initialization دیگه این عمل امکان پذیر نیست. و برای اینکه یک تابع را به کلی از کلاس محدود کنیم از کلمه کلیدی delete استفاده میکنیم که باعث میشود هیچ شئ توانایی فراخوانی آن تابع را نداشته باشد.
-
3 امتیازاستفاده از توزیعهای آماری برای تولید اعداد تصادفی سرعت رو پایین میاره. چون مشخهٔ آماری توزیع (مثلاً توی مورد شما توزیع یکسان) باید در هنگام تولید اعداد رعایت بشه. به همین خاطر موقع تولید عدد ممکنه سه یا چهار بار عدد تصادفی تولید بشه. این مسأله موقع استفاده از توزیعهای آماری پیچیدهتر مثل توزیع نرمال شدیدتر هم میشه. تولید عدد تصادفی با توزیع نرمال در سیپلاسپلاس خیلی کنده. در مقابل اگر مشخصهٔ آماری براتون مهم نیست میتونید از توابع سادهٔ rand استفاده کنید که از سختافزار هم برای تولید عدد تصادفی کمک میگیرند: cat /dev/urandom | hexdump سرعت تولید عدد تصادفی به این روش خیلی بالاست اما آشفتگی لازم برای رمزنگاری رو نداره. اگه کاربرد خیلی جدی هست باید از randomبهجاش استفاده کنید که کندتره. توابع استاندارد هم از همینها استفاده میکنند.
-
3 امتیازتعریف ماکرو یک ماکرو به عنوان یک قطعه کدی (رشتهای) است که به آن نام مشخصی داده شده است. قطعه کد مربوطه میتواند شامل رشته، عدد، شیء، تابع و دیگر موارد باشد. زمانی که از این نام استفاده شود آن را با محتوای موجود در ماکرو جایگزین میکند. به طور کلی دو نوع ماکرو وجود دارد Object-Like (شیء مانند) برای استفاده در زمانی که محتوا شامل اشیاء باشد و Function-Like (تابع مانند) نیز زمانی مورد استفاده قرار میگیرد که شامل تابع میباشد. /* object-like macro */ #define <identifier> <replacement token list> /* function-like macro, note parameters */ #define <identifier>(<parameter list>) <replacement token list> نکته: ایجاد یک ماکروی سفارشی توسط دستور #define انجام میشود. /* create the macro */ #define <identifier> نکته: ماکروهای ایجاد شده توسط دستور #undef میتوانند حذف شوند. /* delete the macro */ #undef <identifier> نکته: ماکروها علاوه بر اینکه میتوانند توسط کاربر (توسعهدهنده) سفارشی ساخته شوند، همچنین از قبل به صورت از پیش تعریف شده برای انواع سیستمعاملها، معماریها و دیگر منظورها ساخته شده اند که تحت استانداردهای کامپایلرها متفاوت عمل میکنند. ماکرو از نوع شیء (Object-Like) یک ماکرو از نوع شیء شناسهی سادهای است که با یک قطعه کد جایگزین میشود. آن را شیء مانند مینامند زیرا، به نظر میرسد یک شیء از نوع داده در آن مورد استفاده قرار میگیرد. معمولاً آنها از نامهای نمادین برای ثابتهای عددی استفاده میشود. #define BUFFER_SIZE 1024 در کد فوق ماکروی BUFFER_SIZE دستور #define را دنبال میکند و مقدار ۱۰۲۴ را به عنوان مقدار آن در نظر میگیرد. در مثال زیر میتوانید نحوهی استفاده از یک ماکروی سفارشی از نوع شیء (Object-Like) را مشاهده کنید. #include <iostream> using namespace std; #define BUFFER_SIZE 1024 int main() { cout << "Buffer Size is : " << BUFFER_SIZE << endl; return 0; } ماکرو از نوع تابع (Function-Like) همچنین شما میتوانید از ماکروها مانند صدا زدن یک تابع استفاده کنید. این نوع ماکروها Function-Like هستند. برای تعریف این نوع شما باید از دستور پیشپردازندهی #define استفاده کرده و دو پرانتز ر بلافاصله پس از نام ماکرو قرار دهید. در مثال زیر ماکرویی با نام Maximum را برای محاسبهی بزرگترین عدد ورودی پیاده سازی کردهایم. #include <iostream> using namespace std; #define Maximum( a, b ) a > b ? a : b int main() { int x = 4; int y = 9; int z = Maximum( x, y ); cout << "Result : " << z << endl; return 0; } نسخهی معمولی آن میتواند به شکل زیر باشد. #include <iostream> using namespace std; int Maximum (int a, int b) { if (a > b) return a; else return b; } int main() { int x = 4; int y = 9; int z = Maximum( x, y ); cout << "Result : " << z << endl; return 0; } بعضی از موارد در حوزهی سفارشی سازی ماکروها میتواند به صورت سلیقهای و نسبت به نوع پروژه تعریف شوند. برای مثال قرار است در برنامهای نوع اولویت اشکالزدائی را مشخص کنیم. #include <iostream> using namespace std; #define DEBUG # if defined (DEBUG) # define DEBUG_LEVEL 5 #endif # if DEBUG_LEVEL < 3 # define DLEVEL "Low Level" # elif DEBUG_LEVEL > 3 # define DLEVEL "High level" #endif int main() { cout << "Debug level is : " << DLEVEL; return 0; } در کد بالا توسط پیش پردزندهی #define و پیش پردازندههای شرطی #if و #elif و #endif حالتی را ایجاد کردهایم که با مشخص سازی درجهی مشخصه DEBUG_LEVEL نتیجهی آن اعلام خواهد شد. ماکروهای از پیش تعریف شده بسیاری از ماکروهای از پیش تعریف شده توسط کامپایلرها و شرکتهای سازنده وجود دارد که در توسعه بسیار مفید و کاربردی هستند. برای مثال اگر نیاز باشد کد شما بر اساس نوع پلتفرمی که بر روی آن اجرا میشود واکنش متفاوتی را انجام دهد نیاز خواهد بود تا از چنین ماکروهای پرکاربری استفاده کنید. مثالهای زیر برخی از ماکروهای از پیش تعریف شده بر اساس استاندارد ISO را معرفی میکند. استانداردهای زبان نوع : __STDC__ تعریف شده برای استانداردهای ANSI X3.159-1989 | ISO/IEC 9899:1990 نوع : __STDC_VERSION__ تعریف شده C برای استانداردهای ISO/IEC 9899-1:1994 | ISO/IEC 9899:1999 | ISO/IEC 9899:2011 نوع : __cplusplus تعریف شده ++C برای استانداردهای ISO/IEC 14882:1998 | ISO/IEC 14882:2011 | ISO/IEC 14882:2017 | ISO/IEC 14882:2014 نوع : __cplusplus_cli تعریف شده برای ECMA-372 نوع : __embedded_cplusplus تعریف شده برای پلتفرمهای امبد در Embedded C++ یک مثال از کاربرد استانداردهای C تحت ماکروهای از پیش تعریف شده: #if defined(__STDC__) # define PREDEF_STANDARD_C_1989 # if defined(__STDC_VERSION__) # if (__STDC_VERSION__ >= 199409L) # define PREDEF_STANDARD_C_1994 # endif # if (__STDC_VERSION__ >= 199901L) # define PREDEF_STANDARD_C_1999 # endif # endif #endif مثالهای زیر برخی از ماکروهای از پیش تعریف شده در پلتفرمهای مختلف را معرفی میکند. پلتفرم ویندوز دسکتاپ (Windows) نوع : _WIN16 تعریف شده برای پلتفرمهای ۱۶ بیتی نوع : _WIN32 تعریف شده برای پلتفرمهای ۳۲ بیتی نوع : _WIN64 تعریف شده برای پلتفرمهای ۶۴ بیتی نوع : __WIN32__ تعریف شده برای پلتفرمهای ۳۲ بیتی توسط کامپایلرهای Borland C++ نوع : __TOS_WIN__ تعریف شده برای پلتفرمهای ویندوز توسط xlC نوع : __WINDOWS__ تعریف شده برای پلتفرمهای ویندوز توسط Watcom C/C++ پلتفرم ویندوز اِمبِد (Windows CE) نوع : _WIN32_WCE تعریف شده برای پلتفرمهای ویندوز ۳۲ بیتی در اِِمبِد نوع : WIN32_PLATFORM_ تعریف شده توسط Embedded Visual Studio C++ پلتفرم یونیکس مکینتاش (Unix macOS) نوع : macintosh تعریف شده نسخههای macOS نوع : Macintosh تعریف شده برای نسخههای macOS نوع : __APPLE__ تعریف شده برای Mac OS X توسط GNU C and Intel C++ نوع : __MACH__ تعریف شده برای Mac OS X توسط GNU C and Intel C++ پلتفرم لینوکس - کرنل (Linux Kernel) نوع : __linux__ تعریف شده برای کرنل لینوکس نوع : linux تعریف شده برای کرنل لینوکس - منسوخ شده (سازگار نیست با POSIX) نوع : __linux تعریف شده برای کرنل لینوکس - منسوخ شده (سازگار نیست با POSIX) پلتفرم اندروید (Android) نوع : __ANDROID__ تعریف شده برای اندروید پلتفرم یونیکس بیاِسدی (Unix BSD) نوع : __FreeBSD__ تعریف شده برای FreeBSD نوع : __NetBSD__ تعریف شده برای NetBSD نوع : __OpenBSD__ تعریف شده برای OpenBSD نوع : __bsdi__ تعریف شده برای BSDI نوع : __DragonFly__ تعریف شده برای Dragon Fly پلتفرم کیواِنایکس (QNX) نوع : __QNX__ تعریف شده برای نسخههای QNX 4.x نوع : __QNXNTO__ تعریف شده برای نسخههای QNX 4.x نکته : این مقاله ادامه دارد...
-
3 امتیازسلام، برخی از دوستان در گروه برنامهنویسی در رابطه با نحوهی بررسی وضعیت اینترنت و شبکه سوال پرسیده بودن که چطور میشه در سی++ تحت کیوت مخصوصاً همراه QML وضعیت آنلاین بودن رو در زمان واقعی بررسی کرد. من نمونه مثالی آماده کردم که در وضعیت زمان واقعی (Real-Time) هر چند ثانیه یک بار نسبت به وضعیت اینترنت واکنش نشون میده. برای دریافت این نمونه مثال از مخزن مربوطه استفاده کنید.
-
3 امتیازبا سلام، با توجه به درخواستهای مکرر از کاربران و اساتید محترم، نیاز جامعهی برنامهنویسی به معرفی محصولات و قابلیتهای یک زبان در قالب یک محصول قابل لمس و دیداری احساس میشد. بنابراین این بخش با هدف این که توسعهدهندگان بومی بتوانند محصولات و پروژههای خود را برای معرفی از جنبههای فنی و همچنین تجاری مطرح نمایند ایجاد شده است. هدف این است که شما توسعهدهندهی محترم بتوانید برای کسب نظر از تجربیات اساتید برای توسعه هرچه بهتر پروژهی خود و همچنین معرفی محصول نوشته شدهی خود اقدام کنید. در صورتی که محصول شما تحت زبان و استانداردهای ویژهای تولید شده است میتوانید آن را برای همگان نشان دهید تا بتوانند نمونهی واقعی یک محصول را در آن حوزه مشاهده نمایند. اهداف کلی معرفی محصولات نوشته شده توسط زبانهای مختلف (این کار باعث میشود توسعهدهندگان قابلیتهای یک زبان را در پروژه واقعی مشاهده کنند) هر چند ممکن است پروژههای کوچکی معرفی شود اما اینکه با یک زبان واقعاً چه کارهایی میتوان انجام داد بسیار مهم است. امکان نظر سنجی و کسب نظرات اساتید و افراد با تجربه برای بهبود هرچه بهتر پروژه شما امکان بررسی و ارسال نظر و امتیاز به پروژه شما جهت کسب امتیاز مهارتی و تجربی امکان بررسی پروژه و رزومههای واقعی شما توسط کارفرمایان و اساتید معتبر امکان ایجاد محیط رقابتی برای بهبود مهارتهای تخصصی و شخصی در توسعهدهندگان و در نهایت بهبود مهارتهای جامعهی برنامهنویسی نمونه قالب معرفی پروژه به صورت زیر میباشد: عنوان پروژه توضیحات در رابطه با کاربرد پروژه معرفی زبان برنامهنویسی بَکاِند معرفی زبان یا فناوریهای به کار گرفته شده در بخش فرانتاِند کتابخانهها و فریموُرکهای استفاده شده نوع پروژه (رایگان یا تجاری) تعداد توسعه دهندگان یا تیم حق چاپ و تکثیر (شخصی یا حقوقی) چند قطعه تصویر استاندارد از محیط محصول مثال: با سلام، عنوان: پروژهی جِنسیس (Genesis) توضیحات: این پروژه یک موتور برنامهنویسی چندسکویی در قالب یک چهارچوب تخصصی میباشد که در توسعه هرچه سریعتر محصولات و طراحی و همچنین مستقر سازی آنها بر روی پلتفرمهای مختلف کمک بسیاری میکند. زبانها و فناوریهای استفاده شده: زبان برنامهنویسی ++C فریم وُرک و کتابخانهها: کتابخانهی OpenSSL، LibCurl، STL ابزارهای ساخت: qmake، qbs و cmake نوع پروژه: تجاری (انحصاری شرکتِ Dotwaves LLC) نویسندگان: کامبیز اسدزده حق چاپ و تکثیر: شرکت داتویوز *دوستان میتوانند نظرات و پیشنهادات خود را در رابطه با این پروژه اعلام کنند.
-
3 امتیازاین تاپیک مخصوص نمونه مثالهایی از پروژهها، ماژولها، کامپوننتها و افزونههایی میباشد که به صورت استاندارد و مدرن توسط سیپلاسپلاس و جاوااسکریپت تحت فناوری Qt Quick طراحی میشوند. بدون هیچگونه تعارفی باید بگوییم هر نرمافزار (اپلیکیشن) و یا محصولی که ساخته میشود باید مطابق استانداردهایی که مهندسین طراحی بر روی آن تاکید دارند توسعه یابد. این استانداردها ممکن است شامل اصول کُدنویسی، الگوهای کدنویسی و یا قوانین روانشناسی رنگها، چیدمان اشیاء و هر موردی که میتواند در نتیجهی آن تاثیر مثبت داشته باشد مهم هستند. با هدف اینکه میخواهیم نمونه مثالهایی را برای تازه واردین قرار دهیم تا بتوانند به درستی ونحوهی صحیح طراحی و پیاده سازی دو بخش بکاِند و فرانتاِند آشنا شوند، نمونه مثالهای شما باید دارای شرایط زیر باشند ساختار استاندارد کلاسها و توابع در سمت سیپلاسپلاس استفاده از اشاره گرهای هوشمند و یا رعایت اصول مدیریت حافظه استفاده از ماکروهای سفارشی iOS، Android، Windows، macOS و لینوکس جهت مدیریت بهتر بعضی از ویژگیهای منحصربفرد سیستمعاملها تا جایی که میتوانید سعی کنید از ابزارهای qmake و qbs در این نمونه مثالها استفاده کنید رعایت رنگبندی و همچنین اصول UX درست مهم است مثال شما باید برگرفته و بر اساس استانداردهای توصیه شدهی doc.qt.io باشد. استفادهی بهینه از لنگرها و همچنین ترازبندی صحیح لایهها و نگهدارندهها در سمت QML استفاده از تصاویر و یا قالبهای استاندارد و سبک مانند SVG, PNG و base64 استفاده از فونت آیکونیکها مانند (FontAwesome) این پست ممکن است ویرایش و یا به روزرسانی شود. در ادامه شما میتوانید بر اساس شرایطی که ذکر شده است و با توجه به استانداردهای Google Material، Microsoft Fluent و همچنین Apple Human Interface نمونه مثالهای خود را ارائه دهید که برخی از مثالهای استاندارد در زیر آمده اند.
-
3 امتیازدر این قسمت قصد داریم تا با چند مفهوم پایهای تر در سیستم عامل ویندوز آشنا شویم. در ابتدا مفهوم (VAS (Virtual address spaces را مورد بررسی قرار میدهیم. فضای آدرسهای مجازی (VAS) یک مُدل برای مدیریت بهتر حافظه میباشد، زمانی که یک پردازنده اقدام به خواندن یا نوشنتن در یک مکان حافظه میکند، از یک آدرس مجازی استفاده میکند. به عنوان بخشی از عملیات خواندن یا نوشتن، پردازنده آدرس مجازی را به آدرس فیزیکی ترجمه میکند. دسترسی به حافظه از طریق یک آدرس مجازی مزایای زیر را دارد : یک برنامه میتواند از محدودهٔ مجاور آدرس های مجازی برای دسترسی به یک بافر حافظه بزرگ استفاده کند که در حافظه فیزیکی به یکدیگر متصل نیستند. یک برنامه میتواند طیفی از آدرس های مجازی برای دسترسی به بافری بزرگتر از حافظه فیزیکی موجود را مورد استفاده قرار دهد. حافظهٔ فیزیکی ( که به اندازه 4 کیلوبایت میباشد) را به فایل دیسک میفرستد. صفحات داده یا کد بین حافظهٔ فیزیکی و دیسک در صورت مورد نیاز منتقل میگردد (اولویت با صفحات قدیمی تر میباشد.که دیرتر به آنها مراجعه شده است). آدرس های مجازی مورد استفاده در فرایندهای مختلف از یکدیگر جدا شده اند. کد در یک فرآیند نمیتواند حافظهٔ فیزیکی را که توسط فرآیند دیگری یا سیستم عامل مورد استفاده قرار میگیرد تغییر دهد. محدودهٔ آدرسهای مجازی که در فرآیند در دسترس است، فضای آدرس مجازی برای فرایند میباشد. هر فرایند حالت کاربر، دارای فضای آدرس مجازی خصوصی خود است. برای یک فرایند 32 بیتی، فضای آدرس مجازی معمولاً محدودهٔ 2 گیگابایتی از 0x00000000 تا 0x7FFFFFFF است. برای یک فرآیند 64 بیتی فضای آدرس مجازی محدوده 8 ترابایتی 0x00000000000 تا 0x7FFFFFFFFFF است. طیفی از آدرسهای مجازی گاهی اوقات طیفی از حافظههای مجازی نامیده میشوند. این نمودار برخی از ویژگی های آدرس مجازی را نشان میدهد: این نمودار فضاهای آدرس مجازی را برای دو فرایند 64 بیتی نشان میدهد: Notepad.exe و MyApp.exe هر فرایند دارای فضای آدرس مجازی خود است که از 0x000'0000000 تا 0x7FF'FFFFFFFF قرار دارد. هر بلوک آبی نشان دهنده یک صفحه (به اندازه 4 کیلوبایت) از حافظه مجازی یا فیزیکی است. توجه داشته باشید که فرایند Notepad از سه صفحه پیوندی از آدرس های مجازی استفاده میکند، با شروع از آدرس 0x7F7'93950000. اما این سه صفحه مجاور آدرسهای مجازی به صفحات غیر مستقیم در حافظه فیزیکی نقش میشود. همچنین توجه کنید که هر دو فرایند با استفاده از یک صفحه از حافظه مجازی شروع از 0x7F7'93950000 استفاده میکنند، اما آن صفحات مجازی به صفحات مختلف حافظه فیزیکی نقش میشوند. فضای کاربر و فضای سیستم: فرایندهایی مانند Notepad.exe و MyApp.exe در حالت کاربر اجرا میشوند. اجزاء اصلی سیستمعامل و بسیاری از درایورها بیشتر در حالت کِرنل مورد استفاده قرار میگیرند. هر فرایندِ حالت کاربر دارای فضای آدرس خود است ، اما تمام کدهایی که در حالت هسته اجرا میگردند، یک فضای آدرس مجزا به نام فضای سیستم دارند (دارای فضای آدرس مشترک هستند) . فضای آدرس مجازی برای فرآیند کاربر حالت فعلی کاربر، user space نامیده میشود. در ویندوز 32 بیت، فضای آدرس مجازی موجود در دسترس 2 به توان 32 بایت (4 گیگابایت) است. معمولاً 2 گیگابایت کمتر برای فضای کاربر میباشد و ۲ گیگابایت بالاتر برای فضای سیستر در نظر گرفته میشود. در ویندوز 32 بیتی شما میتوانید گزینه ای (در هنگام بوت شدن) را مشخص کنید که بیش از 2 گیگابایت برای فضای کاربر در دسترس باشد . در نتیجه آدر مجازی کمتری در دسترس سیستم قرار میگیرد. شما میتوانید حجم فضای کاربر را تا 3 گیگا بایت افزایش دهید ، در این صورت فقط 1 گیگ فضا برای سیستم باقش میماند. در ویندوز های 64 بیتی مقدار فضای آدرس مجازی 2 به توان 64 بایت (16 اگزابایت) میباشد . اما تنها بخش کوچکی از این محدوده استفاده میگردد محدوده 8 ترابایت از 0x000'00000000 تا0x7FF'FFFFFFFF برای فضای کاربر استفاده میشود و بخش هایی از 248 ترابایت از 0xFFFF0800'00000000 تا 0xFFFFFFFF'FFFFFFFF برای فضای سیستم استفاده میگردد. کُدِ در حال اجرا در حالت کاربر دسترسی به فضای کاربر دارد، اما دسترسی به فضایِ سیستم ندارد. این محدودیت باعث میشود که کد کاربر حالت خواندن یا تغییر ساختار داده های محافظت شده سیستم عامل را نداشته باشد. کد در حالِ اجرا در حالت هسته دارای دسترسی به فضای کاربر و فضای سیستم میباشد. درایورها (راهاندازهایی) که در حالت هسته اجرا میشوند باید در نوشتن یا خواندن در فضای آدرس کاربر به دلایل زیر بسیار محتاط باشد: یک برنامه یوزر مُد (حالت کاربر)، یک در خواست برای خواندن برخی از دادهها را به یک دستگاه میفرستد. این برنامه آدرس اولیه یک بافر برای دریافت داده ها را فراهم میکند. یک دستگاه روتینِ درایور در حالت اجرا در حالت هسته، عملیات خواندن را شروع میکند و کنترل را به تماس گیرنده خود بازمیگرداند سپس اینتراپت دستگاه هر نخ (ترد) را که در حال اجرا است را قطع میکند. در این مرحله، درایور نباید دادهها را به آدرس اولیها ارسال کند که در برنامه کاربر، در قسمت اول به آن اشاره شد. این آدرس در فضای آدرس مجازی فرایند است که درخواست را آغاز کرده است، که به احتمال زیاد همانند فرایند فعلی نیست. مخازن (استخر حافظه) صفحهبندی شده و صفحهبندی نشده (Paged pool and Nonpaged pool) در فضای کاربری، تمام صفحات حافظه فیزیکی را میتوان به عنوان یک فایل دیسک به صورت صحیح برگرداند. در فضای سیستم، برخی صفحات فیزیکی میتوانند از بیین بروند و برخی نیز نمیتوانند. فضای سیستم دارای دو منطقه برای تخصیص حافظه پویا میباشد : paged pool و nonpaged pool. در حالت paged pool حافظه میتواند به صورت فایل (در صورت نیاز) به دیسک منتقل گردد. در حالت nonpaged pool هرگز حافظه نمیتواند به دیسک منتقل گردد. کتابخانهٔ پیوند پویا و فایلهای اجرایی (DLL و PE) در این قسمت کمی با ساختار فایل های اجرایی و بخصوص DLL ها آشنا میشویم. در خلاصه ترین حالت میتوان گفت Dynamic link library نام کتابخانههایی است که توسط برنامه ها استفاده میشوند و توسط مایکروسافت پیاده سازی شده ( که اغلب دارای پسوند dll میباشند). این فایل ها همانند ساختار فایل های exe در ویندوز دارای ساختار (PE (Portable Executable میباشد. این کتابخانهها میتوانند شامل کد و داده و منابع (ریسورسها) باشند. یکی از مزایای فایل های dll این است که یک بار در حافظه بارگذاری میشود و میتواند توسط چندین برنامه مورد استفاده قرار گیرد (به صورت مجازی برای هر برنامه کپی میشود). میتوان dll ها را در موقه نیاز در برنامه بارگذاری کرد و هر جا که دیگر مورد نیاز نبود آن را خالی (Unload) کرد. از طرفی دیگر میتوان از آن برای استفاده از برنامه های قابل بهروزرسانی نیز استفاده کرد به این صورت که میتوان آیکنها ، فونتها و کدهایی که در هسته اصلی برنامه جایگاهی ندارند را درون dll ها قرار داد و در هنگام بهروزرسانی تنها این dll ها را تعویض کرد. هر فایل اجرایی جدا از کدها و دادههای خود میتواند اطلاعات را از خارج از خود و از dll بگیرد. در هر فایل pe بخشی از هدر فایل، شامل آدرس جدول آدرس وارد کردن (Import) میشود که اطلاعات موجود در آن، آدرس توابعی که از dll ها فراخوانی میشود را در خود نگه داری میکنند ( البته این آدرس ها با پایهٔ آدرس dll ترکیب میشوند که در تصویر دوم هم قابل مشاهده است). تصویر زیر خلاصهای ار هدر فایلهایی با ساختار PE میباشد. در این عکس import adress table حاوی آدرس iat در برنامه میباشد. شکل زیر یک توضیح کلی تر و بهتر در اختیار ما میگذارد. در این شکل میتوان iat را بین دو بخش کد و داده ببینید. نمونه ای از فراخوانی یکی از توابع dll ها را در زیر میتوان مشاهده کرد. این تصویر کد اسمبلی یک برنامه میباشد. مثال های کاربردی: مثال اول: در مثال اول یک dll ساخته و آن را با rundll32.exe اجرا کنید. از قسمت پروژه جدید (New project) در قسمت سیپلاسپلاس پروژه ای از نوع win32project بسازید. در صفحه باز شده Next را بزنید. dll را انتخاب کرده و سپس تیک Empty project را بزنید و پروژه را بسازید. سپس به پروژه خود یک فایل cpp اضافه کنید و کدهای زیر را در آن بنویسید: //[dll01.dll] #include <windows.h> extern "C" __declspec (dllexport) void __cdecl hello() { ::MessageBox(0, L"hello world", 0, 0); } BOOL APIENTRY Dll(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { return TRUE; } برنامه را کامپایل کنید، سپس cmd را باز کرده و دستور زیر را در آن تایپ کنید . (در آدرسی که dll قرار دارد دستور را اجرا کنید یا این که آدرس کامل dll را به آن بدهید) c:\rundll32.exe dll01.dll,hello شکل کلی استفاده از این دستور: RUNDLL32.EXE <dllname>,<entrypoint> <optional arguments> با اجرای این دستور پنجرهای را میبینید که در آن پیغام موجود در dll را چاپ میکند. مثال دوم: در این مثال، دیالال (dll) ای که در مثال قبل ساختید را در یک برنامه دیگر با زبان c++ ایجاد و بعد از اتمام کار، آن را آن بارگذاری کنید. کُد برنامه مورد نظر به صورت زیر خواهد بود: #include <windows.h> #include <stdio.h> typedef void(__cdecl *MYPROC)(); int main(void) { HINSTANCE hinstLib; MYPROC ProcAdd; BOOL fFreeResult, fRunTimeLinkSuccess = FALSE; // Get a handle to the DLL module. hinstLib = LoadLibrary(TEXT("c://dll01.dll")); // If the handle is valid, try to get the function address. if (hinstLib != NULL) { ProcAdd = (MYPROC)GetProcAddress(hinstLib, "hello"); // If the function address is valid, call the function. if (NULL != ProcAdd) { printf("dll is loaded\n"); fRunTimeLinkSuccess = TRUE; (ProcAdd)(); } // Free the DLL module. fFreeResult = FreeLibrary(hinstLib); if (fFreeResult && ProcAdd) { printf("dll is Unloaded\n"); } else if (!fFreeResult && ProcAdd) { printf("error , dll is not Unload\n"); } } // If unable to call the DLL function, use an alternative. if (!fRunTimeLinkSuccess) { printf("Message printed from executable\n"); } system("pause"); return 0; }
-
3 امتیازدر این پست قصد دارم به توضیح کد بخش VTK در مثال استفاده از VTK با Qt در گیتهاب بپردازم. از فایل VTKmain.h شروع میکنم : #include "qobject.h" #include "vtkCubeSource.h" #include "vtkOrientationMarkerWidget.h" #include <QVTKWidget.h> #include <vtkActor.h> #include <vtkAxesActor.h> #include <vtkDataSetSurfaceFilter.h> #include <vtkIdFilter.h> #include <vtkOBJReader.h> #include <vtkPLYReader.h> #include <vtkPolyDataMapper.h> #include <vtkProperty.h> #include <vtkRenderWindow.h> #include <vtkRenderer.h> #include <vtkSmartPointer.h> #include <vtkSphereSource.h> در بخش بالا کتابخانه های مورد نیاز در پروژه اینکلود شدند . یک سری از این کتابخانهها مثل #include "qobject.h" کتابخانههای کیوت هستند. و یک سری کتابخانهها که در اسم آنها VTK به چشم میخورد کتابخانههای VTK هستند. برای اطلاعت بیشتر از هرکدام از این کتابخانهها میتوانید نام آن را جستجو کنید و به داکیومنت VTK برای آن کتابخانه و همچنین سورس آن کتابخانه دست یابید. بخش دوم کد : class VTKmain : public QVTKWidget { public: VTKmain(QWidget *parent = nullptr); ~VTKmain(); // vtk renderer vtkSmartPointer<vtkRenderer> renderer; vtkSmartPointer<vtkPolyDataMapper> mapper; vtkSmartPointer<vtkActor> actor; public slots: }; در این بخش یک کلاس به اسم VTKmain ساخته شده است و از QVTKWidget به ارث برده که یک کتابخانه توسعه داده شده توسط توسعهدهندگان VTK برای تعبیه کردن صفحه سه بعدی VTK در رابط کاربری گرافیکی Qt است. درون کلاس هم سه تعریف داریم که در فایل سورس بیشتر در مورد آنها توضیح خواهم داد. توضیحات فایل VTKmain.cpp : همانطور که مشاهده می کنید در این مثال ساده فقط در تابع سازنده کد نوشته شده است : VTKmain::VTKmain(QWidget *parent) : QVTKWidget(parent) در دو خط زیر پنجره را به اندازه مورد نظر ریسایز میکنیم و حداقل سایز پنجره را مشخص میکنیم : resize(1920, 1000); setMinimumSize(400, 200); در خط زیر با استفاده از vtkSmartPointer یک نمونه از vtkRenderer میسازیم و در اشارهگر هوشمند VTK که با اسم renderer در هدر تعریف کردیم میریزیم این روند کلی ایجاد یک شی با استفاده از اسمارت پوینتر VTK است و برای بقیه کلاسها هم به همین منوال عمل میکنیم : renderer = vtkSmartPointer<vtkRenderer>::New(); در خط 19 رنگ پسزمینه را تنظیم میکنیم مقادیر ورودی این تابع بین 0 و 1 هستند و نشانگر استاندارد رنگی قرمز-سبز-آبی است : renderer->SetBackground(0, 0, 0); در خط 20 پنجره رندر از کلاس (به ارث برده شده از QVTKWidget ) را میگیریم و رندرر را به آن اضافه میکنیم : GetRenderWindow()->AddRenderer(renderer); در خط 22 و 23 یک مکعب ایجاد میکنیم : vtkSmartPointer<vtkCubeSource> cube = vtkSmartPointer<vtkCubeSource>::New(); در خط 26 یک نمونه برای mapper ایحاد میکنیم : mapper = vtkSmartPointer<vtkPolyDataMapper>::New(); در خط 27 پورت خروجی مکعب را به اتصال ورودی mapper میدهیم : mapper->SetInputConnection(cube->GetOutputPort()); در خطوط 29 تا 32 یک اکتور ایجاد کرده و mapper را که در بالا ساختیم برای ان تنظیم میکنیم و اندازهی نقاط را برای ان تنظیم میکنیم و در خط 32 رنگ آن را تنظیم میکنیم : actor = vtkSmartPointer<vtkActor>::New(); actor->SetMapper(mapper); actor->GetProperty()->SetPointSize(1000); actor->GetProperty()->SetColor(1, 1, 0); //(R,G,B) در خط 33 این اکتور را به رندرر اضافه میکنیم : renderer->AddActor(actor); در خطوط 35 و 36 یک نمونه از axes برای نمایش جهت در کنار صفحه به صورت سه بعدی ایجاد میکنیم : vtkSmartPointer<vtkAxesActor> axes = vtkSmartPointer<vtkAxesActor>::New(); در خطوط 38 و 39 یک ویوپورت برای نمایش این جهتنما درست میکنیم چون نمیخواهیم با جابجایی سه بعدی صحنه این جهتنما از گوشه پنجره نکان بخورد و حرکت انتقالی در سه بعد داشته باشد: vtkSmartPointer<vtkOrientationMarkerWidget> axesViewPort = vtkOrientationMarkerWidget::New(); در خطوط 41 تا 46 به ترتیب رنگ دور ویوپورت ، اکتور جهت نمایش ، اینتراکتور رندر ویندو ، اندازه و مکان دو بعدی ویو پورت در صفحه ( بین پراپرتیها بین 0 و 1 هستند ) ، فعال بودن و تعاملی بودن را تنظیم میکنیم که این گزینه آخر در صورت فعال بودن این امکان را به کاربر میدهد که با موس ویوپورت ساخته شده را جابجا کند : axesViewPort->SetOutlineColor(0.9300, 0.5700, 0.1300); axesViewPort->SetOrientationMarker(axes); axesViewPort->SetInteractor(GetRenderWindow()->GetInteractor()); axesViewPort->SetViewport(0.9, 0.0, 1.0, 0.1); axesViewPort->SetEnabled(1); axesViewPort->InteractiveOff(); در خط 48 مکان دوربین فعال را تنظیم میکنیم : renderer->GetActiveCamera()->SetPosition(1000, 2500, 1000); در خط 49 تابع رندر از رندرر را صدا زده : renderer->GetActiveCamera()->SetPosition(1000, 2500, 1000); و در خط 50 تابع ریست دوربین رندرر را صدا میزنیم تا تغییراتی که انجام دادیم قابل مشاهده شوند : renderer->ResetCamera();
-
3 امتیازهمانطور که میدانید در بازیهای رایانهای مدیریت حرکت کاراکتر یا شیء در محیط توسط کلیدهای روی صفحه کلید و یا دستهی بازی مدیریت میشوند. در این پست چگونگی واکنش نشان دادن به فشرده شدن کلیدهای بالا (رو به جلو)، پایین (رو به عقب)، چپ و راست را بررسی میکنیم. ابتدا توابع مورد نیاز را جهت نمایش در خروجی پیاده سازی میکنیم: void MoveToUp(){ std::cout << "Moved to Up!" << std::endl; } void MoveToDown(){ std::cout << "Moved to Down!" << std::endl; } void MoveToLeft(){ std::cout << "Moved to left!" << std::endl; } void MoveToRight(){ std::cout << "Moved to right!" << std::endl; } void Fire(){ std::cout << "Shooted! Boooom!" << std::endl; } سپس تحت کلاس sf::Keyboard آنها را مدیریت میکنیم: if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) { // move left... MoveToLeft(); } else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) { // move right... MoveToRight(); } if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) { // move up... MoveToUp(); } if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) { // move down... MoveToDown(); }
-
3 امتیازفرض بر اینکه قرار است تابع یا کلاس شلیک توسط دستهی بازی اجرا شود. ابتدا باید مطمئن باشید که دستهی بازی به سیستم متصل و توسط سیستم عامل شناسایی شده است. برای این منظور دستور زیر را خواهیم داشت: if (sf::Joystick::isConnected(0)) { // joystick number 0 is connected } سپس تحت یک دستور ساده و شرطی میتوان تابع مورد نظر را با فشرده شدن کلید روی دسته اجرا کرد: if (sf::Joystick::isButtonPressed(0, 1)) { Fire(); } در ادامه مثالی زدهایم که اطلاعات دستهی متصل شده را گرفته و در نهایت با فشرده شدن کلید روی آن تابع Fire اجرا میشود.? #include <SFML/Window.hpp> #include <iostream> void GetDeviceInfo(){ if (sf::Joystick::isConnected(0)) { //get information about the joystick sf::Joystick::Identification id = sf::Joystick::getIdentification(0); std::cout << "\nVendor ID: " << id.vendorId << "\nProduct ID: " << id.productId << std::endl; sf::String controller("Joystick Use: " + id.name); } } void Fire(){ std::cout << "Shooted! Boooom!" << std::endl; } int main() { sf::Window window(sf::VideoMode(640, 480), "Hello world!"); GetDeviceInfo(); while (window.isOpen()) { sf::Event event; while (window.pollEvent(event)) { if (event.type == sf::Event::KeyPressed) window.close(); } if (sf::Joystick::isButtonPressed(0, 1)) { Fire(); } // check the type of the event... switch (event.type) { // window closed case sf::Event::Closed: window.close(); break; // key pressed case sf::Event::KeyPressed: std::cout << "Key pressed!" << std::endl; break; case sf::Event::MouseMoved: break; // we don't process other types of events default: break; } } return 0; }
-
3 امتیازبا توجه به وجود کتابخانههای متعدد در سیپلاسپلاس در این پُست قصد داریم آموزشهایی در رابطه با نحوهٔ راه اندازی انواع کتابخانهها را در سیپلاسپلاس توضیح دهیم. محیطهای توسعه جهت نصب Visual Studio و Qt Creator خواهند بود. در صورتی که نیاز است کتابخانهای را به صورت سفارشی کامپایل کنید نکاتی را باید مورد توجه قرار دهید که در ادامه آمدهاند. قبل از هر چیز نیاز است توضیحاتی در رابطه با انواع کتابخانهها داده شود. کتابخانهها برای اینکه در پروژه مورد استفاده قرار بگیرند نیاز است آنها از سمت منبع خود کامپایل و ساخته شوند. البته در این فرآیند باید توجه داشته باشید که نوع معماری در پیکربندی یک کتابخانه بسیار مهم است. برای مثال اگر قرار است کتابخانهای را بر روی یک پروژهای که تحت معماری x64 پیکربندی شده است و در وضعیت release منتشر شود، در این صورت حتماً باید کتابخانه مورد نظر تحت همین پیکربندی کامپایل شود. کتابخانهها ممکن است خودشان وابستهٔ کتابخانههای دیگری باشند. برای مثال بخشی از ماژول کتابخانه Boost و Poco وابستهٔ کتابخانهٔ OpenSSL میباشد. و یا بخشی از کتابخانهٔ MySQL وابستهٔ کتابخانهٔ Boost میباشد. بنابراین قبل از پیکربندی پروژه تحت هر کتابخانهای مطمئن شوید که پیش نیازات آن را در اختیار داشته باشید. توجه داشته باشید که حتماً راهنمای کتابخانهٔ مورد نظر خود را جهت نحوهٔ پیکربندی مطالعه نمایید، زیرا هیچ روش عامیانهای وجود ندارد که بر روی تمامی کتابخانهها صادق باشد. با توجه به نکات بالا آموزش لازم جهت پیکربندی و راه اندازی کتابخانهها را تحت دو گزینهٔ Boost و MFSL ادامه میدهیم: نسخهٔ مورد نظر کتابخانهٔ مورد نظر را از این بخش دریافت کنید. فایل دریافت شده را استخراج و در یک مسیر مشخصی مانند C://کتابخانهٔ شماکپی کنید. محیط کنسول در سیستم عامل را باز کنید، پیشنهاد میشود از Visual Studio Cross Tools Command Prompt استفاده کنید. به مسیر کتابخانه تحت دستور cd رفته و وارد آن شوید. در این مرحله نیاز است تا قبل از ساخت کتابخانه آن را پیکربندی کنید، بنابراین دستور زیر را اجرا خواهیم کرد: ./configure دقت کنید که این مرحله معمولاً در کتابخانهها متفاوت میباشد، برای مثال در کتابخانهٔ Boost فایلی به نام bootstrap.bat متخص ویندوز و فایل bootstrap.sh برای محیطهای یونیکس موجود است که وظیفهٔ پیکربندی و تولید فایل ساخت را بر عهده دارد. البته در نظر داشته باشید که این چنین پیکربندی در کتابخانههای خاص ممکن است و در بیشتر آنها باید با دستورات configure و فلگهای موجود در هر یک از آنها اقدام به پیکربندی کنید. بنابراین با توجه این مورد میتوانید آموزش لازم را در این بخش پیگیری نمایید. بعد از پیکربندی دستور make، nmake، cmake و یا qmake متناسب با نوع ابزار سازنده باید اجرا شود تا کتابخانه بر اساس پیکربندی تنظیم شده شروع به کامپایل و ساخت کند. این مرحله معمولاً بر اساس قدرت پردازشی سیستم شما زمان متغیری خواهد داشت. بعد از به اتمام رسیدن زمان کامپایل کتابخانهٔ مورد نظر فایلهای lib را تحت پسوندهای .dll در ویندوز و .lib و .so در لینوکس و یونیکس تولید خواهد کرد که بهتر است مسیر include برای هدرهای کتابخانه و lib برای فایلهای کامپایل شده مشخص شود. طبق شرایط ذکر شده برای مثال ما از کتابخانهٔ SDL در این بخش استفاده خواهیم کرد. نسخهٔ از پیش کامپایل شده مربوط به آن را از این بخش دریافت و استخراج نمایید. قست اول (نصب و راه اندازی تحت محیط Visual Studio) وارد محیط ویژوال استودیو شده و بعد از ایجاد پروژه بر روی پروژه راست کلیک و گزینهٔ Properties را انتخاب کنید، به زبانه C/C++ رفته و زبانه General گزینهٔ Additional Include Directories را انتخاب کنید. در ادامه مسیر include را از کتابخانهٔ SDL به پروژه معرفی کنید. مرحله کنونی را تایید کنید، و به زبانهٔ Linker و سپس General بروید، در این بخش گزینهٔ Additional Linker Library را انتخاب و مسیر Lib را از کتابخانهٔ SDL معرفی کنید. در این مرحله فایلهای کتابخانه معرفی شدهاند. به زبانهٔ General و Input برگشته و در بخش Additional Dependences فایلهای SDL2.lib و SDL2_image.lib و SDL2main.lib و SDL2_ttf.lib را معرفی کنید. در نهایت فایلهای dll موجود در پوشهٔ lib کتابخانه را در کنار فایل اجرایی کپی کنید. قست دوم (نصب و راه اندازی تحت محیط Qt Creator) پروژه خود را ایجاد و بر روی نام پروژه راست کلیک کنید. گزینهٔ Add Library و سپس External Library را بزنید. طبق شرایط قبل گزینههای lib را همراه با include به پروژهٔ خود اضافه نمایید. کد مربوط به فایل .pro به صورت زیر خواهد بود win32: LIBS += -L$$PWD/../../../../SDL2-2.0.8/lib/x86/ -lSDL2 -lSDL2main -lSDL2_ttf INCLUDEPATH += $$PWD/../../../../SDL2-2.0.8/lib/x86 DEPENDPATH += $$PWD/../../../../SDL2-2.0.8/lib/x86 طبق روش کامپایل برنامه را کامپایل کنید و قبل از اجرا فایلهای dll یا lib را نسبت به پلتفرم خود در کنار فایل اجرایی پروژه قرار دهید. https://iostream.ir/forums/topic/33-روش-افزودن-کتابخانههای-دیگر-به-محیط-qt-creator/ روش فوق در بیشتر کتابخانهها قابل انجام است.
-
3 امتیازطبق موضوع قبلی جهت راه اندازی و استفاده از این کتابخانه برای آزمایش ساده ترین کُد ممکن در این کتابخانه در نسخهی ویندوز یکی از محیطهای توسعه نرمافزار مانند Qt Creator یا Visual Studio را اجرا کرده و یک پروژه ساده ایجاد کنید. ما در این مثال قرار است یک پنجره با ابعاد مشخصی را نمایان سازیم که به صورت زیر خواهد بود. نیاز است هدر SDL را به این صورت به کد خود اضافه کنیم: #include <SDL.h> سپس کُد زیر نمونه ساده ای از نمایش پنجره تحت SDL خواهد بود که در تابع main فراخوانی شده است: #include "SDL.h" int main(int argc, char ** argv) { bool quit = false; SDL_Event event; SDL_Init(SDL_INIT_VIDEO); SDL_Window * window = SDL_CreateWindow("Hello, World!", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0); SDL_Renderer * renderer = SDL_CreateRenderer(window, -1, 0); while (!quit) { SDL_WaitEvent(&event); switch (event.type) { case SDL_QUIT: quit = true; break; } } SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_Quit(); return 0; } شمارندهی SDL_Event از هسته کتابخانه جهت مدیریت انواع رخدادها میباشد. در ادامه کُد SDL_Init(SDL_INIT_VIDEO); جهت مقدار دهی اولیه است. جهت سفارشی سازی چنین بخشی بهتر است کُد آن به صورت زیر نوشته شود: if (SDL_Init(SDL_INIT_VIDEO) != 0){ std::cout << "SDL_Init Error: " << SDL_GetError() << std::endl; return 1; } در ادامه SDL_Window به عنوان نوع ساختار در SDL میباشد که با متد SDL_CreateWindow ترکیب و مقادیری چون عنوان، محورهای y و x همچنین طول و عرض پنجره و در نهایت تنظیم فلگ وضعیت پنجره میباشد که به صورت پیش فرض بر روی مقدار ۰ تنظیم شده است. در صورتی که لازم باشد پنجره شما به صورت تمام صفحه نمایان شود کافی است فلگ آن را روی مقدار ۲ یا ۳ قرار دهید. جهت تولید (رندر) و ارسال پنجره به این مرحله کافی است از SDL_Renderer نمونه گرفته و پنجرهی خود را به متُد SDL_CreateRenderer ارسال کنید. در ادامه برای بررسی وضعیت حلقهای تعریف شده است که در صورت رخداد خروج اجرا خواهد شد. while (!quit) { SDL_WaitEvent(&event); switch (event.type) { case SDL_QUIT: quit = true; break; } } در نهایت SDL_DestroyRenderer جهت نابود سازی زمینهی تولید یک پنجره و تمامی موارد همراه آن و همچنین SDL_DestroyWindow جهت نابود سازی پنجره ساخته شده مورد استفاده قرار میگیرد که معمولاً در تمامی برنامههای تحت SDL مورد استفاده قرار خواهند گرفت. تابع SDL_Quit(); جهت پاکسازی تمامی موارد مقدار دهی شده زیر سیستمی مورد استفاده قرار میگیرد. برنامه را اجرا کنید، حال باید پنجرهای در ابعاد ۶۴۰ در ۴۸۰ پیکسل با عنوان Hello, World تولید و نمایش داده شود.?
-
3 امتیازمشکل من حل شد اما با یک کار اضافه دیگه ابتدا پلاگین مربوط به اندروید با نام libqsvg.so که در پوشه پلاگین هست رو کپی کردم در فولدر برنامه م بعد در فایل .pro باید این خط کد اضافه میشد تا آیکن با فرمت svg نشون بده : QT += svg و الان راحت ایکن با فرمت svg نشون میده در دستگاه اندروید. ممنون
-
3 امتیازمقدمهای ساده با توجه به فعالیتهای هیجان انگیز اخیر گوگل و کنفرانس آیاو امسال (Google IO/2018) که فلاتر (Flutter) رو معرفی کرد، فلاتر به یاری چند تا از ویژگیهای قدرتمندش توانست توجه تقریبا تعداد زیادی از توسعه دهندهها را به خود جلب کند و باعث کنجکاوی آنها شود. با توجه به این که شروع کار با این فریمورک در ایران به دلیل تحریم ممکن است کمی دردسر ساز باشد، بنده این آموزش ساده و صریح رو آماده کردم تا شاید گره از کار کسی باز شود و همچنین معرفی دوباره و دقیقتر فلاتر به زبان شیرین پارسی میتواند درک بهتری از این فریمورک و ویژگی های قدرتمندش به ما بدهد. پس با من همراه باشید. ? نکته: لازم به ذکر است قبل از شروع نصب، برای دریافت پیشنیازها، نیاز به پروکسی دارید. پس حتما یکی تهیه کنید! فلاتر (Flutter) چیست؟ به گفتهی گوگل: کاربران برنامه ها انتظار دارند برنامه های شما دارای طراحی زیبا، انیمیشنهای نرم و کارایی بالا باشند. برای رسیدن به این امر، توسعه دهندهها نیاز دارند تا بدون نگرانی برای کیفیت یا کارایی امکانات جدید را سریع تر از همیشه بسازند. به همین دلیل ما فلاتر را ساختیم. فلاتر، فریموک UI موبایل گوگل که یک راه سریع و واضح برای توسعه دهندهها فراهم میکند تا روی آی او اس و اندروید برنامههای بومی (Native) بسازند. این به خاطر این است که برنامههای ساخته شده با فلاتر از یک کد پایه ساخته شدهاند، مستقیما به کد بومی Arm کامپایل میشوند، از پردازنده گرافیکی (GPU) استفاده میکنند و میتوانند به ایپیآی (API) ها و سرویس های پلتفرم مورد نظر دسترسی داشته باشند. فلاتر میتواند به سه طریق در همان روز اول به شما کمک کند: سرعت بالای توسعه: فلاتر برای سرعت بالای توسعه دهنده مهندسی شده است. راهاندازی گرم با حفظ وضعیت (Stateful hot reload) این اجازه را به شما میدهد که کد خود را تغییر داده و تغییرات را در کمتر از یک ثانیه و بدون از دست دادن حالت برنامه مشاهده کنید! علاوه بر این فلاتر با ابزار توسعه ی مشهور ادغام میشود؛ یعنی شما میتوانید سریعا با ادیتور یا IDE ای که میشناسید و دوست دارید خود شروع به کار کنید. رابط کاربری منعطف: فلاتر ویجتها، رندر کردنها، انیمیشنها و حرکات (Gesture) را به فریمورک انتقال میدهد تا برای شما کنترل کامل روی هر پیکسل از صفحه را فراهم کند! این یعنی شما انعطاف دارید تا طراحی های شخصی سازی شده بسازید. برنامههای بومی برای آیاواس و اندروید: برنامه های فلاتر قرارداد های پلتفرم و جزئیات صفحه را مثل اسکرول کردن (Scrolling)، پیمایش، آیکونها، فونتها و ... را دنبال میکند. به همین دلیل است که برنامههای ساخته شده با فلاتر در اپ استور و گوگل پلی مورد تایید است. فلاتر برای توسعه دهندهها عالی است، هم برای افراد باتجربه و هم برای تازه کاران در موبایل! اگر شما در موبایل تازه کار هستید، فلاتر به شما یک راه سریع، جالب و مدرن برای ساخت برنامههای بومی میدهد. اگر شما یک توسعه دهندهی با تجربهی موبایل هستید، میتوانید فلاتر را جریان کار و ابزارهای موجود خود اضافه کنید. فلاتر آزاد و متنباز است، و توسط توسعه دهندهها و سازمانهای جهان مثل enterprise، آژانسها و استارتآپ ها استفاده شده است. برای اطلاعات بیشتر و شروع میتوانید به وبسایت فلاتر مراجعه کنید. شروع کار با فلاتر نکته: مراحلی که اینجا توضیح داده شده نسخه فارسی این لینک است به علاوه ی نکتههایی که چطور قسمتهایی که به دلیل تحریم کار نمیکنند را به راه بیاندازیم. در صورت وجود مشکل دیگری لطفا کامنت بگذارید تا در صورت حل مشکل این پست آپدیت شود. دانلود کیت توسعه نرمافزار فلاتر (Flutter SDK): برای شروع ابتدا باید کیت توسعه فلاتر را دانلود کنید در اینجا چون ما با سیستم عامل اوبونتو کار میکنیم لازم است که به این لینک مراجعه کرده و کیت توسعه فلاتر را دانلود کنیم. لینک دانلود در تصویر زیر قابل مشاهده است. که زمان انتشار این نوشته نسخه 0.3.2 بتا است. فایل فشرده دانلود شده را به دایرکتوری مورد نظر خود انتقال داده و آن را استخراج (Extract) کنید. برای مثال: $ cd ~/development $ tar xf ~/Downloads/flutter_linux_v0.3.2-beta.tar.xz وقتی که با ترمینال در دایرکتوری مورد نظر هستید با اجرای دستور زیر به صورت موقت ابزار فلاتر را به مسیر خود اضافه کنید: $ export PATH=`pwd`/flutter/bin:$PATH حالا شما آماده هستید که دستورات فلاتر را وارد کنید. اجرای دکتر فلاتر: دستور زیر را اجرا کنید تا ببینید آیا وابستگیای وجود دارد که شما برای کامل کردن نصب نیاز به نصب آن داشته باشید: $ flutter doctor این دستور محیط شما را بررسی کرده و گزارشی برای شما در صفحه ترمینال نمایش میدهد. کیت توسعهی دارت همراه با فلاتر وجود دارد و ضروری نیست که دارت را به صورت جدا نصب کنید. به دقت خروجی این دستور را برای برنامههای دیگری که نیاز به نصب آن دارید بررسی کنید. ممکن است لازم باشد کارهای دیگری هم انجام دهید. برای مثال: [-] Android toolchain - develop for Android devices • Android SDK at /Users/mrdimaan/Library/Android/sdk ✗ Android SDK is missing command line tools; download from https://goo.gl/XxQghQ • Try re-installing or updating your Android SDK, visit https://flutter.io/setup/#android-setup for detailed instructions. مراحل پایین تر نحوه انجام این کارها و اتمام روند نصب را به شما نشان میدهند. بروزرسانی مسیر شما: شما میتوانید متغیر آدرس خود را فقط برای جلسه (session) در حال حاظر در خط فرمان بروزرسانی کنید. (همانطور که بالاتر آن را انجام دادیم). احتمالا میخواهید این متغیر یا برای همیشه آپدیت کنید، تا بتوانید دستورات فلاتر را در هر جلسه ترمینال اجرا کنید. ابتدا با ترمینال به دایرکتوری که پوشه با نام flutter در آن قرار دارد بروید و سپس با دستور pwd آدرس کامل آن مسیر را بدست آورید. برای مثال: $ pwd $ /home/moein/Documents/flutter-dev حالا فایل .bash_profile را باز کنید. در صورتی که این فایل وجود ندارد آن را بسازید، عبارت زیر را در آن قرار دهید و به جای [PATH] آدرسی که از طریق pwd بدست آوردید را قرار دهید: export PATH=[PATH]/flutter/bin:$PATH حالا دستور زیر را اجرا کنید تا پنجره ی در حال حاظر را تازه سازی (Refresh) کند: $ source $HOME/.bash_profile نصب اندروید نکته: فلاتر به نصب کامل اندروید استودیو متکی است تا وابستگی های پلتفرم اندروید آن را استفاده کند. با این حال شما میتوانید برنامه های فلاتر خود را در ادیتور های مختلفی بنویسید. نصب اندروید استودیو اندروید استودیو را از اینجا دانلود کرده و نصب کنید. توجه داشته باشید که برای دسترسی به این وبسایت حتما باید پروکسی خود را فعال کنید. اندروید استودیو را اجرا کنید. در اولین برخورد صفحه نصب را میبینید. به دلیل تحریم، اندروید استودیو قادر به دانلود یا یافتن ابزار و SDK نخواهد بود بنابراین در اولین نصب با رفتن به مراحل بعدی چیزی دانلود نخواهد شد. بعد از رسیدن به مرحله آخر و انتخاب دکمه Finish صفحه خوشآمدگویی برای شما باز میشود که باید از پایین صفحه تنظیمات را باز کرده و به قسمت پروکسی وارد شوید. بعد از وارد کردن مشخصات پروکسی برنامه را ببندید و دوباره باز کنید این دفعه هم صفحه نصب را مشاهده خواهید کرد با این تفاوت که در مراحل نصب اندروید استودیو به صورت اتوماتیک آخرین کیت توسعه اندروید (Android SDK)، کیت ابزار پلتفرم (Android SDK Platform-Tools)، و کیت ابزار بیلد (Android SDK Build-Tools) را دانلود میکند که برای توسعه برنامه اندروید با فلاتر مورد نیاز است. نصب دستگاه اندرویدی شما ابتدا Developer options و USB debugging را در دستگاه خود فعال کنید. با استفاده از کابل USB موبایل خود را به کامپیوتر وصل کنید و اگر در موبایل شما اجازه خواست آن را تایید کنید. در ترمینال دستور flutter devices را اجرا کرده تا ببینید فلاتر دستگاه اندروید شما را شناسایی کرده یا خیر. برنامه فلاتر خود را با اجرای دستور flutter run راه اندازی کنید. نصب شبیهساز اندروید برای آماده سازی تست و اجرای برنامه فلاتر شما روش شبیهساز اندروید این مراحل را دنبال کنید: قابلیت VM Acceleration را روی کامپیوتر خود فعال کنید. AVD Manager را که در مسیر Android Studio>Tools>Android قرار دارد اجرا کنید و یک دستگاه مجازی بسازید. در قسمت Emulated Performance گزینه Hardware - GLES 2.0 را انتخاب کنید تا hardware acceleration را فعال کنید. حالا درست بودن مشخصات را تایید کرده و Finish را انتخاب کنید. سپس دستگاه شما در لیست دستگاه های اندروید مجازی اضافه میشود پس با کلیک روی آیکون Run دستگاه اندرویدی را راه اندازی کنید. حالا برنامه ی خود را با دستور flutter run اجرا کنید. آماده سازی محیط برنامه نویسی اندروید استودیو در صورتی که میخواهید از این IDE برای برنامه نویسی برنامه خود استفاده کنید کافیست پلاگین Flutter و Dart را در اندروید استودیو نصب کنید سپس بعد از یکبار راه اندازی مجدد اندروید استودیو قابلیت های جدیدی مربوط به فلاتر به اندروید استودیو اضافه خواهد شد و در صفحه خوش آمد گویی گزینه ای برای ساخت پروژه فلاتر جدید نمایان خواهد شد. برای اجرای برنامه خود کافیست دستگاه اندروید مجازی خود را راه اندازی کرده و دکمه ی run در اندرید استودیو را انتخاب کنید. ویژوال استودیو کد در صورت استفاده از ویژوال استودیو کد هم به همین صورت میتوانید افزونه Flutter را نصب کنید. با نصب افزونه Flutter افزونه ی Dart هم به صورت خودکار نصب خواهد شد. حالا برای ساخت پروژهی جدید کافیست Ctrl + shift + p را بزنید، حالا در ورودی flutter را تایپ کنید و از بین گزینههای نمایش داده شده New Project را انتخاب کنید. همچنین برای اجرای پروژه میتوانید در گزینههای نمایش داده شده run را انتخاب کنید. نکته خیلی مهم: اگر هنوز نتوانستید برنامه ی خود را اجرا کنید اصلا نگران نباشید. چون باید برای Gradle هم پروکسی ست کنید تا برنامه شما اجرا شود. ? برای این کار فایل gradle.properties را باز کرده و محتوای داخل آن را به این صورت تغییر دهید و مشخصات پروکسی خود را به جای داده های فایل وارد کنید: org.gradle.jvmargs=-DsocksProxyHost=0.0.0.0 -DsocksProxyPort=1080 همچنین نیاز هست تا محتویات فایل build.gradle را به شکل زیر تغییر دهید: buildscript { repositories { jcenter () maven { url "https://maven.google.com" } } dependencies { classpath 'com.android.tools.build:gradle:3.0.1' } } allprojects { repositories { jcenter () maven { url "https://maven.google.com" } } } rootProject.buildDir = '../build' subprojects { project.buildDir = "${rootProject.buildDir}/${project.name}" } subprojects { project.evaluationDependsOn(':app') } task clean(type: Delete) { delete rootProject.buildDir }
-
3 امتیازمقدمه گاهی اوقات ارزش این را دارد که چند قدم به عقب برداریم و از دید یک تازهکار دنیای توسعه را نگاهی بیاندازیم. امروزه که استقبال زیادی از فریمورک (framework) انگولار میشود، پرسشهای زیادی در مورد انگولار در ذهن توسعه دهندهها به وجود آمده پرسشهایی مانند: انگولار چیست؟ چرا باید انگولار را استفاده کنیم؟ چه موقع نباید از انگولار استفاده کنیم؟ در این مقاله من پاسخ این پرسشها و مطالب بیشتری را میدهم. نگاهی خواهیم انداخت به این که انگولار چیست، چگونه راهاندازی شد و چه زمانی استفاده از انگولار ایدهی خوبی است. بگذارید از ابتدا شروع کنیم و ببینیم چگونه فریمورک انگولار راه اندازی شد؟ انگولار چگونه راهاندازی شد؟ انگولار به عنوان یک پروژهی جانبی شروع شد. در سال 2009، میسکو هِوِری (Miško Hevery) و آدام ابرونز (Adam Abrons) پروژهای را تحت عنوان <angular/> منتشر کردند که به توسعه دهندهها و طراحان کمک میکرد تا با استفاده از تگ (tag) های ساده HTML وب اپلیکیشنهایی (Web application) بسازند. نام "Angular" از براکت های زاویهدار یا <> میآید، که تمام تگهای HTML را احاطه میکنند. میسکو ایدهی پشت این فریمورک را در مصاحبهای که در سال 2013 انجام شد شرح داد: چون دامین angular.com گرفته شده بود - که هنوز هم گرفته شده - حامیها نام کتابخانه را به GetAngular تغییر دادند و سایت کوچکی را قرار دادند که دربارهی امکانات فریمورک صحبت میکرد. تصویر زیر وبسایت انگولار در سال 2009 را نشان میدهد: پس از مدت کوتایی میسکو شروع به کار برای گوگل کرد، و در 2010 در حال کار کردن روی پروژه ای به نام google feedback بود. میسکو برد گرین (Brad Green) مدیر خود را قانع کرد تا پروژه را با استفاده از پروژه جانبی انگولار او باز نویسی کند و مقدار زمان و کدی که تیم توانست ذخیره کند کمک کرد تا گوگل را برای قدرتی که انگولار ارائه میداد متقاعد کند. کمی بعد از موفقیت در بازنویسی Google Feedback، همان تیم کتابخانه را متنباز کردند و سرانجام نسخه 1.0 از انگولار در ماه می سال 2011 منتشر شد. طی چند سال آمار استفاده از انگولار صعود کرد، و امروز گوگل استفادهی نیم میلیون توسعه دهنده از انگولار را به رخ میکشد. انگولار چه میکند؟ انگولار یک فریمورک جاوا اسکریپت است که به توسعه دهندهها در ساختن برنامه کمک میکند. این کتابخانه تعدادی امکانات را ارائه میکند که پیاده سازی نیازمندیهای پیچیدهی برنامههای مدرن را بدیهی و آسان میکند. مانند پیوند داده (data binding)، مسیریابی (routing) و انیمیشنها (animations). همچنین انگولار قراردادهایی را برای چگونگی توسعه برنامه (application) فراهم میکند، که میتواند برای تیمهای بزرگی که نیاز دارند با هم روی یک کد پایه کار کنند بسیار مفید باشد. انگولار تنها کتابخانه جاوا اسکریپت است که راهنمای استایل (style) جامع را با تعدادی دستورالعمل محتاطانه درباره چگونگی نوشتن کد با فریمورک ارائه میدهد. چه زمانی باید انگولار را استفاده کرد؟ از دید تکنیکی شما میتوانید هر چیزی با انگولار بسازید، اما انگولار در پروژه های پیچیده که شامل داده میشوند به بهترین شکل عمل میکند. اگر شما نگاهی به برنامههای متنوع ساخته شده توسط انگولار که در اینجا لیست شده بیاندازید، خواهید دید عموما برنامههایی هستند که دادهها را از فرم (form) ها جمعآوری کرده و با آن کاری میکنند. این به این معنی نیست که شما باید برای استفاده از انگولار در پروژهی خود فرم داشته باشید. توسعه دهندهها تعداد تعجب برانگیزی از بازی با انگولار به خوبی چیزهایی مثل برنامههای واقعیت مجازی ساختهاند! با این حال اکثر آموزشهایی که خواهید یافت دربارهی برنامههایی از نوع فرمدار خواهد بود. برای مثال مستندات انگولار آموزشی دربارهی ساخت برنامهای است که شما با استفاده از فرم، قهرمان هایی را میسازید و آنها را در لیستی مشاهده میکنید. انگولار در برنامههای با پایه فرم خوب عمل میکند، همچنین برای برنامههای بزرگ و پیچیده بسیار مناسب است. همچنین انگولار نه آسانترین فریمورک جاوا اسکریپ است و نه کوچکترین؛ بنابراین اگر در حال ساخت چیز کوچکی هستید کتابخانههای سادهتری مثل جیکوئری خواهید یافت که مناسبتر هستند. مشابهاً انگولار بسیار مناسب برنامههایی است که توسط تیمهای متوسط الی بزرگ ساخته شدهاند. اگر شما خودتان در حال کار بر روی برنامهای هستید، ممکن است قرارداد های انگولار را بیشتر از نیاز خود ببینید. انگولار همچنین برای برنامههایی مناسب است که نیاز دارند در محیطهای توسعه مختلفی اجرا شوند. اگر شما برنامهای دارید که باید به خوبی یک برنامهی ویندوزی یا مک اجرا شود، میتوانید یکی از آموزشهای آنلاین برای اجرای برنامهی انگولار خود با پروژه معروف الکترون را دنبال کنید. اگر شما برنامهای دارید که باید به خوبی برنامه اندروید و ios اجرا شود، میتوانید با استفاده از NativeScript برنامهی خود را در یک محیط بومی واقعی موبایل رندر (Render) کنید. در بعضی موارد حتی میتوانید این کد را بین پلتفرمهای مختلف به اشتراک بگذارید. چه کسی پشتیبان انگولار است؟ تیم هستهی انگولار آرایهای عظیم از افراد و جامعهی (community) انگولار را شامل میشود که در دنیا گسترده شدهاند. که میشود گفت بیشتر توسعههای روز به روز انگولار توسط کارمندان گوگل انجام شده است. صفحه دربارهی انگولار تقریباً 20 کارمند گوگل را در تیم هسته انگولار لیست کرده است و تمام برترین مشارکت کنندهها در پروژه انگولار در گوگل کار میکنند. که میشود گفت گوگل انگولار را کنترل میکند، خود کتابخانه هنوز تا مقدار زیادی تلاش جامعه است. بیشتر از 2000 فرد در یکی از مخزنهای (repositories) متنباز انگولار مشارکت داشتهاند. راهنما و آموزشهای بیشمار نوشته شده توسط جامعه در دسترس هستند، و شرکتهای مختلفی به توسعه دهندهها برای قدرت بیشتر پیشنهاد آموزش و تجهیز شدن به انگولار را میدهند. چه نسخه ای از انگولار را استفاده کنم؟ در زمان نوشتن این مقاله دو نسخه مشهور انگولار موجود هستند. نسخه یک در وبسایت https://angularjs.org در دسترس است و نسخه ی آپدیت شدهی همان کتابخانهای است که میسکو و تیم در سال 2011 منتشر کردند. نسخه ی مشهور دیگر انگولار اکنون به سادگی "Angular"خوانده میشود و در وبسایت https://angular.io در دسترس است. انگولار مدرن کاملا شکل دوباره طراحی شدهی نسخه یک برای مرورگرها، جریانهای کار و پلتفرمهای توسعه جدیدتر است.
-
2 امتیازنسخهی نهایی کیوت کریتور ۴.۷.۰ منتشر شد. بهبودهای مرتبط با سیپلاسپلاس از ویژگیهای این نسخه میتوان به فعال سازی مُدل کلنگ به صورت پیشفرض اشاره کرد. این ویژگی فرایند توسعهی بسیار بزرگی را در این نسخه های اخیر رقم زده است. مدل کد کلنگ میتواند اطلاعات خوبی را مربوط به خطاهای شما را نمایش دهد. ویژگی یکپارچه سازی آزمایش (Test Integration) اگر مکان نمای ماوس را در ویرایشگر سیپلاسپلاس در درون تابع آزمایش قرار دید، به طور مستقیم میتوانید یک آزمایش جدید از آن را با اجرای گزینه Test Under Cursor action را ایجاد کنید. همچنین ویژگی های بیشتری توسط Google Test برای پشتیبانی از فیلترینگ های بیتر اضافه ده است. میزبانی ویندوز در ویندوز بررسی کامپایلر های MSVC بهبود یافته است، مشکلاتی در این زمینه حل شده اند. دیگر بهبودها گزینهی کیت (Kit) یکی از مهمترین تنظیمات در کیوت کریتور میباشد. بنابراین در این نسخه جایگاه آن در بالاترین بخش از تنظیمات قرار گرفته شده است که در پست قبلی نیز به آن اشاره شده است. اگر شما صفحههای نمایش با کیفیت بالا HiDPI در ویندوز یا لینوکس دارید، حال شما میتوانید به راحتی نحوهی مقیاس پذیری آن را انتخاب کنید. بخش نمایش سیستم فایلها تغییراتی پیدا کردهاند که اجازه میدهد فایلها و پوشهها را با یکپارچگی بهتری ببینید. همچنین شما میتوانید پوشههای جدیدی را به صورت مستقیم در بخش فایل سیستم ایجاد کنید. دیگر بهبودها و جزئیات در زیر لیست شده اند: Qt Creator version 4.7 contains bug fixes and new features. The most important changes are listed in this document. For a complete list of changes, see the Git log for the Qt Creator sources that you can check out from the public Git repository. For example: git clone git://code.qt.io/qt-creator/qt-creator.git git log --cherry-pick --pretty=oneline origin/4.6..v4.7.0 General * Added option for enabling and disabling HiDPI scaling on Windows and Linux (QTCREATORBUG-20232) * Added `Properties` item to context menu on files (QTCREATORBUG-19588) * Added `New Search` button to search results pane (QTCREATORBUG-17870) * Added option to show only icons in mode selector (QTCREATORBUG-18845) * File System View * Added `New Folder` (QTCREATORBUG-17358) * Added `Collapse All` (QTCREATORBUG-19212) * Added option to show folders on top (QTCREATORBUG-7818) * Made synchronization of root directory with current document optional (QTCREATORBUG-19322) * Fixed that external tools did not expand variables for environment changes Editing * Made replacement with regular expression search more perl-like (`$<number>` and `$&` are supported, whereas `&` is no longer used for captures) (QTCREATORBUG-9602, QTCREATORBUG-15175) * Added `Context Help` to editor context menu (QTCREATORBUG-55) * Added previous and next buttons to bookmarks view, and polished their behavior (QTCREATORBUG-9859, QTCREATORBUG-20061) * Added support for `WordDetect` in Kate highlighting files * Fixed that extra editor windows were not restored when opening session (QTCREATORBUG-13840) * Fixed that editor could stay busy repainting annotations (QTCREATORBUG-20422) * FakeVim * Added `:<range>sor[t][!]` Help * Improved performance impact on start up All Projects * Moved kit settings to separate options category * Made it easier to abort builds by changing build button to stop button while building (QTCREATORBUG-20155) * Added project type specific warnings and errors for kits, and made them visible in `Projects` mode * Added shortcut for showing current document in project tree (QTCREATORBUG-19625) * Added global option for `Add linker library search paths to run environment` (QTCREATORBUG-20240) * Added `%{CurrentBuild:Env}` Qt Creator variable QMake Projects * Added support for `-isystem` in `QMAKE_CXXFLAGS` * Added deployment rules for devices to widget and console application wizards (QTCREATORBUG-20358) * Fixed that arguments for QMake step did not expand variables * Fixed `lupdate` and `lrelease` external tools for Qt 5.9 and later (QTCREATORBUG-19892) C++ Support * Improved resize behavior of editor tool bar (QTCREATORBUG-15218, QTCREATORBUG-19386) * Fixed auto-insertion of closing brace and semicolon after classes (QTCREATORBUG-19726) * Fixed location information of macros (QTCREATORBUG-19905) * Clang Code Model * Enabled by default * Switched to Clang 6.0 * Implemented outline pane, outline dropdown and `C++ Symbols in Current Document` locator filter * Implemented `Follow Symbol` for single translation unit * Added type highlighting for Objective-C/C++ * Added errors and warnings of current editor to Issues pane (category `Clang Code Model`) * Added highlighting style for overloaded operators (QTCREATORBUG-19659) * Added option to use `.clang-tidy` configuration file or checks string * Added default configurations for Clang-Tidy and Clazy checks * Added link to the documentation in tooltip for Clang-Tidy and Clazy diagnostics * Improved reparse performance and memory usage * Improved selecting and deselecting specific Clang-Tidy checks * Fixed slow completion in case Clang-Tidy or Clazy checks were enabled * Fixed crashes when closing documents fast * Built-in Code Model * Added support for nested namespaces (QTCREATORBUG-16774) QML Support * Updated parser to Qt 5.10, adding support for user-defined enums * Fixed that linter warning `M127` was shown as error (QTCREATORBUG-19534) * Fixed that reformatting incorrectly removed quotes (QTCREATORBUG-17455) * Fixed that `.pragma` and `.import` were removed when reformatting (QTCREATORBUG-13038) * Fixed that import completion did not offer `QtWebEngine` (QTCREATORBUG-20723) Python Support * Added stack traces in application output to Issues pane (category `Python`) Debugging * Added `Leave Debug Mode` button to toolbar * Fixed updating of memory view * Fixed issue with restoring debugger views (QTCREATORBUG-20721) * QML * Added support for nested properties (QTBUG-68474) * Fixed issue with different endianness (QTBUG-68721) * Fixed Qt namespace detection with GDB 8 (QTCREATORBUG-19620) Qt Quick Designer * Fixed crash when adding quotes to text (QTCREATORBUG-20684) * Fixed that meta data could move in source code even when no changes occurred (QTCREATORBUG-20686) Clang Static Analyzer * Renamed plugin to `ClangTools` * Replaced Clang static analyzer by tool that runs Clang-Tidy and Clazy over whole project or a subset of the project's files QML Profiler * Improved performance of timeline * Added zooming into flame graph items Version Control Systems * Git * Added `-git-show <ref>` command line parameter * Gerrit * Added warning when pushing to wrong branch (QTCREATORBUG-20062) * Fixed updating after settings change (QTCREATORBUG-20536) Image Viewer * Added option to export SVGs in multiple resolutions simultaneously Test Integration * Added `Run Test Under Cursor` to C++ editor * Added editor marks for failed test locations (QTCREATORBUG-20328) * Google Test * Added support for filters * Fixed issue with jumping to file and line of failing test (QTCREATORBUG-18725) * Qt Quick * Fixed parsing issue with non-ASCII characters (QTCREATORBUG-20105) * Fixed detection of test name (QTCREATORBUG-20642) * Fixed detection when `quick_test_main()` is used directly (QTCREATORBUG-20746) Welcome * Rather than open project do nothing when right-clicking recent projects * Open session mini menu when right-clicking sessions Platform Specific Windows * Improved parsing of MSVC error messages (QTCREATORBUG-20297) * Fixed that querying MSVC tool chains at startup could block Qt Creator * Fixed issue with writing to network drives (QTCREATORBUG-20560) * Fixed issue with Clang and Qt 5.8 and later (QTCREATORBUG-20021) * Fixed handling of Windows debug stream which could lead to freezes (QTCREATORBUG-20640) Android * Improved behavior when emulator cannot be started (QTCREATORBUG-20160) * Fixed QML debugger connection issue from macOS client (QTCREATORBUG-20730)
این صفحه از پرچمداران بر اساس منطقه زمانی تهران/GMT+03:30 می باشد