پرچمداران
-
در همه بخش ها
- همه بخش ها
- فایل
- دیدگاه فایل
- نقد و بررسی فایل
- مقالات
- مقاله دیدگاه
- مقاله نقد و بررسی
- صفحات استاتیک
- صفحه دیدگاه
- صفحه نقد و بررسی
- کتابخانهها
- کتابخانه دیدگاه
- کتابخانه نقد و بررسی
- رویداد
- دیدگاه های رویداد
- بازبینی رویدادها
- تصاویر
- دیدگاه های تصویر
- نقد های تصویر
- آلبوم ها
- نظر های آلبوم
- نقد های آلبوم
- پست ها
- نوشتههای وبلاگ
- دیدگاه های وبلاگ
- بروزرسانی وضعیت
- پاسخ های دیدگاه ها
-
همه زمان ها
-
همه زمان ها
4 خرداد 1397 - 6 مهر 1402
-
سال
6 مهر 1401 - 6 مهر 1402
-
ماه
6 شهریور 1402 - 6 مهر 1402
-
هفته
30 شهریور 1402 - 6 مهر 1402
-
امروز
6 مهر 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 خواهد بود. شرح کامل فرایند ساخت فایل اجرایی اکثر پروژهها دارای مجموعهای از فایلهای هدر سی++ هستند، که امکان ماژولار شدن در آن را فراهم میکند و مجموعهای از آن میتواند به عنوان بخشهای کوچکی از برنامه محسوب شوند. برای ساخت چنین پروژههایی هر فایل سیپلاسپلاس باید کامپایل شود و سپس فایلهای ساخته شده در قالب شیء (آبجکت) باید همراه توابع و کتابخانههای دیگر لینک (پیوند) شوند. البته هر گام از مراحل کامپایل شامل یک مرحله پیشپردازنده است که دستورالعمل # عمل تغییرات و اصلاحیهها را در فایل متن اعمال میکند. شکل زیر فرایند ساخت چند فایل به صورت همزمان را نشان میدهد: در ادامهٔ این مقاله، مطلبی مرتبط با تنظیمات بیشتر از کامپایلر آمده است که میتوانید آن را مورد مطالعه قرار دهید.
-
16 امتیاز
نگارش ۱.۳.۸
دنیای خود را چگونه با کیوت بسازیم!؟ با توجه به توسعهٔ روزافزون فناوری، دنیای نرمافزاری همگام با آن با سرعت بسیار زیادی در حال پیشرفت و توسعه است. ما برای رسیدن به این مسیر باید به فکر تولید و توسعهٔ محصول با کیفیت همراه با اقدامات کلیدی باشیم تا این محصول هماهنگ با استانداردهای جهانی باشد. برای این امر نیاز است تا این استانداردها را بررسی و در درون پروژههای خود مورد استفاده قرار دهیم. کیوت به عنوان یک چهارچوب قدرتمند یکی از بهترین و پیشتازترین ابزارهای موجود در دنیای برنامهنویسی است که با تمرکز بر روی مباحث تولید محصولی اساساً بر پایهٔ تجربهکاربری و رابطکاربریِ پیشرفته همراه با پشتیبانی از قدرتمندترین زبان برنامهنویسی، نتیجهای مطلوب را در مسیر توسعهٔ محصول نرمافزاری شما فراهم میکند. توجه داشته باشید برنامهنویسی صرفاً نوشتن کد منطقی و برقراری ارتباط با دادهها و حل مسائل مربوط به آن نیست! علاوه بر حل مشکل، برقراری ارتباط با احساسات کاربر و ایجاد یک تجربه و تعامل خوب بسیار مهم است. باید توجه داشت که زمان، هزینه، سرعت و کیفیت همه باهم مهم هستند و برای به حداکثر رساندن درجه کیفیت هر یک از این مولفهها باید از بهترین روشهای ممکن استفاده کرد که شامل مواردی همچون چند-سکویی، ابری، تجربهکاربری، رابطکاربری، رابطهای برنامهنویسی، کتابخانهها و غیره... میباشند و برای رسیدن به آنها کافی است یک زبان مهم و پایه همراه با چند زبان فرعی و فناوریهای مرتبط با یکدیگر را به عنوان ابزار در اختیار داشته باشیم. آخرین اعتبار تخفیفات ویژه به مناسبتهای اخیر به پایان رسیده است. نکتهٔ بسیار مهم: این کتاب به صورت رسمی در کتابخانهٔ ملی ثبت شده است، بنابراین هرگونه چاپ، تکثیر و به اشتراکگذاری این کتاب پیگیرد قانونی دارد. توجه: دریافت نسخههای بهروزرسانی شده تنها از این صفحه برای کسانی که حداقل یک بار آن را تهیه کردهاند امکانپذیر است. نوع این کتاب الکترونیکی است، بعد از پرداخت میتوانید بر روی دکمهٔ دریافت فایل در همین صفحه کلیک کرده و آن را دریافت نمایید. در صورتی که درگاه پرداختی با مشکل مواجه شده باشد، میتوانید به شماره کارت ۶۱۰۴۳۳۷۸۸۴۵۳۳۳۴۸ (بانک ملت) واریز و آن را به آدرس kambiz.ceo@gmail.com و یا شناسهٔ تلگرامی @Kambiz_Asadzadeh اطلاع دهید تا تأیید شود. در صورتی که از شما اطلاعات آدرس مکانی پرسیده شد، میتوانید آنها را وارد نکنید. * تمامی حقوق مادی و معنوی این کتاب متعلق به مولف و ناشر مولف (کامبیز اسدزاده) میباشد و هرگونه کپی برداری از آن پیگرد قانونی خواهد داشت. توجه : در داشتن هر گونه انتقاد و پیشنهاد در رابطه با این کتاب با آدرس شخصی نویسنده (kambiz.ceo@gmail.com) مکاتبه نمایید. نکته : این کتاب در روزهای خاص ممکن است شامل تخفیف قرار بگیرد. نکته دوم : کسانی که این کتاب را یک بار خریداری میکنند نسخهٔ بهروزرسانی شده آن را به صورت رایگان میتوانند دریافت کنند. برخی از درخواستها در کتاب مقدماتی به صورت زیر بودند: آموزش پیشرفته در رابطه با QML و آشنایی با آن آموزش برقراری ارتباط بین ++C و QML به صورت بکاند و فرانتاند آموزش کار با کنترلها و نحوهٔ سفارشی سازی پروژه آموزش برقراری ارتباط با پایگاه داده و فناوری های مرتبط با آن آموزش نحوهٔ پیکربندی کیتها، کامپایلر و ... آموزش نحوه توسعه برنامه بر روی بسترهای مختلف از جمله اندروید، آیاواس و ... و درخواستهای دیگر... بنابراین بر اساس این درخواستها و محتوایی که نیاز می باشد بعد از جلد مقدماتی با آنها آشنا باشید را در این نسخه فراهم کرده ایم. نکته از نظر من در رابطه با محتوا: کتابخانه کیوت شامل مباحث بسیار زیادی است که میتوان از هزاران صفحه محتوای آموزشی تولید کرد. اما در این محتوای آموزشی من تنها به مواردی اشاره کردهام که لازمهٔ کار هستند و در پروژهها میبایست اطلاعات لازم در رابطه با آنها داشته باشید. سرفصل ها و محتوا چه چیزهایی هستند؟ محتوای کتاب طبق آخرین استاندارد کتابخانه بر پایه نسخه ۵.۸ به بالا میباشد. محتوای آن به نسخه ۵.۹ و حتی ۵.۱۳ بهروزرسانی شده است. همچنین ویژگی های و موارد مهمی که در نسخه ۵.۹ و ۵.۱۰ موجود هستند در این کتاب به آنها اشاره شده است. سر فصلهای نهایی و تایید شده کتاب: فصل اول مقدمه بر زبان ++C برخی از قابلیتها ساختار برنامه در ++C کتابخانهها فرق بین C و ++C ویژگیهای معرفی شده در ++C ویرایشهای ۱۱ ٬ ۱۴ و ۱۷ کامپایلرهای ++C و وضعیت آنها ساختار اسناد ++C در پروژه کاربرد این زبان در کجاست؟ استانداردهای زبان مقدمه کیوت (Qt) معرفی کیوت (Qt) ۵.۹ آشنایی با محیط توسعه، نصب و راه اندازی همراه با پیکربندی کیت (Kit) در آن نصب و راه اندازی محیط Qt پیکربندی کیتها در macOS پیکربندی کیتها در Linux پیکربندی کیتها در Windows معرفی محیط توسعه کیوت کرِیتور (Qt Creator) نسخه 4 پیکربندی و تنظیمات مربوط به ساخت برای پلتفرمهای مختلف معرفی مجوز های Qt و نحوه استفاده از مناسبترین مجوز لوگوهای نشانگر ساخته شده با Qt پشتیبانی از انواع پلتفرمها پشتیبانی از انواع معماری ها شرایط و قوانین لازم جهت انتشار اپلیکیشن در فروشگاه iTunes یا همان (Apple Store) شرایط و قوانین لازم جهت انتشار اپلیکیشن در فروشگاهWindows Store شرایط و قوانین لازم جهت انتشار اپلیکیشن در فروشگاه Google Play شرایط و قوانین اختصاصی برنامه تحت Qt جهت انتشار و پذیرش در فروشگاه های مرتبط فصل دوم معرفی فناوری Qt Quick ویرایش 2 معرفی زبان کیو اِم اِل (QML) ویرایش 2 آشنایی با سبک - سینتَکس (Syntax) زبان QML روش اعلام یا اظهار یک شیء در QML اشیاء فرزند (Child-Object) در QML سبک و روش اعمال اظهار نظر (Comment) در QML صفت های اشیاء در QML پشتیبانی از جاوا اسکریپت (JavaScript) و ترکیب آن با QML روش استفاده از جاوا اسکریپت در سند QML روش های ترکیب ++C و استفاده از آن در سند QML فصل سوم معرفی انواع پروژه ها تحت فناوری کیوت کوئیک (Qt Quick) معرفی پروژه از نوع Qt Widget Application معرفی پروژه از نوع Qt Console Application معرفی پروژه از نوع Qt Quick Application معرفی پروژه از نوع Qt Quick Controls 2 Application معرفی پروژه از نوع Qt Quick Controls Application معرفی پروژه از نوع Qt Quick Canvas 3D Application معرفی پروژه از نوع Qt Quick Labs Controls Application آغاز ایجاد پروژه تحت C++ و Qt Quick ساده ترین برنامه معرفی کلاس QGuiApplication معرفی کلاس QQmlApplicationEngine معرفی کلاس QCoreApplication معرفی تابع exect در پروژه فصل چهارم انواع کنترل ها، منو ها و دیگر آبجکت ها معرفی انواع QML پایه در فناوری Qt Quick نوع date نوع color نوع font نوع matrix4x4 نوع point نوع quaternion نوع rect نوع size نوع vector2d نوع vector3d نوع vector4d معرفی انواع اشیاء QML در فناوری Qt Quick معرفی Accessible معرفی AnchorAnimation معرفی AnchorChanges معرفی AnchorImage معرفی AnimatedSprite معرفی Animation معرفی AnimationController معرفی Animator معرفی Behavior معرفی BorderImage معرفی Contex2D معرفی Canvas معرفی CanvasGradient معرفی CanvasImageData معرفی CanvasPixelArray معرفی CanvasColorAnimation معرفی Column معرفی DoubleValidator معرفی Drag معرفی DragEvent معرفی DropArea معرفی EnterKey معرفی Flickable معرفی Flipable معرفی Flow معرفی FocusScope معرفی FontLoader معرفی FontMeteric معرفی Gradient معرفی GridMesh معرفی GridView معرفی Image معرفی IntValidator معرفی Item معرفی ItemGraResult معرفی KeyEvent معرفی KeyNavigation معرفی Keys معرفی LayoutMirror معرفی ListView معرفی Loader معرفی MouseArea معرفی MouseEvent معرفی MultiPointTouchArea معرفی NumberAnimation معرفی OpacityAnimator معرفی ParallelAnimation معرفی GraphicInfo معرفی ParentAnimation معرفی ParentChange معرفی Path معرفی PathAnimation معرفی PathView معرفی PauseAnimation معرفی PropertyAction معرفی PropertyChanges معرفی Rectangle معرفی RegExpValidator معرفی Repeater معرفی Rotation معرفی RotationAnimation معرفی RotationAnimator معرفی Row معرفی Scale معرفی ScaleAnimator معرفی SecuentialAnimation معرفی ShaderEffect معرفی ShaderEffectSource معرفی Shortcut معرفی SmoothedAnimation معرفی SpringAnimation فصل پنجم معرفی انواع کنترل های 2 Qt Quick Controls کنترل AbstractButton کنترل ApplicationWindow کنترل BusyIndicator کنترل Button کنترل ButtonGroup کنترل CheckBox کنترل CheckDelegate کنترل ComboBox کنترل Container کنترل Control کنترل Dial کنترل Drawer کنترل Frame کنترل GroupBox کنترل ItemDelegate کنترل Label کنترل Menu کنترل MenuItem کنترل Page کنترل PageIndicator کنترل Pane کنترل Popup کنترل ProgressBar کنترل RadioButton کنترل RadioDelegate کنترل RangeSlider کنترل ScrollBar کنترل ScrollIndigator کنترل Slider کنترل SprinBox کنترل StackView کنترل SwipeDelegate کنترل SwipeView کنترل Switch کنترل SwitchDelegate کنترل TabBar کنترل TabButton کنترل TextArea کنترل TextField کنترل ToolBar کنترل ToolButton کنترل ToolTip کنترل Thumbler فصل ششم معرفی Qt Quick Dialog (دیالوگ های انتخاب رنگ، فایل، فونت و پیغام) معرفی Color Dialog معرفی Font Dialog معرفی File Dialog معرفی Message Dialog معرفی Qt Quick Layouts معرفی Column Layout معرفی Grid Layout معرفی Row Layout معرفی Stack Layout معرفی Qt Quick Control Styles (سبک و استایل نویسی کنترل ها – سفارشی سازی) واکنش گرایی و پاسخ دهی محتوای وب در اپلیکیشن با Qt WebEngine محتوای چند رسانه ای در کیوت QMultimedia محتوای چند رسانه ای در کیوت QMultimedia پخش صوت ظبط صدا در فایل پخش ویدیو کار با دوربین فصل هفتم معرفی و پیکربندی کار با بانک اطلاعاتی (دیتابیس) کار با بانک اطلاعاتی و ارتباط آن بین C++ و QML معرفی و کار با XML معرفی و کار با JSON معرفی و کار با QSetting سفارشی سازی فایل .pro پروژه فصل هشتم مقایسه انواع حالت های کامپایل Debug و Release نحوه افزودن دیگر کتابخانه های C++ در محیط Qt Creator و استفاده همراه با کتابخانه Qt فرق بین کامپایل استاتیک و داینامیک نحوه خروجی گرفتن / گسترش (Deployment) در Qt پیکربندی و انتشار برنامه در پلتفرم ویندوز (Windows) پیکربندی و انتشار برنامه در پلتفرم مک (macOS) پیکربندی و انتشار برنامه در پلتفرم لینوکس (Linux) پیکربندی و انتشار برنامه در پلتفرمهای iPhone و iPad (iOS) پیکربندی و انتشار برنامه در پلتفرم اندروید (Android) معرفی ابزار کیوبس (QBS) به روز رسانی کیوت بدون دریافت فایل نصبی آفلاین اهداف و چشمانداز فنی کیوت ۶ پیشنهادات و ملاحظات در عملکرد و کارآیی (جدید)﷼۶۵۰٬۰۰۰
-
13 امتیازسلام و درود خدمت دوستان عزیز، همانطور که میدانید مهمترین و شاید بزرگترین سوال در حوزهٔ برنامهنویسی این است که من باید کدام زبان برنامهنویسی را انتخاب کنم؟! واقعیت امر این است که این سوال همیشه از سمت علاقهمندان مطرح شده است اما هیچگاه یک پاسخ اساسی در مورد آن ارائه نشده است. البته اساتید و برنامهنویسان حرفهای به خوبی میدانند که زبانهای برنامهنویسی به عنوان ابزارهای کمک کار ما کاربرد دارند و به هیچ عنوان نمیتوان یک زبان را به عنوان اولین و آخرین انتخاب در نظر گرفت، اما شناخت در مورد آنها کمک بسیاری در انتخاب ابزارهای مناسب خواهد کرد. در این پُست من قصد دارم در رابطه با انتخاب یک زبان برنامهنویسی بر اساس نیاز و علایق صحبت کنم تا شما عزیزان بتوانید به یک نتیجهٔ مطلوب برسید. بنابراین، قبل از هر چیز این بسیار مهم است که بدانیم یک زبان برنامهنویسی چیست! و چرا باید از آن استفاده کنیم؟! اجازه دهید نگاهی به دلیل استفاده از زبان برنامهنویسی داشته باشیم، چرا از زبان برنامهنویسی استفاده میکنیم؟ به برقراری ارتباط با یکدیگر فکر کنید، انسان برای برقراری ارتباط با همنوعان نیاز به ابزاری به نام زبان دارد که عناصر اساسی آن حروف است. برای مثال حروف خ-ا-ن-ه با ترکیب شدن به خانه تبدیل شده و شما میتوانید آن را درک کنید و این کدی است که شما توسط آن با جهان بیرون خود ارتباط برقرار میکنید. ممکن است کدهای شما توسط یک زبان دیگر مانند زبان انگلیسی ساخته شود، برای مثال h-o-m-e حرفی است که که نتیجهٔ آن Home خواهد بود. در کشور ما معمولاً زبان مادری هریک از ما فارسی، ترکی (آذربایجانی)، عربی، کردی، لُری و دیگر موارد هستند که به صورت بومی آن را فرا میگیریم و با تسلط بسیاری از آن استفاده کرده و منظور همنوعان خود را درک میکنیم. در بحث کامپیوتر، استفاده از زبان انسانی تا حدی کاربرد دارد که فقط خود انسان آن را درک خواهد کرد نه ماشین! چرا که زبان بومی و اصلی کامپیوتر (ماشین) ۰ و ۱ است نه کاراکتر و حرف! ماشینها برای برقراری ارتباط و درک منظور انسان از واحد ۰ و ۱ استفاده میکنند که مجموعهای از آنها به عنوان دستورالعملهای مشخصی برای کامپیوتر قابل درک است. مغز کامپیوتر یعنی واحد پردازشگر مرکزی (CPU) به عنوان پردازندهٔ مرکزی تمامی دادههای شما را در قالب ۰ و ۱ شناسایی میکند و آنها را درک خواهد کرد. بنابراین زبان بومی ماشین بر خلاف انتظار برای انسان بسیار دشوار است و اگر به فکر این باشید که بخواهید از طریق آن با کامپیوتر ارتباط برقرار کنید شما یک دیوانهٔ تمام عیار بشمار خواهید آمد! اجازه دهید منظورم را سادهتر کنم، کامپیوتر منظور شما را از home درک نخواهد کرد! اما اگر به آن بگویید 01101000 01101111 01101101 01100101 مسلماً خواهد فهمید که منظور شما از آن یعنی home است! حالا اگر منظور شما سلام دنیا باشد باید به کامپیوتر بگویید 01101000 01100101 01101100 01101100 01101111 00100000 01110111 01101111 01110010 01101100 01100100 و همینطور برای برقراری ارتباط بیشتر باید هزاران، میلیونها و میلیاردها ۰ و ۱ را با اصول زبان ماشین در کنار هم قرار دهید تا شاید بتوانید یک دستورالعمل ساده برای انجام یک کار را به آن انتقال دهید! احمقانست نه؟! وقت و زمان برای ما انسانها بسیار با ارزش است و مسلماً به هدر دادن آن به این روش هرچند دانش بسیار بالایی از مهندسی کامپیوتر میطلبد اما حتی اگر شما یک دانشمند هم باشید بکار گیری این روش دیوانگی محض است! ما که کامپیوتر نیستیم! ما انسانیم! ساختار کامپیوتر بسیار شبیه به ساختار انسان است، همانطور که خالق انسان، خداوند یکتا او را آفرید به آن نیز هوش و قدرتِ تفکر داد تا بتواند بر اساس آن رشد کرده و در مسیر پیشرفت قدم بردارد، انسان نیز از دانستههای خود برای ساختههایش استفاده میکند. کامپیوترها به عنوان ابزارهای ساخت دست بشر دارای ساختار بسیار ساده ولی در عین حال بسیار پیچیده هستند که انسان برای برنامهریزی آن نیاز به ابزارهایی دارد (ابزارهایی برای ایجاد دستورات قابل درک برای ماشین). ابزارهای برنامهریزی برای کامپیوتر همانطور که اشاره شد، کامپیوترها هیچ درکی از کدهایی که انسان مینویسد ندارند! بنابراین ما نیاز به ابزاری داریم تا منظور خود را برای درک کامپیوتر ارائه دهیم. حال آن ابزار میتواند یک مفسر (Interpreter) باشد یا یک کامپایلر (Compiler) ! هر دوی این ابزارها وظیفهٔ دریافت زبان سطح بالا (نزدیک به زبان انسان) و تبدیل (ترجمهٔ آن) به زبان ماشین است. با تفاوت اینکه مفسرها کدهای نوشته شده را خط به خط تفسیر کرده و آنها را برای پردازنده اجرا میکند، در حالی که کامپایلر تمامی کدها را به شیء و هر شیء را به کد باینری یکجا ترجمه کرده و هرجا که نیاز بود آنها توسط پردازنده اجرا میشوند. به بیان سادهتر فرض کنید قرار است به زبان روسی صحبت کنید، شما دو روش خواهید داشت: صحبت کردن به زبان روسی به صورت مستقیم استخدام یک مترجم، صحبت با مترجم و ترج گفتههای شما توسط مترجم به طرف مقابل برخی از مزایا و معایب کامپایلر و مفسر نسبت به یکدیگر نکته ۱: مفسرها کدهای نوشته شده را به صورت خط به خط تفسیر و ترجمه میکند اما کامپایلرها آنها را یکجا ترجمه میکند که دارای یک خروجی مانند یک فایل اجرایی است. نکته ۲: برنامهٔ تولید شده تحت کامپایلر توسط سخت افزار (ماشین واقعی) اجرا میشود در صورتی که برنامهٔ تولید شده با مفسر توسط نرمافزار (ماشین مجازی) اجرا میشود. نکته ۳: کامپایلرها عملیات بهینهسازی یا همان (Optimization) را در آخرین مرحله از کامپایل (ترجمه) انجام میدهند، در صورتی که مفسرها عملیات بهینه سازی را در زمان تبدیل انجام میدهند. نکته ۴: سرعت اجرای کدهای کامپایل شده بسیار بیشتر از کدهای تفسیر شده است. برای مثال اگر حلقهای را در نظر داشته باشید که قرار است ۱۰ بار اجرا شود، آن حلقه در حالت مفسر ۱۰ بار تفسیر شده و ۱۰ بار توسط پردازنده اجرا خواهد شد! در حالی که در حال کامپایل شده حلقه یک بار ترجمه میشود و نتیجهٔ آن یک بار توسط پردازنده در زمان نیاز اجرا میشود! این بسیار مهم است و در پردازشهای بسیار بزرگ سرعت برنامههای کامپایل شده به شدت بالاتر از تفسیر شدهها است. نکته ۵: کدهای تولید شده توسط مفسر سطح بالاتری نسبت به کدهای تولید شده توسط کامپایلر دارند در واقع آنها تقریباً قابل خواندن هستند اما کدهای تولید شده توسط کامپایلر غیر قابل خواندن است. نکته ۶: امنیت برنامههای کامپایل شده و همچنین دسترسی به منابع کد آنها از امنیت بیشتری نسبت به برنامههای تحت مفسر دارند. نکته ۷: برنامههای تفسیر شده وابستگی خاصی به سیستمعامل ندارند و در هر جایی که برنامهٔ تفسیر کننده موجود باشد اجرا خواهند شد، در صورتی که برنامههای کامپایل شده برای هر نوع سیستمعامل متفاوت باید مجدداً کامپایل شود که البته برای اجرای آن نیازی به نصب بودن کامپایلر بر روی سیستمعامل نیست. نکته ۸: کامپایلر کد برنامه را به صورت کامل به کُد ماشین ترجمه میکند، بنابراین زمان اجرای آن بسیار کم تر است و انتخاب بسیار خوبی برای دوستداران سرعت است. نکته ۹: استفاده از زبانهای مفسری برای توسعهدهندگان مبتدی آسانتر از نوع کامپایلری میباشد بنابراین یادگیری و استفاده از این نوع زبانها نسبتاً سریعتر و راحتتر از نوع کامپایلری است. فرایند توسعهٔ نرمافزار در این فرایند کامپایلر برنامه را میسازد سپس همه دستورات زبان را از نظر صحت تجزیه و تحلیل میکند و اگر دستوری غلط باشد، اخطار میدهد. در صورتی که خطایی وجود نداشته باشد همهٔ کدها را به کد ماشین تبدیل میکند که در نهایت فایلهای مختلفی را به برنامه اجرایی اضافه میکند و در نهایت برنامه را اجرا میکند. در حالی که مفسر برنامه را میسازد اما، فرایند افزودن فایل اجرایی به برنامه یا تولید کدهای ماشین وجود ندارد بلکه دستورات کد منبع خط به خط در حین زمان اجرا یا به اصطلاح Run-time اجرا میکند. کدام زبان در چه حوزهای کاربرد دارد؟ با توجه به تعاریف بالا نوبت آن رسیده است تا زبان برنامهنویسی مورد نظر خود را بر اساس نیاز و قابلیتهایی که آن در اختیار توسعهدهنده قرار میدهد انتخاب کرد. حوزههای کاربردی زبانهای برنامهنویسی متناسب با کاربرد و رسالت آنها مشخص میشود، به طور کلی زبانهای برنامهنویسی را بهتر است به دو دستهٔ اصلی و فرعی جدا کنیم. در دستهٔ اصلی زبانهایی که پایه و اساس کتابخانهها، نرمافزارهای عظیم، انجینها و همچنین خود زبانهای برنامهنویسی میباشند را زبان مادر و اصلی و تمامی زبانهایی که به عنوانی جهتِ مکمل سازی و یا محصول نوع سوم برای اهداف تجاری ساخته شدهاند را فرعی میگوییم. زبانهای اصلی و مادر: C و ++C زبانهای اصلی و فرعی: Python, Java, Delphi, C#, Swift, Objective-C, Php, JavaScript زبانهای مکمل رابط کاربری: JavaScript, CSS, Xaml, Xhtml, Html, QML درنظر داشته باشید کتابخانهها و برنامههای اساسی و پایه که بخش اعظمی از آنها توسط زبانهای سی++ و سی نوشته میشوند در صورت نیاز برای زبانهای دیگر نیز قابل استفاده هستند. به عنوان مثال سیستمعاملها، نرمافزارهای عظیم، انجینهای بازیسازی، کتابخانههای پرکاربرد و مهم همهٔ آنها توسط زبانهای اصلی توسعه یافتهاند اما در صورت نیاز میتواند از کتابخانههای نوشته شده توسط زبانهای اصلی در زبانهای فرعی نیز استفاده کرد. شاید اینطور به نظر برسد که اگر با زبانهای اصلی هر کاری میتوان انجام داد، پس چرا زبانهای دیگر را مورد استفاده قرار میدهیم؟! جواب سوال این است که زبانهای اصلی و مهم نیاز به دانش بسیار از لحاظ معماری سیستمعامل، کامپایلر و دیگر شاخههای علوم کامپیوتر هستند و نحوِ کُدنویسی در آنها نسبت به زبانهای دیگر مانند جاوا، پایتون، سیشارپ و غیره دشوارتر است. بنابراین ممکن است انتخاب اول برنامهنویسان مبتدی نباشند اما کاربرد آنها جنریک (عمومی) است. اشاره به کاربرد زبانهای محبوب در حوزههای مختلف: توسعهٔ وبسایت: C++, Java, Php, JavaScript, C#, Ruby, Python توسعهٔ نرمافزارهای موبایل: , C++, Java, C#, Objective-C, Swift, JavaScript, Kotlin توسعهٔ نرمافزارهای دسکتاپ: C/C++, Java, Delphi, VB.Net, C#, JavaScript, Objective-C توسعهٔ نرمافزارهای اِمبِد: C/C++, Python توسعهی بازیهای کامپیوتری: ++C و #C توسعهٔ هوش مصنوعی: C++,Python, R, Prolog, Java, Haskell, AIML توسعهٔ رابطکاربری: JavaScript, QML, XAML نکتهٔ قابل توجهی از کاربرد زبانهای اصلی در این است که خود آنها وابستهٔ زبان برنامهنویسی و محدود بر یک حوزه نیستند و به اصطلاح زبان مادر بشمار میآیند که و در تمامی حوزهها کاربرد دارند. کاربرد در صنایع و حوزههای مختلف بر اساس ویژگیهایی که یک زبان برنامهنویسی ارائه میدهد بسیار مهم است. برای مثال Python, R, Prolog و غیره در حوزهٔ هوش مصنوعی و بیگ دیتا بسیار سادهتر به کمک توسعه دهندگان میآید. در توسعهٔ وبسایت زبانهای برنامهنویسی Node.JS, Php, C#, Asp.Net محبوبیت بیشتری دارند. اما میتوان با توجه به این پست وبسایتهای بسیار سریع و بهینهای را توسعه داد که بی شک نیاز به دانش بسیار بالایی دارد و بهتر است در اهداف خاص از آن استفاده شود. در حوزهٔ موبایل در پلتفرم iOS دو زبان Swift و Objective-C به عنوان زبان اصلی پلتفرمهای iOS, tvOS و watchOS به شمار میآیند. در حوزهٔ اندروید (Android) زبانهای Java و Kotlin به عنوان انتخابهای اول توسعهدهندگان مطرح میشند در صورتی که بسیاری از کتابخانههای اندروید تحت C و ++C توسعه یافته و حتی میتواند با استفاده از ++C اپلیکیشن و بازیهای بسیار سریعتری را تولید کرد. در حوزههای صنایع بازیسازی زبانهایی مانند #C نیز کاربرد دارند، اما ترجیح اول و اصلی در این حوزه بکارگیری ++C است چرا که هیچ زبانی به جز آن نهایت سرعت را ارائه نخواهد داد. آمارها و محبوبیتها سالانه طبق گزارش بسیاری از مراجع نمودارها و آمارهایی در رابطه با ایندکس شدن زبانهای برنامهنویسی ارائه میشود که نمونهای از آنها TIOBE است. متاسفانه باید گفت مقایسهٔ چنین مراجع بر اساس ویژگیهایی که در بالا توضیح دادیم صورت نمیگیرد و صرفاً بر اساس محبوبیت بین کاربران گزارش داده میشوند. برتری زبان نسب به زبان دیگر بر اساس چنین آمارهایی اشتباه بوده و توسط آن نمیتوان یک زبان را به عنوان انتخاب اول در نظر گرفت. همچنین اگر دقت کنید مقایسهٔ زبانهای برنامهنویسی اسکریپتی با کامپایلری و همچنین زبانهایی مانند SQL در بین آنها وجود دارد که از لحاظ منطقی درست نیست چرا که کاربرد زبانها با یکدیگر متفاوت بوده و ملاک آماری این مراجع فقط استقبال کاربران است. تعاریف و هِدایتهای اشتباه به سمت یک زبان برنامهنویسی متاسفانه مشاهده میشود که در بسیاری از گروهها و سایتهای برنامهنویسی چندین زبان برنامهنویسی را به عنوان بهترین انتخاب معرفی میکنند و دلیل انتخاب آنها را مشاهدهٔ رتبههای آن بر اساس ایندکسهای برخی از مراجع و یا طرفداری بعضی از شرکتها و تعصبات بی هدف است! باید در نظر داشته باشید قدرت و ویژگیهای یک زبان ربطی به محبوبیت آن ندارد. اگر احساس میکنید شرکتها تقاضای متخصص زبان برنامهنویسی خاصی را دارد که تکرار میشود به آن معنی نیست که زبانهای برنامهنویسی دیگر در حال منسوخ شدن یا کنار گذاشتن هستند. ارزش زبان ملاک برتری آن است نه محبوبیتش! به عنوان مثال اگر JavaScript رتبهٔ اول از نظر محبوبیت را دارد به آن معنا نیست که Php در حال منسوخ شدن است! هر زبانی کاربرد خودش را نسبت به اهداف و ویژگیهای خود دارد. آیا زبان ماشین منسوخ شده است؟! خیر! این چه سوالیه!!؟ چنین افکار بیهوده را از ذهن خود بیرون بریزید! تمامی زبانهای کامپایلری به جز نوعهای مفسری در نهایت کدهایشان توسط کامپایلر به زبان ماشین یعنی assembly تبدیل میکنند. مثال زیر کد ++C است: int main() { } خروجی آن به زبان ماشین (Assembly) در کامپایلر GCC به صورت زیر خواهد بود: main: push rbp mov rbp, rsp mov eax, 0 pop rbp ret انتخاب چند-سکویی پیشنهاد میشود یا خیر؟ لازم بذکر است که بدانید، ابزارهای چند-سکوی بسیاری وجود دارند که به شما اجازه میدهند بدون داشتن دانش آنچنانی در رابطه با زبانهای برنامهنویسی متعددِ مخصوص سکوهای هدف محصول خود را توسعه دهید. برخی از آنها عبارتند از Xamarin و یا React Native که متاسفانه به دلیل ساختار نامطلوب تبدیل کدهای نوشته شده نتیجهٔ نهایی آنها آنچنان خوب مانند محصولات واقعی زبان بومی نیستند چرا که کدهای آن مستقم به زبان ماشین ترجمه نمیشوند. اما این بسیار مهم است که بدانید ابزارهای بومی چند-سکویی واقعی انتخاب بهتری برای این امر بشمار میآیند که معروفترین آنها Qt است که به صورت بومی بدون اُفت کیفیت محصول نهایی به شما اجازهٔ توسعه محصول در سکوهای مختلف را میدهد که مسلماً دانش بسیار بالایی از سی++ را میطلبد. در نتیجه اگر به دنبال محصول با کیفیت در حوزهٔ چند-سکویی هستید باید دانش بالایی از ++C داشته باشید. نکته: در نظر داشته باشید زبانهای کامپایلری خود به دو دسته نیز تقسیم میشوند که برخی از آنها به صورت مستقیم کدهای نوشته شده را به کد ماشین ترجمه میکنند و برخی از آنها کد نوشته شده را به یک زبان میانی تبدیل و سپس آن را توسط برنامهٔ مجازی برای ماشین برنامهریزی مینمایند. بهتر است توجه داشته آنها مزایا و معایبی نیز خواهند داشت. زبانهای کامپایلری در دو دستهی بومی (Native) و مجازی (Virtual) کامپایل از نوع بومی روشی است که کدهای نوشته شده را به صورت مستقیم به کُد ماشین ترجمه میکند. کامپایل از نوع مجازی روشی است که کدهای نوشته شده را ابتدا به کُدمیانی (کدمشترک یا همان بایت کُد - Byte Code) در جاوا و زبان میانی (CIL) در Net. تبدیل میکند که خودِ آن شبیه به کُد ماشین است. در این فرایند کد مربوطه توسط کامپایلر مخصوص یعنی JIT (کامپایلری از نوع Just-In-Time) در زمان اجرا توسط سیستمعامل، به دستورالعملهای قابل فهم برای پردازنده تفسیر و اجرا میشود (که این فرایند شبیه به فرایند عملکرد اجرایی مفسرها است). زبانهای بومی (زبانهایی که کد آنها به کد ماشین به صورت مستقیم توسط کامپایلر قبل از اجرای آنها توسط سیستمعامل، ترجمه میشوند که به اصطلاح ahead-of-time (جلوتر از زمان) یا همان AOT نام دارد) مانند: C, C++, Rust, Haskell, Clean, Swift, Go, Fortran, D زبانهای مجازی (زبانهایی که کد آنها توسط یک رابط میانی به زبان مشترک ترجمه میشود) : Java و #C مزایا و معایب زبانهای کامپایلری از نوع کلاس بومی (Native) از سرعت بسیار بالایی برخوردار هستند (دلیل آن ترجمهٔ مستقیم کدها به کد ماشین است) در مقابل بزرگترین مزیتی که زبانهای نوع کلاس مجازی (Byte Code) دارند به خاطر وجود یک برنامهٔ واسط جهت شبیهسازی کدهای ترجمه شده به کد قابل فهم برای پردازنده، اجرا شدن آنها در هر پلتفرم بدون کامپایل مجدد امکان پذیر است که البته این ویژگی خود نیازمند نصب بودن JVM بر روی پلتفرم مربوطه میباشد. در نوع بومی برای اجرا در هر پلتفرم لازم است سورس کدها را برای پلتفرم مقصد کامپایل کنید که نیازی به وجود ماشین مجازی مانند JVM یا برنامهٔ خاصی ندارد. سریعترین زبان برنامهنویسی کدام است؟ شاید پاسخ به این سوال به گونهای تعصبی به نظر برسد، اما واقعیت این است که باید حقیقت را پذیرفت! با توجه به دلایلی که به نوع زبانهای کامپایلری آورده شده است مشخص است که سریعترین نوع زبانهای برنامهنویسی باید در دستهٔ شاخهٔ کامپایلری و کلاس Native قرار گرفته باشند چرا که در این مبحث زبانها کامپایلری (مجازی) و مفسری حرفی برای گفتن ندارند. جهت تثبیت آن مستنداتی از بنچمارکها در این بخش آورده شدهاست. حقیقت این است ++C در بدترین حالت ممکن بدون بهینهسازی کدها و فلگهای خاص حداقل ۲ تا ۴ برابر سریعتر از زبانهای کامپایلری دیگر است! تلخترین حقیقت نیز این خواهد بود که ++C حداقل ۱۰۰ تا ۲۰۰ برابر سریعتر از زبانهای مفسری است! با توجه به تجربیات شخصی در صورتی که نوع کامپایلر Clang باشد سرعت کدها به چند برابر از این نیز خواهد رسید! همچنین باید در نظر بگیرید اگر کدهای شما خارج از اصول استاندارد زبان باشد ممکن است نتایج آن به تساوی و حتی پایینترین حالت ممکن برسد. سخن آخر، برای انتخاب زبان برنامهنویسی و به دست آوردن مهارت در آن و در نهایت تبدیل دانش به یک محصول نرمافزاری، بهتر است بر اساس نوع (کامپایلری یا مفسری بودن)، اهمیت سرعت، ویژگیهای آن و کاربردش در حوزههای مختلف تصمیم بگیرید نه بر اساس تعصب و علاقه. دقت کنید که زبانهای برنامهنویسی ابزارهای برنامهنویسی بوده و هرچقدر جعبه ابزار شما کامل باشد توانایی و مهارت شما در توسعهٔ حوزههای مختلف بیشتر خواهد بود. در صورتی که میخواهید در رابطه با انواع روشهای کامپایل و تفاوتهای کامپایل Native، Cross Compile و JIT آشنا شوید، پیشنها میشود مقاله زیر را مطالعه فرمایید.
-
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 امتیازدر این مقاله من قصد دارم در رابطه با تفاوتهای اختصاص دادن حافظه در اِستَک و هیپ توضیحاتی دهم که بسیاری از علاقهمندان راجع به آنها سوال کردهاند. با توجه به اینکه، از اوایل سیستمهای کامپیوتری این تمایز در این وجود داشته است که برنامه های اصلی در حافظه فقط خواندنی مانند ROM ، PROM و یا EEPROM نگه داری میشوند. به عنوان دیگر از زمانی که سیستم ها پیچیدهتر شدند برنامهها از حافظههای دیگری مانند RAM به جای اجرا در حافظه ROM استفاده کردند. این ایده به خاطر این بود که تعدادی از قسمت های حافظه مربوط به برنامه نباید تغییر یابند و در این حالت باید حفظ شوند. در این میان دو بخش .text و .rodata بخشیهایی از برنامه هستند که میتواند به بخش های دیگر برای وظایف خاص تقسیم شوند که در ادامه به آنها اشاره شده است. بخش کد، به عنوان یک بخش متنی (.text) و یا به طور ساده به عنوان متن شناخته میشود. جایی است که بخشی از یک فایل شیء یا بخش مربوطه از فضای آدرس مجازی برنامه که حاوی دستورالعمل های اجرایی است و به طور کلی فقط خواندنی بوده و اندازه ثابتی دارد میباشد. بخش .bss که به عنوانی بخشی ویژه (محل نگه داری اطلاعات تخصیص داده نشده (مقدار دهی نشده)) محلی که متغیرهای سراسری و ثابت با مقدار صفر شروع میشوند. بخش داده (.data) حاوی هر گونه متغیر سراسری و یا استاتیک که دارای یک مقدار از پیش تعریف شده هستند و میتوانند اصلاح شوند. تصویر زیر طرح معمولی از یک حافظه برنامه ساده کامپیوتری را با متن، داده های مختلف، و بخشهای استک و هیپ و bss را نشان میدهد. .section.data < initialized data here> .section .bss < uninitialized data here> .section .text .globl _start _start: <instruction code goes here> برای مثال در کد C به صورت زیر خواهد بود: int val = 3; char string[] = "Hello World"; مقادیر برای این نوع متغیرها در ابتدا در حافظه فقط خواندنی ذخیره میشوند. (معمولا در داخل .text) و در زمان اجرای برنامه که به صورت روتین خواهد بود در بخش .data کپی میشوند. بخش BSS یا همان .BSS در برنامهنویسی کامپیوتر، نام .bss یا bss توسط بسیاری از کامپایلرها و لینکرها برای بخشی از دیتا سِگمنت (Data Segment) استفاده میشود که حاوی متغیر های استاتیک اختصاصی که تنها از بیت هایی با ارزش صفر شروع شده است میباشد. این بخش به عنوان BSS Section و یا BSS Segment شناخته میشود. به طور معمول فقط طول بخش bss نه data در فایل آبجکت ذخیره میشود. برای نمونه، یک متغیر به عنوان استاتیک تعریف شده است static int i; این در بخش BSS خواهد بود. حافظه هیپ (Heap) ناحیهٔ هیپ (Heap) به طور رایج در ابتدای بخشهای .bss و .data قرار گرفته است و به اندازههای آدرس بزرگتر قابل رشد است. ناحیهٔ هیپ توسط توابع malloc, calloc, realloc و free مدیریت میشود که ممکن است توسط سیستمهای brk و sbrk جهت تنظیم اندازه مورد استفاده قرار گیرد. ناحیه هیپ توسط تمامی نخها، کتابخانههای مشترک و ماژولهای بارگذاری شده در یک فرآیند به اشتراک گذاشته میشود. به طور کلی حافطه Heap بخشی از حافظه کامپیوتر شما است که به صورت خودکار برای شما مدیریت نمیشود، و به صورت محکم و مطمئن توسط پردازنده مرکزی مدیریت نمیشود. آن بیشتر به عنوان یک ناحیه شناور بسیار بزرگی از حافظه است. برای اختصاص دادن حافظه در ناحیه هیپ شما باید از توابع malloc(), calloc() که توابعی از C هستند استفاده کنید. یکبار که شما حافظه ای را در ناحیه هیپ اختصاص دهید، جهت آزاد سازی آن باید خود مسئول باشید و با استفاده از تابع free() این کار را به صورت دستی جهت آزاد سازی حافظه اختصاص یافته شده انجام دهید. اگر شما در این کار موفق نباشید، برنامه شما در وضعیت نَشت حافظه (Memory Leak) قرار خواهد گرفت. این بدین معنی است که حافظه اختصاص یافته شده در هیپ هنوز خارح از دسترس قرار گرفته و مورد استفاده قرار نخواهد گرفت. این وضعیت همانند گرفتگی رَگ در بدن انسان است و حافظه نشت شده جهت عملیات در دسترس نخواهد بود. خوشبختانه ابزارهایی برای کمک کردن به شما در این زمینه موجود هستند که یکی از آنها Valgrind نام دارد و شما میتوانید در زمان اشکال زدائی از آن جهت تشخیص نواحی نشت دهنده حافظه استفاده کنید. بر خلاف حافظه اِستک (Stack) حافظه هیپ محدودیتی در اندازه متغیرها ندارد (جدا از محدودیت آشکار فیزیکی در کامپیوتر شما). حافظه هیپ در خواندن کمی کُند تر از نوشتن نسبت به حافظه اِستک است، زیرا جهت دسترسی به آنها در حافظه هیپ باید از اشاره گر استفاده شود. بر خلاف حافظه اِستک، متغیرهایی که در حافظه هیپ ساخته میشوند توسط هر تابعی در هر بخشی از برنامه شما در دسترس بوده و اساسا متغیرهای تعریف شده در هیپ در دامنه سراسری قرار دارند. حافظه اِستک (Stack) ناحیهٔ اِستک (Stack) شامل برنامه اِستک، با ساختار LIFO کوتاه شده عبارت Last In First Out (آخرین ورودی از همه زودتر خارج میشود) به طور رایج در بالاترین بخش از حافظه قرار میگیرد. یک (اشاره گر پشته) در بالاترین قسمت اِستک قرار میگیرد. زمانی که تابعی فراخوانی میشود این تابع به همراه تمامی متغیرهای محلی خودش در داخل حافظه اِستک قرار میگیرد و با فراخوانی یک تابع جدید تابع جاری بر روی تابع قبلی قرار میگیرد و کار به همین صورت درباره دیگر توابع ادامه پیدا میکند. مزیت استفاده از حافظه اِستک در ذخیره متغیرها است، چرا که حافظه به صورت خودکار برای شما مدیریت میشود. شما نیازی برای اختصاص دادن حافظه به صورت دستی ندارید، یا نیازی به آزاد سازی حافظه ندارید. به طور کلی دلیل آن نیز این است که حافظه اِستک به اندازه کافی توسط پردازنده مرکزی بهینه و سازماندهی میشود. بنابراین خواندن و نوشتن در حافظه اِستک بسیار سریع است. کلید درک حافظه اِستک در این است که زمانی که تابع خارج میشود، تمامی متغیرهای موجود در آن همراه با آن خارج و به پایان زندگی خود میرسند. بنابراین متغیرهای موجود در حافظه اِستک به طور طبیعی به صورت محلی هستند. این مرتبط با مفهوم دامنه متغیرها است که قبلا از آن یاد شده است، یا همان متغیرهای محلی در مقابل متغیرهای سراسری. یک اشکال رایج در برنامه نویسی C تلاش برای دسترسی به یک متغیر که در حافظه اِستک برای یک تابع درونی ساخته شده است میباشد. یعنی از یک مکان در برنامه شما به خارج از تابع (یعنی زمانی که آن تابع خارج شده باشد) رجوع میکند. یکی دیگر از ویژگیهای حافظه اِستک که بهتر است به یاد داشته باشید این است که، محدودیت اندازه (نسبت به نوع سیستم عامل متفاوت) است. این مورد در حافظه هیپ صدق نمیکند. خلاصه ای از حافظه اِستک (Stack) حافظه اِستک متناسب با ورود و خروج توابع و متغیرهای درونی آنها افزایش و کاهش مییابد نیازی برای مدیریت دستی حافظه برای شما وجود ندارد، حافظه به طور خودکار برای متغیرها اختصاص و در زمان نیاز به صورت خودکر آزاد میشود در اِستک اندازه محدود است متغیرهای اِستک تنها در زمان اجرای تابع ساخته میشوند مزایا و معایب حافظه اِستک و هیپ حافظه اِستک (Stack) دسترسی بسیار سریع به متغیرها نیازی برای باز پس گیری حافظه اختصاص یافته شده ندارید فضا در زمان مورد نیاز به اندازه کافی توسط پردازنده مرکزی مدیریت میشود، حافظه ای نشت نخواهد کرد متغیرها فقط محلی هستند محدودیت در حافظه اِستک بسته به نوع سیستم عامل متفاوت است متغیرها نمیتوانند تغییر اندازه دهند حافظه هیپ (Heap) متغیرها به صورت سراسری قابل دسترس هستند محدودیتی در اندازه حافظه وجود ندارد تضمینی برای حافظه مصرفی وجود ندارد، ممکن است حافظه در زمانهای خاص از برنامه نشت کرده و حافظه اختصاص یافته شده برای استفاده در عملیات دیگر آزاد نخواهد شد شما باید حافظه را مدیریت کنید، شما باید مسئولیت آزاد سازی حافظه های اختصاص یافته شده به متغیرها را بر عهده بگیرید اندازه متغیرها میتواند توسط تابع realloc() تغییر یابد در اینجا یک برنامه کوتاه وجود دارد که در آن متغیرها در یک حافظه اِستک ایجاد شده اند. #include <stdio.h> double multiplyByTwo (double input) { double twice = input * 2.0; return twice; } int main (int argc, char *argv[]) { int age = 30; double salary = 12345.67; double myList[3] = {1.2, 2.3, 3.4}; printf("double your salary is %.3f\n", multiplyByTwo(salary)); return 0; } ما متغیرهایی را اعلان کردهایم که یک int، یک double و یک آرایه که سه نوع double دارد هستند. این متغیرها داخل اِستک وارد و به زودی توسط تابع main در زمان اجرا حافظه مورد نیاز خود را دریافت خواهند کرد. زمانی که تابع main خارج میشود (برنامه متوقف میشود) این متغیرها همگی از داخل حافظه اِستک خارج خواهند شد. به طور مشابه، در تابع multiplByTwo() متغیر twice که از نوع double است، داخل اِستک وارد شده و در زمان اجرای تابع multiplyByTwo() حافظه به آن اختصاص مییابد. زمانی که تابع فوق خارج شود یعنی به نقطه پایان اجرایی خود برسد، حافظه اختصاص یافته شده به متغیرهای داخلی آن نیز آزاد خواهند شد. به طور خلاصه توجه داشته باشید که تمامی متغیرهای محلی در این نوع تعریف تنها در طول زمان اجرایی زمانی تابع زنده هستند. به عنوان یک یادداشت جانبی، روشی برای نگه داری متغیرها در حافظه اِستک وجود دارد، حتی در زمانی که تابع خارج میشود. آن روش توسط کلمه کلیدی static ممکن خواهد شد که در زمان اعلان متغیر استفاده میشود. متغیری که توسط کلمه کلیدی static تعریف میشود، بنابراین چیزی مانند متغیر از نوع سراسری خواهد بود، اما تنها در داخل تابعی که داخل آن ایجاد شده است قابل مشاهده خواهد بود. این یک ساختار عجیب و غریب است، که احتمالا به جز شرایط بسیار خاص نیازی به آن نباشد. نسخهٔ دیگری از برنامه فوق در قالب حافظه هیپ به صورت زیر است: #include <stdio.h> #include <stdlib.h> double *multiplyByTwo (double *input) { double *twice = malloc(sizeof(double)); *twice = *input * 2.0; return twice; } int main (int argc, char *argv[]) { int *age = malloc(sizeof(int)); *age = 30; double *salary = malloc(sizeof(double)); *salary = 12345.67; double *myList = malloc(3 * sizeof(double)); myList[0] = 1.2; myList[1] = 2.3; myList[2] = 3.4; double *twiceSalary = multiplyByTwo(salary); printf("double your salary is %.3f\n", *twiceSalary); free(age); free(salary); free(myList); free(twiceSalary); return 0; } همانطور که میبینید، استفاده از malloc() برای تخصیص حافظه در حافظه Heap و استفاده از free() جهت آزاد سازی حافظه تخصیص یافته میباشد. این مواجه شدن چیز بسیار بزرگی محسوب نمیشود اما کمی مبهم است. چیز دیگری که باید به آن توجه داشته باشید علامت ستاره (*) است که در همه جای کدها دیده میشود. اینها چه چیزهایی هستند؟ پاسخ این سوال این است : اینها اشاره گر هستند! توابع malloc() و calloc() و free() با اشارهگرهایی مواجه میشوند که مقادیرشان واقعی نیست. اشاره گرها نوع داده ای خاصی در C هستند که آدرس حافظه مربوطه را بر میگردانند. در خط ۵ متغیر twice یک متغیر از نوع double نیست، اما اشاره به یک double دارد. آن آدرس حافظه ای است که نوع double در آن بلوک از حافظه ذخیره شده است. در ++C توسط کلمه کلیدی new که خود آن نیز یک اپراتور محسوب میشود میتوان حافظه ای را در Heap اختصاص داد. به عنوان مثال: int* myInt = new int(256); آدرسهای موجود در حافظه توسط اپراتور new به اشارهگر مربوطه پاس داده میشود. به مثال زیر توجه کنید، متغیر تعریف شده در حافظه اِستک قرار گرفته است: int variable = 256; سوالی که ممکن است افراد کنجکاو از خود بپرسند این است که چه زمانی از Stack و چه زمانی از Heap باید استفاده کنیم؟! خب پاسخ این سوال اینگونه خواهد بود، زمانی که شما نیاز به یک بلوک بسیار بزرگی از حافظه دارید، که در آن یک ساختار بزرگ یا یک ارایه بزرگی را ذخیره کنید و نیاز داشته باشید که متغیرهای شما به مدت طولانی در سرتاسر برنامه شما در دسترس باشند در این صورت از حافظه Heap استفاده کنید. در صورتی که شما نیاز به متغیرهای کوچکی دارید که تنها نیاز است در زمان اجرای تابع در دسترس باشند و قابلیت خواندن و نوشتن سریعتری داشته باشند از نوع حافظه Stack استفاده کنید. فقط فراموش نکنید که حافظه Heap تحت توابع molloc(), realloc(), calloc() و free() مدیریت میشوند. هرچند اشارهگر های هوشمند نیز در ++C وجود دارند اما در بسیاری از مواقع که نیاز است بسیار جزئی و حساس بر روی کدهای خود کار کنید از مدیریت حافظه به صورت دستی استفاده کنید.
-
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 اشاره کرد. لازم بذکر است اینها نمونهای از کتابخانههای بیشمار سی++ هستند و میتوان به کتابخانههای بسیاری اشاره کرد که خارج از گنجایش این مقاله است. منابع فارسی برای یادگیری سیپلاسپلاس مدرن چیست؟ متأسفانه منابع فارسی برای این زبان معمولاً متعلق به مباحث دانشگاهی و مفاهیم مرتبط به سیپلاسپلاس سنتی است (مربوط به ۳۰ سال پیش)! یادگیری این مباحث هیچ مزیتی برای شما نخواهد داشت و به شدت پیشنهاد میشود جهت یادگیری این زبان حتماً به سراغ آموزشهای مدرن بروید. تنها بسترهای آموزشی مربوط به سیپلاسپلاس جدید در ایران (به زبان فارسی) مرجع آیاواستریم است.
-
9 امتیازهنگامیکه شما برای اولین بار از C به CPP مهاجرت می کنید، یا اصلا برنامه نویسی را قصد دارید با CPP شروع کنید، با مفاهیم متعددی روبرو خواهید شد که شاید برای شما جالب باشند که بدانید، این ایده ها چطور شکل گرفتند، چطور به CPP افزوده شدند و اهمیت آن ها در عمل (هنگام برنامه نویسی و توسعه نرم افزار) چیست. در این پست وبلاگی IOStream، به این خواهیم پرداخت که ایده Overloading و Template و Auto Deduction چطور از CPP سر در آوردند. همانطور که شما ممکن است تجربه کرده باشید، هنگامیکه برنامه نویسی و توسعه نرم افزاری را با C شروع می کنید، برنامه شما چیزی بیش از یک مجموعه بی انتها از توابع و استراکچرها و متغیرها و اشاره گرها و ... نخواهند بود. از همین روی شما مجبور هستید مبتنی بر ایده مهندسی نرم افزار و پارادیم برنامه نویسی ساخت یافته، برای هر کاری یک تابع منحصربفرد پیاده سازی کنید. این تابع باید از هر لحاظی از قبیل نام، نوع ورودی ها، نوع خروجی و حتی نوع عملکرد منحصربفرد باشد تا بتواند یک کار را به شکل صحیح کنترل کند که همین مسئله می تواند در پیاده سازی برخی نرم افزارها، انسان را در جهنم داغ و سوزان قرار بدهد. مثلا پیاده سازی یک برنامه محاسباتی مانند ماشین حساب که ممکن است با انواع داده های محاسباتی مانند عدد صحیح (Integer) و عدد اعشاری (Float) رو به رو شود. از همین روی فرض کنید، ما قرار است یک عمل محاسباتی مانند جمع از برنامه ماشین حساب را پیاده سازی کنیم. برای اینکه برنامه به شکل صحیحی کار کند، باید عمل جمع یا همان Add برای انواع داده های موجود از قبیل عدد صحیح و اعشاری پیاده سازی شود. اگر شما این کار را انجام ندهید، برنامه شما به شکل صحیحی کار نخواهد کرد (یعنی نتایج اشتباه ممکن است برای ما تولید کند). در تصویر زیر، نمونه این برنامه و توابع مرتبط با آن پیاده سازی شده است: #include <stdio.h> int AddInt(int arg_a, int arg_b) { return arg_a + arg_b; } float AddFloat(float arg_a, float arg_b) { return arg_a + arg_b; } double AddDouble(double arg_a, double arg_b) { return arg_a + arg_b; } int main(int argc, const char* argv[]) { int result_int = AddInt(1, 2); float result_float = AddFloat(10.02f, 21.23f); double result_double = AddDouble(9.0, 24.3); printf("Result Integer: %d", result_int); printf("Result Float: %f", result_float); printf("Result Double: %lf", result_double); return 0; } به برنامه بالا دقت کنید. ما سه تا تابع Add با نام های منحصربفرد داریم که سه نوع داده مجزا را به عنوان ورودی دریافت می کنند، سه نوع نتیجه مجزا بازگشت می دهند، اگرچه پیاده سازی آن ها کاملا مشابه هم دیگر است و تفاوتی در پیاده سازی این سه تابع وجود ندارد. ولی به هر صورت، اگر به خروجی دیزاسمبلی برنامه مشاهده کنید، دلیل این مسئله را متوجه خواهید شد که چرا هنگام برنامه نویسی با زبان C، به نام های منحصربفرد نیاز است، چون اگر توابع نام های مشابه با هم داشته باشند، لینکر نمی تواند به دلیل تداخل نام (Name Conflict)، آدرس آن ها را محاسبه یا اصطلاحا Resolve کند. همانطور که در تصویر بالا خروجی دیزاسمبلی برنامه Add را مشاهده می کنید، اگر توابع نام مشابه داشتند، در هنگام فراخوانی (Call) تابع Add تداخل رخ می داد، چون دینامیک لودر سیستم عامل دقیقا نمی داند که کدام تابع را باید فراخوانی کند. برای همین نیاز است وقتی برنامه نوشته می شود، نام توابع در سطح کدهای اسمبلی و ماشین منحصر بفرد باشد. به هر صورت، به نظر شما آیا راهی وجود دارد که ما پیاده سازی این نوع توابع را ساده تر کنیم یا حداقل بار نامگذاری آن ها را از روی دوش توسعه دهنده و برنامه نویس برداریم؟ بله امکان این کار وجود دارد. مهندسان CPP با افزودن ویژگی Overloading و Name Mangling یا همان بحث Decoration مشکل برنامه نویسان در پیاده سازی توابع با نام های منحصربفرد را حل کردند (البته کاربردهای دیگر هم دارد که فعلا برای بحث ما اهمیت ندارند). ویژگی اورلودینگ در CPP به ما اجازه خواهد داد یک تابع با عنوان Add پیاده سازی کنیم که تفاوت آن ها فقط در نوع ورودی و نوع خروجی است. به عنوان مثال، در قسمت زیر، کد برنامه Add را مشاهده می کنید که با قواعد CPP بازنویسی شده است. #include <iostream> int Add(int arg_a, int arg_b) { return arg_a + arg_b; } float Add(float arg_a, float arg_b) { return arg_a + arg_b; } double Add(double arg_a, double arg_b) { return arg_a + arg_b; } int main(int argc, const char* argv[]) { int result_int = Add(1, 2); float result_float = Add(10.02f, 21.23f); double result_double = Add(9.0, 24.3); std::cout << "Result Integer: " << result_int << std::endl; std::cout << "Result Float: " << result_float << std::endl; std::cout << "Result Double: " << result_double << std::endl; return 0; } همانطور که مشاهده می کنید، ما اکنون سه تابع با نام Add داریم. ولی شاید سوال پرسیده شود که چطور لینکر متوجه تفاوت این توابع با یکدیگر می شود درحالیکه هر سه دارای یک نام واحد هستند. اینجاست که مسئله Name Mangling یا همان Decoration نام آبجکت ها در CPP مطرح می شود. اگر شما برنامه مذکور را دیزاسمبل کنید، متوجه تفاوت کد منبع (Source-code) و کد ماشین/اسمبلی (Machine/Assembly-code) خواهید شد. همانطور که در خروجی دیزاسمبلی برنامه اکنون مشاهده می کنید، توابع اگرچه در سطح کد منبع دارای نام مشابه با یکدیگر بودند، اما بعد کامپایل نام آن ها به شکل بالا تبدیل می شود. به این شیوه نام گذاری Name Mangling یا Decoration گویند که قواعد خاصی در هر کامپایلر برای آن وجود دارد. این ویژگی موجب می شود در ادامه لینکر بتواند تمیز بین انواع توابع Add شود. به عنوان مثال، تابع نامگذاری شده با عنوان j__?Add@YAHH@Z تابعی است که به نوعی از تابع Add اشاره دارد که ورودی هایی از نوع عدد صحیح دریافت می کند. این شیوه نامگذاری خلاصه موجب خواهد شد لینکر بتواند به سادگی بین توابع تمایز قائل شود. با این حال هنوز یک مشکل باقی است، و آن هم تکرار مجدد یک پیاده سازی برای هر تابع است. به نظر شما آیا راهی وجود دارد که ما از پیاده سازی مجدد توابعی که ساختار مشابه برای انواع ورودی ها دارند، جلوگیری کنیم؟ باید بگوییم، بله. این امکان برای شما به عنوان توسعه دهنده CPP در نظر گرفته شده است. ویژگی که اکنون به عنوان Templateها در مباحث Metaprogramming یا Generic Programming استفاده می شود، ایجاد شده است تا این مشکل را اساساً برای ما رفع کند. با استفاده از این ویژگی کافی است، طرح یا الگوی یک تابع را پیاده سازی کنید، تا در ادامه خود کامپایلر مبتنی بر ورودی هایی که به الگو عبور می دهید، در Backend، یک نمونه تابع Overload شده مبتنی بر آن الگو برای نوع داده شما ایجاد کند. #include <iostream> template <typename Type> Type Add(Type arg_a, Type arg_b) { return arg_a + arg_b; } int main(int argc, const char* argv[]) { int result_int = Add(1, 2); float result_float = Add(10.02f, 21.23f); double result_double = Add(9.0, 24.3); std::cout << "Result Integer: " << result_int << std::endl; std::cout << "Result Float: " << result_float << std::endl; std::cout << "Result Double: " << result_double << std::endl; return 0; } به عنوان مثال، در بالا تابع Add را مشاهده می کنید که نوع داده ورودی این تابع و حتی نوع خروجی آن مشخص نشده است و در قالب Typename به کامپایلر معرفی شده است. این یک الگو برای تابع Add است. کامپایلر اکنون می تواند مبتنی بر ورودی هایی که به تابع هنگام فراخوانی یا اصطلاحا Initialization عبور می دهیم، یک نمونه تابع Overload شده از آن الگو ایجاد کند و در ادامه آن را برای استفاده در محیط Runtime فراخوانی کند. حال اگر برنامه بالا را دیزاسمبل کنید، مشاهده خواهید کرد که کامپایلر از همان قاعده Overloading استفاده کرده است تا نمونه ای از تابع Add متناسب با نوع ورودی هایش ایجاد کند. هنوز می توان برنامه نویسی با CPP را جذاب تر و البته ساده تر کرد، اما چطور؟ همانطور که در قطعه کد بالا مشاهده می کنید، هنوز ما باید خود تشخیص دهیم که نوع خروجی تابع قرار است به چه شکل باشد. این مورد خیلی مواقع مشکل ساز خواهد بود. برای حل این مسئله، در CPP مبحثی در نظر گرفته شده است که آن را به عنوان Auto Deduction می شناسیم که سطح هوشمندی کامپایلر CPP را بالاتر می برد. در این ویژگی خود کامپایلر است که مشخص می کند نوع یک متغیر مبتنی بر خروجی که به آن تخصیص داده می شود، چیست. به عنوان مثال، شما می توانید برنامه بالا را به شکل زیر بازنویسی کنید: #include <iostream> template <typename Type> auto Add(Type arg_a, Type arg_b) { return arg_a + arg_b; } int main(int argc, const char* argv[]) { auto result_int = Add(1, 2); auto result_float = Add(10.02f, 21.23f); auto result_double = Add(9.0, 24.3); std::cout << "Result Integer: " << result_int << std::endl; std::cout << "Result Float: " << result_float << std::endl; std::cout << "Result Double: " << result_double << std::endl; return 0; } با استفاده از ویژگی Auto Deduction و کلیدواژه Auto در برنامه، خود کامپایلر در ادامه مشخص خواهد کرد که تابع Add چه نوع خروجی دارد و همچنین نوع متغیرها برای ذخیره سازی خروجی Add چه باید باشد. به عبارتی اکنون تابع Add هم Value و هم Data type را مشخص می کند که این موجب می شود برنامه نویسی با CPP خیلی ساده تر از گذشته شود. حال اگر به نمونه برنامه آخر نگاه کنید و آن را با نمونه C مقایسه کنید، متوجه خواهید شد که CPP چقدر کار را برای ما ساده تر کرده است. در این پست به هر صورت، قصد داشتم به شما نشان دهم که نحوه تحول CPP به صورت گام به گام چطور بوده است و البته اینکه پشت هر ویژگی در CPP چه منطق کلی وجود دارد. امیدوارم این مقاله برای شما مفید بوده باشد. نمونه انگلیسی این مقاله را می توانید در این آدرس (لینک) مطالعه کنید. میلاد کهساری الهادی
-
9 امتیازبا سلام، با توجه به سوالات مکرر برخی از کاربران و خصوصاً دانشجویان جدید، تصمیم گرفته شد تا توضیحاتی دربارهٔ نحوهٔ یادگیری برنامهنویسی با سیپلاسپلاس بیان شود. قبل از هر چیز لازم است بدانید، سیپلاسپلاس یک زبان برنامهنویسی کاملاً تخصصی مهندسی است. بنابراین یادگیری آن طبیعتاً نیاز به تلاش، تحمل و پشتکار کافی در مقابل چالشهای آن خواهد داشت. مقدمه در حال حاضر بیش از سه دهه است که از ساخت و معرفی زبان برنامهنویسی ++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 اگر در حد توانم باشد شما را راهنمایی خواهم کرد.
-
8 امتیاز
نگارش ۵.۱۵.2
501 دریافت
کیوت (به انگلیسی: Qt) مجموعهای از کتابخانهها و سرآیندهای نوشتهشده به زبان سی++ است که به برنامهنویس امکان توسعه آسان نرمافزارهای کاربردی را میدهد. کیوت شامل چندین کلاس برای کار با واسط گرافیکی، چندرسانه، ابزارهای پایگاهداده، شبکه و … است. نرمافزارهای نوشته شده با ابزار کیوت قادرند تا با استفاده از یک کامپایلر زبان سیپلاسپلاس برای طیف وسیعی از سیستمعاملها از جمله گنو/لینوکس (نسخههای رومیزی و وسیلههای قابل حمل)، ویندوز، ویندوز CE، مکاواس و … همگردانی شوند. بدین ترتیب حمل نرمافزار نوشته شده بدون تغییر در متن کد نوشته شده امکانپذیر است. از کیوت در زبانهای برنامهنویسی متعددی مانند سی++ و جاوا و پایتون میتوان استفادهکرد. جهت مشاهدهٔ مباحث مرتبط با این کتابخانه به این بخش مراجعه کنید.رایگان
-
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 امتیاز
نگارش 5.0
هدف از این آموزشها آشنایی با امکاناتی که در Qt میتوان استفاده کرد میباشد، که شامل کدنویسی کمتر، خروجی و طرح های بیشتر و در نهایت استفاده در پلتفرمهای مورد مختلف است. لذا جهت بهرهمندی از این کتابخانه ما با در نظر گرفتن اینکه علاقهمندان با زبان ++C آشنایی لازم را دارند منتشر کردهایم. بنابراین در صورتی که علاقهمندان اطلاعات کافی در رابطه با خود زبان ندارند پیشنهاد میکنیم ابتدا اقدام به تهیه و مطالعه آموزشهای لازم در ++C نمایند که برخی از لینکهای رسمی و استاندارد آن را در زیر اعلام نمودهایم. نوع این کتاب الکترونیکی است، بعد از پرداخت میتوانید بر روی دکمهٔ دریافت فایل در همین صفحه کلیک کرده و آن را دریافت نمایید. در صورتی که درگاه پرداختی با مشکل مواجه شده باشد، میتوانید به شماره کارت ۶۱۰۴۳۳۷۸۸۴۵۳۳۳۴۸ (بانک ملت) واریز و آن را به آدرس kambiz.ceo@gmail.com و یا شناسهٔ تلگرامی @Kambiz_Asadzadeh اطلاع دهید تا تأیید شود. عنوان این آموزش "برنامه نویسی ++C همراه با کتابخانه های Qt 5.12.x (سطح مقدماتی ویرایش ۵) میباشد که به صورت زیر فهرست بندی شده است: فصل اول مقدمه کتابخانه Qt قابلیت ها در طراحی فناوری Qt Quick و QML نسخه های کیوت مجوز های موجود در این کتابخانه محیط های توسعه کیوت ویژگی های کیوت پشتیبانی از انواع سیستم عامل ها نصب و پیکربندی Qt فصل دوم انواه پروژه و ایجاد آن انواع پروژه ها ایجاد پروژه فصل سوم ساده ترین برنامه معرفی و کار با Signal و Slot ها و Event ها معرفی و کار با نمایش Windows معرفی و کار با لایه ها زبانه ها و بدنه های در طراحی معرفی و کار با قابلیت های HTML و CSS در طراحی فصل چهارم معرفی و کار با لایه های افقی و عمودی معرفی و کار با لایه های Grid در طراحی فرم معرفی و کار با جدا کننده ها Splitter فصل پنجم معرفی و کار با دایرکتوری ها معرفی و کار با فایل ها / خواندن و نوشتن در آن ها فصل ششم معرفی و کار با برچسب ها Label معرفی و کار با دکمه ها Button معرفی و کار با کنترل ورودی LineEdit معرفی و کار با چک باکس CheckBox معرفی و کار با RadioButton معرفی و کار با Combobox معرفی و کار با لیست ها / ListWidget معرفی و کار با لیست های درختی / TreeWidget معرفی و کار با Action ها معرفی و کار با Slider و Progress ها معرفی و کار با Statusbar در فرم فصل هفتم معرفی و کار با MessageBox معرفی و کار با Timer معرفی و کار با Thread ها فصل هشتم معرفی و کار با Map معرفی و کار با Hash معرفی و کار با QStringList لیست رشته ای فصل نهم معرفی و کار با الگوریتم های معرفی و کار شبکه / دانلود فایل بر اساس پروتکل های HTTP و FTP معرفی و کار با باینری و سریالیز کردن آبجکت ها معرفی و کار با TextStream ها فصل دهم مقایسه انواع حالت های کامپایل در Qt نحوه افزودن دیگر کتابخانه های C++ در محیط Qt Creator و استفاده همراه با کتابخانه Qt نحوه خروجی گرفتن / گسترش (Deployment) در Qt مقایسه و پیکربندی دو موتور قدرتمند OpenGL و ANGLE در پروژه درایور دیتابیس هایی که تحت این کتابخانه پشتیبانی میشوند ساخت راهانداز دیتابیس در پلتفرمهای Linux، macOS و Windows حق نشر کتاب و اهداف در نسخهٔ بعدی کتاب توجه : در داشتن هر گونه انتقاد و پیشنهاد در رابطه با این کتاب با آدرس شخصی نویسنده (kambiz.ceo@gmail.com) مکاتبه نمایید. نکته دوم : کسانی که این کتاب را یک بار خریداری میکنند نسخهٔ به روز رسانی شده آن را به صورت رایگان میتوانند دریافت کنند.﷼۲۰۰٬۰۰۰
-
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 امتیازبا سلام، یا توجه به مقالهٔ ذکر شده زیر در ارتباط با انتخاب زبان برنامهنویسی و تفاوت عمدهٔ زبانهای کامپایلری و مفسری لازم است تعاریفی در رابطه با جزئیات زبانهای کامپایلری که خود تفاوتهایی را شامل میشوند بپردازیم. در صورتی که مقالهٔ زیر را مطالعه نکردهاید پیشنهاد میکنیم قبل از خواندن این مقاله آن را مرور کنید. در این مقاله شما تفاوت عمدهٔ آنها را خواهید آموخت که شامل توضیحات کامپایلر و روشهای کامپایل میباشد. کامپایلر چیست؟ کامپایلر به ابزار (برنامه یا مجموعهای از برنامهها) گفته میشود، که متنِ نوشته شدهٔ برنامهنویسان (در قالب کُد) را که از سطح بالاتر (زبان مبدأ) برخوردار است و درک آن برای انسان مُیسر میباشد، دریافت کرده و آن را به زبان سطح پایینتر (زبان مقصد) مانند اسمبلی یا کُد ماشین ترجمه میکند. زبانهای کامپایلری در دو دستهی بومی (Native) و مجازی (Virtual) کامپایل از نوع بومی روشی است که کدهای نوشته شده را به صورت مستقیم به کُد ماشین ترجمه میکند. کامپایل از نوع مجازی روشی است که کدهای نوشته شده را ابتدا به کُدمیانی (کدمشترک یا همان بایت کُد - Byte Code) در جاوا و زبان میانی (CIL) در Net. تبدیل میکند که خودِ آن شبیه به کُد ماشین است. در این فرایند کد مربوطه توسط کامپایلر مخصوص یعنی JIT (کامپایلری از نوع Just-In-Time) در زمان اجرا توسط سیستمعامل، به دستورالعملهای قابل فهم برای پردازنده تفسیر و اجرا میشود (که این فرایند شبیه به فرایند عملکرد اجرایی مفسرها است). زبانهای بومی (زبانهایی که کد آنها به کد ماشین به صورت مستقیم توسط کامپایلر قبل از اجرای آنها توسط سیستمعامل، ترجمه میشوند که به اصطلاح ahead-of-time (جلوتر از زمان) یا همان AOT نام دارد) مانند: C, C++, Rust, Haskell, Clean, Swift, Go, Fortran, D زبانهای مجازی (زبانهایی که کد آنها توسط یک رابط میانی به زبان مشترک ترجمه میشود) : Java و خانوادهٔ داتنت مانند C#, Visual Basic.Net و C++/CLR نکته قابل توجه در مورد C++/CLR آن است که این نوع استاندارد در مورد سیپلاسپلاس بر پایهٔ چهارچوب داتنت است. در این نسخه از زبان شما با محدودیتهای بسیاری مواجه بوده و به ویژگیها و کیفیت نهایی برنامههای تولید شدهٔ واقعی در قالب Native محروم خواهید بود. روش کامپایل و و انواع آنها کامپایلرها به صورت بومی (Native) و کراس (Cross) تقسیم بندی میشوند. به طور کلی آن دسته از کامپایلرها که کدهای باینری را تولید میکنند از نوع محلی یا همان Native نام دارند؛ در واقع به هر کامپایلی که بر روی سیستمهای معماری x86 نوع x86، بر روی سیستمهای x86-64 نوع x86-64 و بر روی سیستمهای PowerPC نوع powerpc و بر روی arm نوع arm را تولید کند کامپایل بومی میگویند. چرا که تنها برای یک پلتفرمِ هدف کدهای ماشین رو تولید خواهد کرد (در صورت نیاز برای اجرا بر روی پلتفرمهای دیگر باید آن را بر روی پلتفرم متناسب با آن پیکربندی کنید) در واقع یک وابستگی به سختافزار وجود خواهد داشت که کدهای شما بر اساس آن تولید میشود. اما در رابطه با کامپایلرها از نوع Cross یا به اصطلاح عبوری وابستگی خاصی به سختافزار ندارند، در این روش کافی است سختافزار، پلتفرم (معماری و سیستمعامل) مورد نظر را یک بار برای آن معرفی کرده و اقدام به کامپایل کنید. کامپایل به صورت کراس کدها را به برنامهٔ قابل اجرا برای بیشتر از یک پلتفرم فراهم میکند. برای مثال در صورتی که بر روی پلتفرم ویندوز هستید میتوانید برنامهٔ نوشته شدهٔ خود را برای پلتفرم اندروید یا آیاواس که برای arm هستند ارائه دهید. اولین کامپایلری که این ویژگی را پشتیبانی میکند GCC است. این امکان وجود دارد که شما کدهای نوشته شدهٔ خود را بر روی پلتفرم میزبان برای پلتفرمهای هدف (مقصد) کامپایل کنید. البته جدیداً کامپالر کلَنگ (Clang) به عنوان یکی از بهترین انتخاب بین برنامهنویسان ++C جهت کراسکامپایل مطرح میشود. کامپایلرهای پیشنهادی: GCC Clang MSVC مزایا و معایب زبانهای کامپایلری از نوع کلاس بومی (Native) از سرعت بسیار بالایی برخوردار هستند (دلیل آن ترجمهٔ مستقیم کدها به کد ماشین است) در مقابل بزرگترین مزیتی که زبانهای نوع کلاس مجازی (Byte Code) دارند به خاطر وجود یک برنامهٔ واسط جهت شبیهسازی کدهای ترجمه شده به کد قابل فهم برای پردازنده، اجرا شدن آنها در هر پلتفرم بدون کامپایل مجدد امکان پذیر است که البته این ویژگی خود نیازمند نصب بودن JVM بر روی پلتفرم مربوطه میباشد. در نوع بومی برای اجرا در هر پلتفرم لازم است سورس کدها را برای پلتفرم مقصد کامپایل کنید که نیازی به وجود ماشین مجازی مانند JVM یا برنامهٔ خاصی ندارد. کدهای میانی تحت کامپایلِ درجا JIT : Just In Time همانطور اشاره شد زبانهای برنامهنویسی Java و خانوادهٔ Net. به ترتیب توسط Java Byte Code بر روی ماشین مجازی جاوا JVM و CIL : Common Intermediate Language بر روی زیر ساخت CLI : Common Language Infrastructure از هم جدا میشوند. در نظر داشته باشید CIL نام تغییر یافتهٔ MSIL میباشد. معنای ماشین مجازی CLR و JVM جیویام یا همان JVM : Java virtual machine نوعی ماشین مجازی (واسطی) است که وظیفه اجرای کد جاوا را برعهده دارد. زمانی که در مورد برنامههای نوشته شده توسط جاوا صحبت میکنیم، حتما باید JVM بر روی سیستم شما نصب باشد تا قابلیت اجرا شدن برنامههای تحت جاوا را داشته باشد. سیاِلآر یا همان CLR : Common Language Runtime نوعی ماشین مجازی (واسطی) است که کدهای مربوط به CIL را برای سیستم تفسیر و اجرا میکند. البته تفاوتهایی در خروجی این کد با کدهای جاوا وجود دارد که در آن زبان IL به عنوان یک زبان شبیه به زبان ماشین مانند اسمبلی (assembly) میباشد. در CLR کدهای تولید شدهٔ بایتکد، کمتر از دستورالعملها و ابردادههای JVM است. تفاوت اصلی CLR و JVM تفاوت اصلی JVM و CLR در این است که JVM جهت اجرای کدهای جاوا استفاده میشود و CLR مدیریت برنامههای اجرایی داتنت را مدیریت میکند. به طور کلی، JVM امکان اجرای کدهای کامپایل شدهی جاوا را فراهم میکند که در بسیاری از سیستمعاملها و سختافزارها موجود است. از سوی دیگر، CLR یک بستر (محیطی) را برای اجرای برنامههای نوشته شده در چهارچوب داتنت همراه با امکان مدیریت حافظه، مدیریت خطاها، امنیت و غیره را فراهم میکند. نسل جدید JIT برای داتنت (نام کد RyuJIT) به لُطف Net. و نسخهٔ Net Core. نام RyuJIT کُد شناسه از کامپایلر Net. است که وظیفهٔ آن ترجمهٔ کدهای #C به بایتکُد IL است که RyuJIT کدهای بایتکُد از نوع IL را به کُد ماشین ترجمه میکند. همانطور که مشخص است، جهان به سمت محاسبات ۶۴ بیتی حرکت میکند، اما باید در نظر داشته باشید سرعت برنامههای ۶۴ بیتی همیشه بیشتر از ۳۲ بیتیها نمیباشد! برای مثال نمونهای از آن را میتوان به کامپایلر JIT برای داتنت مثال زد؛ تغییرات و بهبودهایی که در نسل بعدی کامپایلر JIT بر روی Net Core. صورت گرفته است نسخهٔ ۶۴ بیتی آن است که اجازه میدهد برنامهها دو برابر سریعتر از نسخهٔ قبلی خود در داتنِت اجرا شود. این امر باعث میشود که نظرات شما را در مورد این نسخه از کامپایلر داتنت تغییر دهد. همانطور که به نظر میرسد، معماری ۳۲ بیتی x86 کامپیوترها که از زمانهای ایجاد تا به کنون در نوع خود بسیار عالی بودهاند، اما مشکل بزرگی که دارند متاسفانه پشتیبانی تا حداکثر ۴ گیگابایت حافظهٔ اصلی (Ram) است. با توجه به رُشد روز افزون معماری ۶۴ بیتی x64 نیاز به حافظههای بیش از ۴ گیگابایت جدی شد و امروزه ما میبینیم که اکثر سختافزارها و حتی دستگاههای موبایل نیز مجهز به حافظههای بیش از ۴ گیگابایت هستند. برای بهرهمندی از قابلیتهای معماری جدید Net Core. کامپایلر خود را با بهینهسازیهای چشمگیری ارائه داده است که میتواند تا دو برابر سریعتر از نسل قبلی خود عمل کند. در نظر داشته باشید که، معماری RyuJIT تقریبا نه سال پیش طراحی شده است و کارهای اجرایی از هفت سال پیش آغاز شده است. RyuJIT به عنوان یک کامپایلر تکامل یافته از JIT32 موجود (که از x86 و ARM32 پشتیبانی میکند) اجرا شد و به تدریج جایگزین بسیاری از بخشهای "بَکاِند" آن کامپایلر با یک تخصیص دهندهٔ رجیستر جدید و تولید کنندهٔ کد همراه با برخی از ویژگیهای جدید و بهبود یافته در "فرانتاِند" برای بهینه سازی در اجرا معرفی شده است. در طول این انتقال به کدهای نسل جدید معماری، سعی بر این بوده است که کدهای نسل قبل را در کنار نسل جدید نگه داشته شود. انجام این کارها مزایایی داشته است مانند حفظ هزینهها و باز نویسیهای بسیار! اما مسلماً هزینههایی هم دربر داشته است که کمترین آنها سردرگم بودن توسعهدهندگان در بارهٔ آیندهٔ Jit بوده است. در حال حاضر عملکرد RyuJIT برای کدهای قدیمی بسیار خوب بوده است و سرانجام وقت آن رسیده است که کدهای نسل قبل در JIT در آیندهای نزدیک تمرکز شود. نسل جدید از JIT با تمرکز بر پشتیبانی از معماری ۶۴ بیتی با نام RyuJIT سریعتر از JIT64 است. زبانهایی که از JIT/CLR پشتیبانی میکنند زبانهای اصلی این کامپایلر C#, VB.Net و C++ Managed یا همان C++/CLR میباشند. نکته: سی++ در این نسخه تغییراتی از جانب مایکروسافت داشته است و از نسخهٔ استاندارد آن کمی متفاوت است. برای مثال مدیریت حافظه به صورت خودکار و همچنین تغییرات جزئی از قبیل سینتکس را دارا میباشد. ساختار برنامههای زبان کامپایلری از نوع بومی (Native) در زبانهای مادر C و ++C در صورتی که تمایل دارید در رابطه با جزئیات ساختار برنامههای سریعترین زبانهای برنامهنویسی یعنی C و ++C مطلع شوید توصیه میشود مقالهٔ مرتبط با آن را که در زیر آمده است مطلعه کنید.
-
7 امتیازبا درود، وجود کتابخانههای متعدد برای توسعهی رباتهای تلگرام برای زبانها و چهارچوبهای مختلف، و عدم وجود یک کتابخانه بهروز برای ++C و کیوت باعث شد تا توسعهی این پروژه را آغاز کنم. امیدوارم این پروژه برای توسعهدهندگان مفید واقع شود. عنوان: پروژهی TarnaBot توضیحات: یک کتابخانه بر پایه فریمورک کیوت (Qt) که به توسعهدهندگان امکان برنامهنویسی رباتهای تلگرام را میدهد. زبانها و فناوریهای استفاده شده: ++C فریمورک ها و کتابخانهها: کیوت (Qt) نسخه ۵ ابزارِ ساخت: qmake نوع پروژه: متن باز (Open source) مجوز: LGPL v3 نویسندگان: علی رشیدی وضعیت: در حال توسعه - پایدار (stable) مثالها و مستندات به زودی اضافه خواهند شد.
-
6 امتیازاصطلاحاتی که بهتر است در مورد C++ مدرن بدانید! داشتم به این فکر میکردم که برخی از مبتدیان برنامهنویسی به خصوص کسانی که به سراغ زبانهایی مثل سی++ میروند معمولاً مستقیم وارد کد نویسی میشوند و به این گمان که آغاز برنامهنویسی یعنی نوشتن یک کد با خروجی «سلام، دنیا»! دریغ از آن که بعضی از موارد مانند «معرفی کامپایلر و انواع آن» و حتی «ساختار برنامههای نوشته شده تحت سیپلاسپلاس» و یا حتی «مدیریت حافظه» را در نظر بگیرند! من معمولاً در مقالات و آموزشهای خودم به این اشاره میکنم که قبل از هر چیز باید با ساختار برنامههای نوشته شدهٔ یک زبان آشنا شد و سپس به بررسی موارد دیگر مانند نحو زبان و یا دیگر ویژگیهای آن. بنابراین، یکی از خطرناکترین عواملی که موجب خونریزی داخلی یک نرمافزار در برنامههای نوشته شده توسط برنامهنویس درC++ میشود عدم مدیریت حافظهٔ اختصاص یافته است که باید بعد از اختصاص یافتن حافظه در زمان معین آن را آزادسازی کند. در صورتی که این کار صورت نگیرد عمل Memory Leak (نَشتِ حافظه) رخ داده است. بسیاری از علاقهمندان بر این باورند که چون سی++ دارای GC یا همان Garbage Collector (زبالهروب) نیست که البته صحیح است! سی++ دارای GC نیست و این امر محدودیت یا نکته ضعف آن هم نیست! سی++ همه چیز را آزادانه در اختیار برنامهنویس قرار میدهد تا خود در زمان مناسب روش مدیریت حافظه را انتخاب کند. در علوم رایانه بازیافت حافظه یا زبالهروبی نوعی مدیریت حافظهٔ خودکار است که عمل مدیریت حافظههای اختصاص یافته شده را به دست میگیرد و اکثر زبانهای برنامهنویسی مانند #C، جاوا و دیگر موارد مشابه به آن مجهز به این ویژگی هستند که البته وجود چنین ابزارهایی میتواند توهمی را ایجاد کند مبنی بر آن که دیگر نیازی به مدیریت منابع نیست، اما در بعضی موارد مدیریت منابع هنوز یک الزام است چرا که منابع آزاد شده هنوز هم دلیل بر نشتِ حافظه هستند. این نشت حافظه زمانی اتفاق میافتد که اشیاء هنوز قابل دسترس از طرف اشیاءای که زنده هستند اما هرگز مورد استفادهٔ دوباره قرار نمیگیرند اتفاق بیافتد. در بسیاری از زبانهای برنامهنویسی این ویژگی وجود دارد که طبیعتاً مدیریت توسط GC راه حل بسیار خوب و بی نقصی نیست. اما با توجه به عدم وجود GC در سی++ اکثراً با روشهای دستی برای مدیریت حافظه میپردازند که رایجترین روش آن استفاده از عمل new و delete در اختصاص دادن و آزادسازی حافظه است. بسیاری از ما با سی++ در دانشگاه و یا دروس مرتبط با مفاهیم اولیه برنامهنویسی آشنا شده ایم، اما معمولاً مفاهیم مربوطه برای نسلهای قبلی و منسوخ شدهٔ این زبان است. بهتر است در نظر داشته باشید که برنامهنویسی مدرن یعنی پیروی از اصول و قوانین جدیدی که در تکامل یافتن یک زبان به کار گرفته میشود. RAII : Resource Acquisition is initialization بنابراین، باید در نظر گرفت مدیریت حافظه از استاندارد ۱۱ به بعد این زبان به روشهای بسیار مدرنتری هوشمند سازی شده است. یکی از بهترین تکنیکهای موجود در هستهٔ زبان اصطلاح Raiiاست. الگوی RAII مخفف «Resource Acquisition is initialization» که به عنوان یک اصطلاح در برنامهنویسی مطرح میشود به صورت یک تکنیک (کنترل تخصیص منابع و آزادسازی آنها) یکی از ویژگیهای اصلی در سیپلاسپلاس است. با قرار دادن چنین کدی دیگر نیاز به فراخوانی آن کد توسط برنامهنویس در مخرب (ویرانگر) نیست و کامپایلر خود این کار را انجام میدهد. به طور کلی این الگو هر شیء را مجبور میسازد تا در زمان مواجه با رفتارهای ناهنجار خود را پاکسازی کند. به طور کلی هنگامی که شما یک شیء را مقداردهی اولیه میکنید، قبل از انجام آن باید منابع مورد نیاز آن را تأمین کنید (در سازنده). هنگامی که یک شیء از محدوده خارج میشود، هر منبعی را که مورد استفاده قرار داده است باید آزاد کند (در مخرب - ویرانگر). نکات کلیدی هرگز نباید یک شیء به حالت نیمه آماده یا نیمه از بین رفته وجود داشته باشد! وقتی که یک شیء ساخته میشود، آن شیء باید در حالت آماده باش برای استفاده باشد. وقتی یک شیء از محدوده خارج میشود، باید منابع اختصاص یافتهٔ خود را در حافظه آزاد کند (کاربر مجبور به انجام کار دیگری نیست). آیا RAII عنوان بدی برای مفهوم این تکنیک است! از نظر خالق سیپلاسپلاس نام بهتر میتواند به صورت زیر باشد: مدیریت منابع مبتنی بر حوزه (محدوده یا دامنه) : Scope Based Resource Management چیزی که تکنیک RAII را نقض میکند چیست؟ اشارهگرهای خام و تخصیص حافظه فراخوانی با کلمهٔ کلیدی new برای دست آوردن یا اختصاص دادن منبع (حافظه). فراخوانی با کلمهٔ کلیدی delete برای آزادسازی منبع (حافظه). اما این مورد به صورت خودکار بعد از خروج از محدوده توسط اشارهگرها صورت نمیگیرد. void rawPtrFn() { // acquire memory resourceNode* n = newNode; // manually release memory delete n; } بنابراین در صورتی که برنامهنویس استفاده از کلمهٔ کلیدی delete را برای آزادسازی حافظه فراموش کند (نشتِ حافظه) رخ میدهد. این عمل کافی است تا تکنیک RAII را نقض کنیم. void UseRawPointer() { // Using a raw pointer -- not recommended. Song* pSong = new Song(L"Nothing on You", L"Kambiz Asadzadeh"); // Use pSong... // Don't forget to delete! delete pSong; } بنابراین، راه حل RAII برای این امر در چیست؟ کلاسی داشته باشید که : حافظه را هنگام مقداردهی اولیه تخصیص دهد. حافظه را هنگام فراخوانی مخرب (ویرانگر) آزاد کند. دسترسی به اشارهگرهای زیرین را امکانپذیر کند. اشارهگرهای هوشمند (Smart Pointers) یک اشارهگر هوشمند یک شیء به سبکِ RAII است که تضمین میکند یک اشارهگر در هر زمانی که مناسب باشد حافظهٔ اختصاص یافته شده را آزاد میکند. به عنوان یک قاعده، برنامههای نوشته شده در سیپلاسپلاس مدرن (پیشرفته) هرگز نباید از اشارهگرهای خام (Raw) برای مدیریت حافظهٔ پویا (مشترک) استفاده کنند. برنابراین، در برنامههای مدرن سی++ به ندرت باید از کلمهٔ کلیدی delete جهت آزادسازی حافظه استفاده کرد. در واقع انجام این روش موجب جلوگیری از نشت حافظه است. این ویژگی اساساً مدیریت حافظهٔ خودکار را ارائه میدهد. زمانی که یک اشارهگر هوشمند دیگر استفاده نمیشود (زمانی که از محدودهٔ خود خارج میشود) حافظهٔ مورد نظر خود را به طور خودکار آزاد میکند.توجه داشته باشید که اشارهگرهای سنتی با عنوان اشارهگرهای خام (Raw Pointer) شناخته میشوند. اشارهگرهای هوشمند را میتواند یک شکل کلی از GC در نظر گرفت؛ نوعی مدیریت خودکار وقتی که دیگر توسط برنامه مورد استفاده قرار نمیگیرند حافظهٔ اختصاص یافتهٔ آن شیء به طور خودکار حذف میشود. در استاندارد ۱۱ سیپلاسپلاس سه نوع اشارهگر هوشمند معرفی شده است که همهٔ آنها در فایل سرآیند <memory> از کتابخانهٔ استاندارد STL معرفی شدهاند. کلاس std::unique_ptr یک اشارهگر هوشمند که دارای یک منبع تخصیص حافظهٔ پویا است. این شیء دارای یک اشارهگر به حافظهٔ پشته است، بنابراین نمیتوان آن را کپی کرد. تنها میتوان آن را جابجا (move) و مبادله کرد. خارج از این بیشتر مانند یک اشارهگر عادی رفتار میکند. { std::unique_ptr<Person> person(new Person("Kambiz")); if (person != nullptr) person->SetLastName("Asadzadeh"); if (person) DoSomethingWith(*person); } اگر دقت کنید، اپراتورهای -> و * اطمینان میدهد که unique_ptr میتواند اکثر اوقات شبیه به یک اشارهگر خام (Raw Pointer) استفاده شود. کاربردهای معمول از unique_ptr که باعث میشود از آن را به یک ابزار واقعی و ضروری تبدیل کند به صورت زیر است: آنها را میتوان با خیال راحت در داخل یک ظرف (Container) ذخیره کرد. هنگامی که به عنوان متغیرهای عضو کلاس دیگر استفاده میشوند، نیاز به حذف صریح در مخرب را از بین میبرند. در واقع نیازی نیست در مخرب کلاس خود شیءای را که حافظهای را به خود اختصاص داده است به صورت دستی آزاد کنید. علاوه بر این، موجب جلوگیری تولید خطاهای احتمالی از طرف کپی عضوها برای اشیاءای که باید حافظهٔ پویا داشته باشد در کامپایلر نیز میشود. آنها امنترین و توصیه شدهترین روشهایی برای انتقال مالکیت انحصاری، یا بازگشت به یک unique_ptr از یک تابع که شیء ای را در پشته ساخته است و یا با انتقال یکی از آنها به عنوان آرگومانی که در تابع میتواند به عنوان مالکیت بیشتر پذیرفته شود. در هر دو مورد، std::move به طور کلی باید مورد استفاده قرار بگیرد، و این انتقال مالکیت را به صورت صریح بیان میکند. انتقال مالکیت از قبل تعیین شده از طرف توابع امضاء شده معلوم میشود. از نشت حافطه جلوگیری میکند. همچنین، یک شیء unique_ptr میتواند حافظهٔ اختصاص داده شده را با استفاده از new[] مدیریت کند: { std::unique_ptr<int[]> array(new int[123]); DoSomethingWith(array.get()); } به طور معمول توصیه میشود که برای ساخت یک unique_ptr از std::make_unique() استفاده شود. کلاس std::shared_ptr شامل یک اشارهگری است که دارای یک منبع تخصیص حافظهٔ پویا با تفاوت اینکه میتواند چندین شیء را به صورت اشتراکی از یک منبع مشترک ردیابی کند. در واقع هنگامی که موجودیتهای متعددی همان شیء اختصاص یافته شده به حافظه را به اشتراک میگذارند، البته این وضعیت همیشه مشهود نبوده و یا ممکن است آن را به یک مالک واحدی اتخصاص دهید. این اشاره گر های هوشمند، شمارندهای از یک رشتهٔ ایمن(thread-safe) برای منبع حافظهٔ مشترک حفظ میکند و در زمانی که تعداد مرجع آن به صفر رسید، حذف میشود. در واقع این زمانی رخ میدهد که آخرین شیء مشترک از آن حذف شود. تابع use_count() نیز تعداد مراجع را بر میگرداند. همچنین مشابه unique_ptr این شیء یعنی shared_ptr میتواند آرایههای پویا را مدیریت کند که این ویژگی از استاندارد ۱۷ به بعد ممکن شده است. چندین شیء از shared_ptr ممکن است دارای همان شیء باشند. اگر یکی از موارد زیر اتفاق بیفتد، شیء از بین رفته و حافظهٔ آن آزاد میشود: آخرین بازمانده از شیء shared_ptr از بین رفته باشد. آخرین بازماندهٔ شیٔ shared_ptr که دارای یک اشارهگر از طریق اپراتور = و یا reset() است تعیین میشود. آنچه که shared_ptr را از unique_ptr متمایز میکند آن است که آنها میتوانند کپی شوند: { auto age = std::make_shared<int>(30); auto aliasAge = age; age.reset(); } کلاسstd::weak_ptr مانند std::shared_ptr است اما با تفاوت آن که شمارندهٔ آن افزایش نمییابد و اختیار شیء را به دست نمیگیرد. درواقع، بعضی اوقات نیاز است هنگام ساخت مخازنی از اشیاءای که به اشتراک گذاشته شدهاند بدانید آن شیء وجود دارد یا خیر. کاربرد آن نیز همراه با shared_ptr معتبر است و اطلاعاتی در بارهٔ اشیائی که توسط shared_ptr به دست گرفته است ارائه میکند. چند مثال در بارهٔ اشارهگرهای هوشمند: { std::unique_ptr<int> p(new int); // شیء p قابل استفاده در داخل حوزه است. } // در این بخش که خارج از دامنهٔ اشارهگر است حافظهٔ اختصاص یافته آزاد میشود. همانطور که مشخص است یک شیء که تحت اشارهگر هوشمند مورد استفاده قرار میگیرد تا زمانی که خارج از حوزهٔ خود قرار نگیرد قابل استفاده خواهد بود. نمونه کد پایین مثالی از نحوهٔ نمونه سازی تحت اشارهگرهای هوشمند است. void UseSmartPointer() { // Declare a smart pointer on stack and pass it the raw pointer. unique_ptr<Song> song2(new Song(L"Nothing on You", L"Kambiz Asadzadeh")); // Use song2... wstring s = song2->duration_; //... } // song2 is deleted automatically here.
-
6 امتیازمنتور چیست؟ منتور (Mentor) به افرادی میگویند که در یک زمینهٔ خاصی تخصص، تسلط و تجربه دارند و در آن زمینه کارشناس و صاحب نظر هستند و میتوانند به دیگران در یادگیری آن کار کمک کنند. منتور یک رابطه ارگانیک و دوستانه با افراد جوانتر تحت سرپرستی خود برقرار میکند و نه تنها در مورد دروس دانشگاهی بلکه در خصوص مشاغل و مشکلات فرهنگی، اجتماعی و روحی و روانی آنان را یاری می دهد. همهٔ ما در زندگیمان فردی را ملاقات کردهایم که هم نشینی و هم صحبتی با او برای زندگی ما اهمیت داشته است. برای مثال، این فرد میتواند یکی از معلمهای ما و یا یکی از اعضای خانواده باشد. چنین فردی را می توان منتور نامید. خصوصیات و وظایفی که منتور دارد سابقه کار قابل توجه علاقهمند به آموزش و انتقال تجربیات خود به دیگران دارای تجربهٔ شکست و موفقیت دارای ارتباطات قابل توجه سابقهٔ کار در تیمهای استارتآپی آگاه به مسائل استارتآپی اهل دانش دانش و تجربیات زندگی خود را به اشتراک میگذارد توصیه میکند و مشاوره میدهد گوش میدهد الهام میبخشد تشویق میکند با علاقه به سؤالات و نگرانیهای فرد پاسخ میدهد صادق و انتقادپذیر است راجع به هدفگذاری بحث میکند در مورد رشد شغلی و حرفهای مشاوره میدهد منابع را شناسایی میکند به رشد مهارتهای مدیریت و رهبری کمک میکند برای رشد فرهنگ سازمانی تلاش میکند میتواند باعث شفافیت در سازمان شود رزومهها را بررسی میکند نکتههای کلیدی برای مصاحبه را تعیین میکند حمایت کننده است ممکن است فرد را به اشخاص کاربلد دیگری ارجاع دهد فرد را به چالش میکشد تا از حوزهٔ امن خودش بیرون بیاید یک محیط یادگیری ایمن برای ریسک کردن ایجاد میکند روی رشد همهجانبهٔ فرد تمرکز دارد مزایایی که یک منتور میتواند داشته باشد پژوهشها نشان داده است که کسانی که از وجود منتور بهره بردهاند، احساس رضایت بیشتری نسبت به شغل خود دارند. علاوه براین، این افراد اغلب اوقات عملکرد بالاتری پیدا کردهاند، حقوق بالاتری میگیرند و روند پیشرفتشان در شغل سریعتر است. او بازار را به خوبی میشناسد و رفتار با مشتری را به شما میآموزد. او چشماندازی بزرگ دارد و صحبت با او چشمانداز شما را بهبود میدهد. راه و چاه را از هم شناخته و شما را با برخی اشتباهات فاحشی آشنا میکند که نبایدانجام دهید. او شبکهای بزرگ از کارآفرینان، سرمایهگذاران و مسوولین دارد که میتوانید واقعاً روی آن حساب کنید. خود او شاید در مقام یک فرشته کسبوکار روی کسبوکار شما سرمایهگذاری کند. شما گاهاً درگیر امور اجرایی جزئی میشوید و از بحثهای کلانی مثل استراتژی کسبوکارتان دور میشوید. او کسبوکار را از بیرون میبیند و مسیر نادرست را گوشزد میکند. او فردی موفق است و باانگیزه. پس در مراحل سخت و خشن راهاندازی کسبوکار در ایران به شما روحیه و انگیزه مضاعف میدهد. به طور کلی، حوزهٔ فعالیتهای منتورها را در دو گروه میتوان دستهبندی کرد؛ حوزهٔ شغلی (حرفهای) و حوزهٔ روانشناختی. در حوزهٔ حرفهای، منتور تلاش میکند تا به عنوان یک مربی به فرد توصیههایی داشته باشد و رشد و عملکرد حرفهای او را بالا ببرد. در حوزهٔ روانشناختی، منتور به عنوان یک الگو ایفای نقش میکند و به عنصر الهامبخش تبدیل میشود. این دو حوزه معمولاً همزمان اتفاق میافتند و به فرد این امکان را میدهند تا علاوه بر پیشرفت در حوزهٔ شغلی، توازنی مناسب بین شغل و زندگی شخصی برقرار سازد. دانش، توصیه و منابعی که منتور با فرد در میان میگذارد بستگی به اهداف رابطهٔ منتورینگ دارد. ممکن است منتور اطلاعاتی را راجع به مسیر شغلی خود به فرد بدهد یا بیشتر به دنبال پشتیبانی کردن احساسی، دادن انگیزه و بازی کردن نقش یک الگو باشد. کمک به کشف ظرفیتهای جدید در هر شغل، هدفگذاری صحیح و شناسایی منابع نیز میتواند در حوزهٔ عملکرد منتور قرار بگیرد. نقش منتور با توجه به نیاز فرد تغییر میکند. بعضی از رابطههای منتورینگ بر اساس برنامههایی ساختاریافته و منظم بنا شدهاند که انتظارات و دستورالعملهای مشخصی دارند ولی بعضی دیگر، حالتی غیررسمی دارند. نکته: همانطور که انتخاب یک منتور خوب مزایای بسیاری در رُشد فردی و موفقیت کسبوکار شما دارد؛ به همان اندازه انتخاب یک منتور نا مناسب و بد تاثیر منفی خواهد داشت. توجه: منتورینگ خود به عنوان یک شغل نیز محسوب میشود، همانگونه که مشاوره مهم است! استفاده از تجربیات یک مشاور کسبوکار و فنی ارزش بسیاری دارد و بدون شک بسیار مهم خواهد بود. بنابراین منتورینگ متناسب با نوع استارتآپ و مشارکتی که در رُشد آن دارد هزینه یا سهمی را برای آن مشخص میکند و در توسعهٔ فردی و یا استارتآپ به وظایف خود عمل میکند. منتور فنی یا منتور کسبوکار!؟ لازم به ذکر است در رابطه با این موضوع روشن سازی شود که منتور کسبوکار میتواند راه و روش توسعهٔ کسبوکار شما را بهبود داده و برای شما مشاورههای مفیدی در این زمینه ارائه دهد. در مقابل منتور فنی میتواند با در نظر گرفتن مسیری که منتور کسبوکار برای شما مشخص کرده است راه و روش صحیح توسعهٔ محصول و استارتآپ شما را از لحاظ فنی ارائه دهد. یک منتور فنی میتواند صاحب نظر در حوزهٔ کسبوکار نیز باشد (این بستگی به تجربیات استارتآپی و کسبوکار آن خواهد داشت). بهرهگیری از هر دو نوع منتور در رشد فردی و استارتآپی شما بسیار موثر خواهد بود. خلاصهای از تعریف منتور منتور کسی است که همانند یک فانوس دریایی مسیر موفقیت و شکست را در هر شرایطی برای شما روشن سازد.
-
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 است و باید از همین کلاس برای این تابع استفاده کنید جز این با خطا مواجه میشوید. حاصل اجرای کد بالا بصورت زیر است:
-
6 امتیازقوانین و قالب اصول نگارشی در مرجع آی او استریم نسخهٔ 1.3.0 با توجه به اهداف مرجع، ارائه اسناد و محتوای معتبر رعایت اصول صحیح نگارشی در ترجمه، بازنشر و دیگر شرایط تولید محتوا نیاز است. بنابراین برای یادگیری شیوه نگارش و نحوهٔ صحیح نوشتن شما میتوانید شیوهٔ صحیح نوشتن و استفاده از علائم نگارشی را بیاموزید. متن زیر بر همین اساس آماده شده است و به مرور زمان تکمیل خواهد شد. توجه داشته باشید که شرایط زیر در سراسر سیستم نرمافزاری که شامل ماژولهای مختلفی چون (خبر، وبلاگ، پادکست، مستندات و ...) میشود. و عدم رعایت آن موجب عدم تایید و حتی لغو مقاله شما خواهد گردید. قبل از هر چیز به نمونه مثال زیر توجه کنید: عنوان آزمایشی متن (انتخاب سر نویس ۳) این متن آزمایشی است جهت نمایش یک پاراگراف از اندازه، چیدمان و دیگر موارد نگارشی که بدون اعمال هیچ گونه اندازه و سر نویسی نوشته شده است. برای اینکه پاراگرافهای زیب و یکدست در سرتاسر وب سایت داشته باشیم لازم است این قانون را رعایت نماییم. با توجه به اهداف مرجع ممکن است در آموزشهای شما در میان متن فارسی از متن انگلیسی یا کدهای برنامه نویسی استفاده کنید که برای مثال : کتابخانه STL یک کتابخانهٔ استاندارد کتابخانهای با نام iostream وجود دارد که با تکه کد #include <iostream> وارد میشود. برای حل این مشکل آن تگ < > کد را بر روی نوشته خود اعمال کنید#include <iostream>نتیجه به صورت یک تکه کد درون خطی نمایش داده میشود. در برخی موارد کاراکترهای خاص مانند C++ لازم است به صورت صحیح نوشته شود، معمولاً برای این کار آن را به صورت برعکس مینویسد اما این کار پیشنهاد نمیشود چرا که در بحث سئو تاثیر منفی خواهد گذاشت. ما برای حل این مشکل یک افزونه با عنوان L در نظر گرفته ایم که میتوانید کاراکترهای خود را انتخاب کنید و آن را بر روی آن اعمال نمایید. مثال : زبان برنامهنویسی C++ بدون اعمال تگ L مثال : زبان برنامهنویسی C++ تگ L اعمال شده است بنابراین نکاتی که همه ما به آن در تولید محتوا توجه میکنیم به صورت زیر هستند: قبل از شروع نگارش فارسی به «راست چین بودن» محیط ویرایشگر توجه میکنیم. برای نگارش صحیح فارسی از صفحه کلید استاندارد فارسی در ویندوز و گنو/لینوکس و مک استفاده میکنیم. این صفحه کلید به صورت پیشفرض در سیستم عامل گنو/لینوکس و مک نصب است. همینطور در نسخههای جدید ویندوز(از ۸ و به بعد) قابل فعالسازی در این سیستم عامل نیز است. در جملات از «میباشد» و «نمیباشد» استفاده نمیکنیم. معادل این کلمات به ترتیب «است» و «نیست» است. معادل واژهها بسیار مهم هستند، برای مثال کیبورد معادلش در فارسی صفحهکلید است و بهتر است از معادل فارسی استاندارد استفاده شود. در نگارش صحیح فارسی هیچگاه پیشوندها و پسوندها به صورت چسبیده نوشته نمیشوند. مثلاً: نمیشوند، میروم، جنگلها، پرندهگان، طراحیها، آنها و… همگی غلط هستند. برای نوشتن پیشوندها و پسوندها به صورت جداگانه، چنانچه حروف دو بخش به صورت پیشفرض احتمال چسبیدن به هم را داشته باشند برای جداسازی آنها از نیم فاصله استفاده میکنیم. مثلاً: نمیشود، میشود، توسعهدهنده، برنامهنویس، کسبوکار، میرسم، نمیخورم، گلهها، سبزهزارها، طراحیها، آنها و… همگی درست هستند. برای درج نیم فاصله در صفحه کلید استاندارد فارسی از Shift + Space که تقریبا در تمامی سیستمعاملها همین ترکیب را دارد استفاده میکنیم. در هنگام استفاده از کاراکترها (نظیر . ! ؟ ، … : ؛) باید به این نکته توجه کرد که آنها بدون هیچ فاصلهای به کلمه قبل از خود میچسبند. همینطور پس از آنها همیشه یک فاصله وجود دارد. چنانچه در متن از کلمات و یا عباراتی به زبانی دیگر استفاده شده بود حتماً در نخستین جایی که از آن کلمات و یا عبارات استفاده میکنیم باید معادل آن به زبان اصلی در درون پرانتز و بلافاصله پس از استفاده درج شود. مثلاً جملات زیر را در نظر بگیرید: پردازنده و رم (RAM) رایانه حتماً باید با هم سازگاری داشته باشند. زبان برنامهنویسی سیپلاسپلاس (++C) و فناوری کیوت کوئیک (Qt Quick). جی. کی. رولینگ (J. K. Rowling) خالق مجموعه داستانهای هری پاتر (Harry Potter) در مصاحبه اخیر خود با بی بی سی (BBC) از قصد خود در خصوص نوشتن سری جدیدی از داستانها خبر داد. نوروزبل (نؤرۊزبل) عید باستانی مردم خطه کاسپین است. به هیچ عنوان هیچ یک از اصطلاحات علمی را به فارسی نباید ترجمه و باز نشر کنیم، برای مثال : فناوری کیوت کوئیک (فناوری کیوت سریع) این غلط است. چنانچه در متن از کلمات و یا عبارتی به زبان فارسی استفاده شود که معادل غیر فارسی آن مفهوم را به شکل بهتری برساند، معادل غیر فارسی در هنگام نخستین استفاده در درون پرانتز نوشته میشود. مثلاً جملات زیر را در نظر بگیرید: راهنمای فایل (File Directory) یکی از روشهای رایج دسترسی به فایلها در سیستم عاملها است. طراحی رابط کاربری (UI) و تجربه کاربری (UX) دو مقوله جدا از هم هستند. چنانچه در متن از عبارات مخفف (فارسی و یا غیر فارسی) استفاده کرده باشیم در نخستین استفاده حتماً باید عبارت کامل در درون پرانتز درج شود. مثلاً جملات زیر را در نظر بگیرید: جهت استفاده از کتابخانههایی چون Qt باید (سطوح مقدماتی و متوسط زبان برنامهنویسی ++C) را به خوبی پشت گذاشته باشید. جَک JAC (Jangal Accounts)) سیستم یکپارچهای برای مدیریت حسابهای کاربری در سرویسهای گوناگون است که توسط شرکت جنگل ساخته شده و مورد استفاده قرار میگیرد. هرگاه در متن نیاز به درج توضیحات تکمیلی باشد از پرانتز استفاده میکنیم. مثلا: داتویوز (شرکت داتویوز (Dotwaves) با (مسئولیت محدود)) بزرگترین تولید کننده نرمافزار در شمال غرب کشور است. متن باید دارای افعالی یکپارچه باشد. این بدان معناست که فعلهای خبری متن همگی باید دارای یک نقش باشند. مثلاً اگر در حال نوشتن متن دستور پخت یک غذا باشیم، عبارت زیر غلط خواهد بود: برای طراحی یک نرمافزار تحت کیوت ابتدا باید محیط توسعه را نصب و راه اندازی کرد. سپس تحت زبان برنامهنویسی ++C و فناوری Qt Quick آن را طراحی و توسعه میدهیم. متن باید دارای لحنی یکپارچه باشد. مثلاً اگر در قسمتی از متن از زبان محاوره استفاده کردیم در جای دیگر نباشد از زبان کتابی صحبت کنیم. مثلاً ۲ جمله اول هر دو درست هستند ولی جمله سوم غلط است. قراره من در این آموزش برای شما بگم که چطور در رابطه با برنامهنویسی سطح پایین دانشتان را ارتقا دهید! (غلط) قراره من در این آموزش برای شما بگم که چطور در رابطه با برنامهنویسی سطح پایین دانشتون رو ارتقا بدین (صحیح) قرار است من در این آموزش برای شما نحوه ارتقا دانشتان در برنامهنویسی سطح پایین را توضیح دهم. (صحیح) در متن هرجا که لازم باشد به مهم بودن بخشی خاص اشاره شود آن را بلد (Bold) میکنیم. مثال: آوردن ماشین حساب در امتحان ریاضی مهندسی ممنوع نیست. در پاراگرافهای موجود در متن باید سعی شود که تا جایی که امکان دارد در جملات پشت سر هم از کلمات یکسان استفاده نشود. مثلاً متن زیر به خاطر تکرار کلمات یکسان (در این مثال جاوا اسکریپت و است) متن زیبایی نیست: جاوا اسکریپن یک زبان پر طرفدار است. جاوا اسکریپت پر کاربرد ترین زبان در لایه رابط کاربری است. جاوا اسکریپت ملقب به نام «JS» است. چنانچه در متن بخواهیم یکپارچگی عبارتی را نشان دهیم آن را درون «» قرار میدهیم. این کار برای سهولت خواندن متن انجام میشود. چنانچه در متن بخواهیم که جملهای را نقل قول کنیم آن را در درون «» قرار میدهیم. اگر متن نقل قول شده بیشتر از یک جمله بود به غیر از استفاده از علامت فوق از فونتی کوچکتر و یا اتالیک (Italic) استفاده میشود. البته برای راحتی کار و یکسان بودن بهتر است بر روی دکمه قالب روی ویرایستار کلیک کرده و از بخش بلوک (بلوک نقل قول) را انتخاب کنید. در محیط وب اگر در متن از کلمات و یا عباراتی استفاده شود که توضیحاتی مفصل از آن در جایی دیگر موجود باشد، آن کلمات و یا عبارات را به همان جایی که توضیحات مفصل آن وجود دارد پیوند (Link) میکنیم. در هنگام لینک کردن عبارات در وب چنانچه لینک مورد نظر خارج از آدرسی خارج از سایت خودمان باشد حتماً باید لینک در تبی (Tab) جداگانه باز شود. در هنگام لینک کردن عبارات حتماً برای آن عنوانی (Title) در نظر میگیریم. این عنوان زمانی که ماوس بر روی لینک قرار بگیرد نمایش داده میشود. این عنوان باید متنی باشد که توضیحات بیشتر را در مورد لینک بدهد. مثلاً اگر کلمه رشت را به صفحه ویکیپدیا فارسی رشت لینک کردهایم یکی از عنوانهای مناسب میتواند «در مورد رشت در ویکیپدیا فارسی بیشتر بخوانید.» باشد. چنانچه در محیط وب متنی را از جایی نقل و قول (و یا کپی) کردیم حتماً باید در صفحه خودمان به آن مطلب لینک بدهیم. این لینک میتواند درون متنی باشد و یا اینکه در انتهای متنمان به عنوان منبع ذکر شود. در وب چنانچه مایل به استفاده از تصاویر در متنمان بودیم حتماً مسأله اندازه (حجم)آن را در نظر میگیریم. معمولاً از تصاویر با حجم پایین در درون متن استفاده میشود و اگر لازم بود که خواننده به تصویر با اندازه اصلی دسترسی داشته باشد معمولاً این تصویر به تصویر کم حجم موجود در متن لینک میشود. در نوشتن مطالب از فونتهای عجیب و غیر استاندارد و یا اندازههای بسیار بزرگ/کوچک استفاده نمیکنیم. هر چند فونتهای استاندارد بر روی ویرایستار تعبیه شده است اما همینطور حتیالامکان رنگها و فونت و اندازههای پیشفرض را تغییر نمیدهیم. (مگر اینکه واقعاً در مواردی خاص نیاز به این کار باشد.) کاراکترهای اعداد در زبان فارسی با زبانهایی نظیر انگلیسی و عربی کاملاً متفاوت است. در نگارش فارسی فقط و فقط از کاراکترهای فارسی اعداد استفاده میکنیم. این کاراکترها ۱۲۳۴۵۶۷۸۹۰ هستند. تنها زمانی مجاز به استفاده از کاراکترهای اعداد انگلیسی و عربی هستیم که در حال ذکر معادلهای غیر فارسی باشیم. مثلا: فایل ام پی تری (MP3) یکی از فرمتهای رایج موسیقی است. ام فور (M4) یکی از اسلحههای رایج بازی کانتر است. در لیستها اعداد شمارهگذاری را به صورت دستی وارد نمیکنیم! برای این کار از ابزار تعبیه شده در محیط نگارش استفاده میکنیم. (همینطور در لیستهای غیر مرتب نیز کاراکترهای شروع کننده پاراگراف را دستی وارد نمیکنیم.) در نگارش جدید فارسی از ی مالکیت استفاده نمیشود. مثلاً عبارات زیر همگی غلط هستند: خانهٔ ما علاقهٔ مفرط پذیرندهٔ جدید برخی از کاراکترها نظیر ی و ک در فارسی متفاوت با عربی است. در نگارش فارسی دقت میکنیم که از کاراکترهای عربی استفاده نکنیم. برای خوانایی متن و بالا بردن درک مطلب از پاراگراف استفاده میکنیم. هر پاراگراف متشکل از یک یا چند جمله است که نزدیکی محتوایی دارند. پس از اتمام پاراگراف فارغ از اینکه جمله نهایی در کجا به پایان رسیده است به خط بعدی میرویم. پس از انتشار مطلب در محیط وب چنانچه پس از گذشت مدتی طولانی قسمتی از متن با حقایق روز متفاوت بود بر روی آن خط میکشیم. همچنین اگر لازم بود بخشی را به عنوان اصلاحیه اضافه میکنیم. متن زیر را در نظر بگیرید: سیستم عامل مَک او اِس ایکس (Mac OS X) در حال حاضر جدیدترین سیستم عامل ساخته شده توسط شرکت اپل (Apple) است. یکی از ویژگیهای جدید افزوده شده به این سیستم عامل ظاهر بسیار زیبای آن است. حال این متن را پس از گذشت چند سال به شکل زیر تغییر میدهیم: سیستم عامل مَک او اِس ایکس (Mac OS X) در حال حاضر جدیدترین سیستم عامل ساخته شده توسط شرکت اپل (Apple) است. (در حال حاضرسیستم عامل مَک او اِس سییرا (macOS Sierra) جدیدترین سیستم عامل اپل است.) یکی از ویژگیهای جدید افزوده شده به این سیستم عامل ظاهر بسیار زیبای آن است. اگر در متن در حال توضیح موضوع خاصی هستیم بهتر است که در جاهایی از معادلهای مترادف آن موضوع استفاده کنیم. مثلاً اگر در حال معرفی یک نرمافزار هستیم میتوانیم برای اشاره به آن از کلماتی نظیر نرم افزار، برنامه، اپ و اپلیکیشن استفاده کنیم. به طور کلی در متن از کلمات و عباراتی که از زبان دیگری آمدهاند استفاده نمیکنیم ولی این مسأله نباید باعث کاهش خوانایی و مفهوم متن شود. ساده نویسی یکی از اصول اصلی نگارش است. اینکه از چه مجموعه از کلمات و عباراتی در متنمان استفاده کنیم بستگی به سطح خوانندگانمان دارد. مثلاً اگر در حال نوشتن یک متن برای برنامه نویسان هستیم به راحتی میتوانیم از کلماتی نظیر UX و UI و.. استفاده کنیم ولی استفاده از این کلمات در یک متن عمومی توصیه نمیشود و در صورت استفاده حتماً باید معانی آنها به صورت کامل در درون پرانتز و یا پاورقی درج شود. روش ارسال کد در قالب مناسب برای درک بهتر مطلب توسط ابزار <> در صورتی که مقاله، سند یا مطلب خاصی را منتشر میکنید که دارای تکه کدی است آن را در داخل تگ کد قرار میدهیم که نمونه مثالهای آن به صورت زیر نمایان خواهند شد: نمونه مثال خروجی کد C //A Hello World! program in C. #include <stdio.h> int main() { // printf() displays the string inside quotation printf("Hello, World!"); return 0; } نمونه مثال خروجی کد ++C // A Hello World! program in C++. #include <iostream> using namespace std; int main() { cout << "Hello, World!"; return 0; } نمونه مثال خروجی کد در Java //A Hello World! program in Java. public class HelloWorld { public static void main( String[] args ) { System.out.println( "Hello World!" ); System.exit( 0 ); //success } } نمونه مثال خروجی کد در JavaScript // A Hello World! program in JavaScript. const btn = document.getElementById('button'); btn.addEventListener('click', function() { alert('Hello World!'); نمونه مثال خروجی کد در QML // A Hello World! program in QML. import QtQuick 2.0 Rectangle { id: page width: 320; height: 480 color: "lightgray" Text { id: helloText text: "Hello world!" y: 30 anchors.horizontalCenter: page.horizontalCenter font.pointSize: 24; font.bold: true } } نمونه مثال خروجی کد در PHP // A Hello World! program in PHP. $text = "Hello, World!"; $x = 5; $y = 4; echo "<h2>" . $text . "h2><br>"; echo $x + $y; نمونه مثال خروجی کد در Node.JS // A Hello World! program in Node.JS const express = require('express') const app = express() app.get('/', (req, res) => res.send('Hello World!')) app.listen(3000, () => console.log('Example app listening on port 3000!')) نمونه مثال خروجی کد در CSS p { text-align: center; color: red; } نمونه مثال خروجی کد در #C // A Hello World! program in C#. using System; namespace HelloWorld { class Hello { static void Main() { Console.WriteLine("Hello World!"); // Keep the console window open in debug mode. Console.WriteLine("Press any key to exit."); Console.ReadKey(); } } } نمونه مثال خروجی کد در Ruby #!/usr/bin/ruby print "Hello, World!\n" نمونه مثال خروجی کد در Python # This program prints Hello, world in Python! print('Hello, world!') و اما یک نکتهی اساسی در نشر محتوا این است که برای مخفی نگه داشتن بخشی از پاسخها که نیاز نیست برای همه قابل نمایش باشد از گزینه اسپویلر یا همان مخفی کردن با علامت چشم بر روی ادیتور استفاده میکنیم تا محتوا به صورت همین نمونه نمایان شود.
-
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 امتیازاین چشمانداز احتمالاً برای دوستداران کتابخانهٔ قدرتمند Qt و طرفدارانش جذاب باشد! بنابراین من سعی کردهام تا نتایج پست رسمی کیوت را در رابطه با چشمانداز فنی برای آیندهٔ کیوت نسخهٔ ۶ است در اختیار شما قرار دهم. تقریباً ۷ سال پیش کیوت نسخهٔ ۵.۰ منتشر شد! از آن زمان بسیاری از چیزها در دنیای اطراف ما تغییر پیدا کرده است. و اکنون وقت آن رسیده است که چشمانداز جدیدی را از نسخهٔ جدیدتر تعریف کنیم. بنابراین در این پست ما به معرفی مهمترین مواردی که به کیوت ۶ مرتبط است را میپردازیم. به نقل از مدیر فنی کیوت Lars Knoll، کیوت ۶ دقیقاً ادامهٔ کارهایی است که در نسخهٔ ۵ انجام داده شده است. بنابراین توسعه باید به گونهای باشد که کاربران نباید اذیت شوند. اما نسخهٔ جدید میتواند یک آزادی بالاتر را در اجرای ویژگیهای جدید، عملکرد و پشتیبانی بهتر از شرایط امروز و فردا از آنچه در حال حاضر میتوان در سری ۵ داشته باشیم را به ما خواهد داد. همانطور که جزئیات بیشتر در زیر شرح داده شده است، کیوت ۶ هدف زیادی از سازگاری با نسخهٔ قبلی خود یعنی کیوت ۵ را خواهد داشت. همچنین ما در حال توسعه روی نسخهٔ ۵ نیز هستیم که قصد داریم برخی از ویژگیهای کیوت ۶ را در نسخههای کیوت ۵.۱۴ و کیوت ۵.۱۵ LTS معرفی کنیم. بنابراین با ثابت نگهداشتن ویژگیها در کیوت ۵.۱۴، بیشترِ تمرکزِ تحقیق و توسعه به سمت کیوت ۶ تغییر خواهد یافت. بنابراین انتظار میرود کیوت ۶ تا پایان سال ۲۰۲۰ آماده شود. قبل از اینکه همه به چیزهای جدید بپردازیم، بیایید برخی از ارزشهای پایه از هستهٔ اصلی کیوت را برای کاربران خود یادآوری کنیم تا چیزهایی که نمیخواهیم تغییر کنند را تعریف کنیم. چه چیزی Qt را برای کاربران ما ارزشمند میکند؟ کیوت محصولی است که در بازارهای مختلفی مورد استفاده قرار میگیرد، ارزشهای اصلی در هستهٔ کیوت برای مشتریان و کاربران ما عبارتند از: ماهیت چند-سکویی آن، به کاربران این امکان را میدهد تا برنامههای خود را با استفاده از این فناوری به تمامی سیستمعاملهای رو میزی، موبایل و سیستمهای تعبیه شده (اِمبِدها) مستقر کنند. مقایس پذیری آن از دستگاههای کم مصرف و یک منظوره تا برنامههای دسکتاپ پیچیده و یا سیستمهای متصل شده. رابطهای برنامهنویسی و ابزارها و مستندات در سطح جهانی، ایجاد برنامهها را سادهتر میکند. حفظ، ثبات (پایداری) و سازگاری، امکان حفظ بانک بزرگی از کدها با حداقل تلاش برای نگهداری آنها. یک اکو سیستم بزرگ توسعهدهنده با بیش از ۱ میلیون کاربر. یک نسخهٔ جدید از کیوت باید خواستههای محصول ما را مطابق با نیازهای بازار تنظیم کند، و در عین حال پنج ویژگیِ بالا را به خوبی حفظ کند. بازار دسکتاپ، ریشهٔ پیشنهادات و یک بازار قوی و مهم برای کیوت است؛ در این مرحله است که بیشترین تماسها با ما و در انجمنهای کیوت از طرف کاربران صورت میگیرد که باید سالم نگه داشتن و رشد آن مهم باشد. بزرگترین بخش از رشد کیوت نیز مربوط به دستگاههای تعبیه شده و متصل شده میباشد؛ صفحات نمایش لمسی به تعداد تصاعدی در حال افزایش است که در کنار آن افزایش قیمت سختافزار برای این دستگاهها وجود دارد. چیپستهای کم مصرف، میکروکنترلرها، همراه با صفحه نمایش لمسی به اندازههای کوچک در همه جا استفاده میشوند. بسیاری از این دستگاهها عملکردی نسبتاً سادهای دارند، اما به رابط کاربری صیقلی و صافی نیاز دارند. بنابراین حجم زیادی از این دستگاهها ایجاد میشود و ما باید اطمینان حاصل کنیم که میتوانیم با ارائهٔ خود آن فضا را هدف قرار دهیم تا بتوانیم قوبل مقیاس پذیری خود را عملی کنیم. در عین حال، رابطهای کاربری در طیف دستگاهها همچنان به افزایش پیچیدگی ادامه میدهند که شامل هزاران صفحه مختلف و برنامههای بسیاری است. ادغام عناصر سه بعدی و دو بعدی در یک رابط کاربری مشترک خواهد بود که در کنار آن استفاده از واقعیت افزوده و مجازی نیز وجود خواهد داشت. عناصر هوش مصنوعی بیشتر در حوزهٔ برنامهها و دستگاهها مورد استفاده قرار میگیرد و ما نیاز به روشهای آنسان برای ادغام با آنها داریم. رشد شدید تعداد دستگاههای متصل به هم و همچنین الزامات بسیار بالاتر در تجربهکاربر باعث میشود تا برای ساده سازی ایجاد برنامهها و دستگاهها، روی ابزارهای کلاس جهانی تمرکز کنیم. هماهنگ سازی و ادغام طراحان UX در گردش کار توسعه یکی از اهداف است؛ اما بسیاری از زمینههای دیگر وجود خواهد داشت که ما باید برای ساده سازی زندگی کاربران تلاش کنیم. کیوت ۶ یک نسخهٔ اصلی و جدید برای Qt خواهد بود؛ هدف اصلی با چنین نسخهٔ اصلی و جدید، آماده سازی کیوت برای شرایط مورد نیاز در سال ۲۰۲۰ و بعد از آن، تمیز کردن کدهای پایهٔ ما و حفظ آسانتر است. به همین ترتیب تمرکز روی آن مواردی خواهد بود که نیاز به تغییرات معماری در کیوت دارند و بدون شکستن برخی از سازگاریها با سریهای کیوت ۵ قابل انجام نیست. در زیر برخی از تغییرات اساسی که ما باید در کیوت ایجاد کنیم برای مناسبتر کردن آن برای سالهای آینده ارائه شده است. نسل بعدی کیواِماِل (QML) زبان QML و فناوری Qt Quick فناوریهای اصلی رشد سالهای گذشتهٔ ما بوده است. روشهای بصری ایجاد واسطهای کاربری با استفاده از آن فناوریها نقطه فروش بی نظیری از پیشنهاد ما است. اما QML، همانطور که برای کیوت ۵ ایجاد شده است، دارای تعداد زیادی تغییرات ناگهانی و محدودیت است. این به نوبهٔ خود به این معنا است که، امکان پیشرفتهای چشمگیری وجود دارد که ما قصد داریم با کیوت ۶ آنها را پیاده سازی کنیم. معرفی وابستگی زیاد به نوع (strong typing)، وابستگی کم به نوع (weak typing) امکان ایجاد تغییر در کدها را برای کاربران ما سخت میکند. سیستمی از مدل وابستگی زیاد به نوع امکان پشتیبانی از این تغییرات را در محیطهای یکپارچهٔ توسعهٔ نرم افزار و سایر ابزارها به کاربران میدهد و به طور چشمگیری حفظ و نگهداری از آنها را راحت میکند. همچنین، قادر به تولید کدهای اجرایی هرچه بهتر و با سربار کمتر خواهیم بود. اعمال JavaScript به عنوان یک ویژگی اختیاری، با توجه به این موضوع، داشتن یک موتور کامل جاوا اسکریپت هنگام استفاده از QML میتواند مشکلات را پیچیدهتر کند و به خصوص هنگام هدف قرار دادن سختافزار کم مصرف مانند میکرو کنترلرها یک مشکل اصلی محسوب میشود. اما در بسیاری از موارد استفاده از آن بسیار مفید است. حذف نسخه سازی QML، با ساده کردن برخی از قوانین بررسی و جستجو و تغییرات در برخی از خواص میتوانیم نیاز به نسخه را در QML حذف کنیم. این به نوبهٔ خود منجر به ساده سازیهای زیاد در موتور کیواماِل میشود. حجم کار در حفظ فناوری کیوت کوئیک و سادهتر کردن استفاده از QML و Qt Quick را برای کاربران بسیار سادهتر خواهد کرد. حذف ساختار دادههای تکراری بین QObject و QML در حال حاضر، برخی از ساختار دادهها بین meta-object و QML کپی و تکرار میشوند و عملکرد (کارایی و پرفرمنس) را در استارتاپ برنامه کاهش میدهد و باعث افزایش مصرف حافظه نیز میگردد. بنابراین با متحد کردن ساختارهای دادهها، ما قادر خواهیم بود بخشی اعظمی از آن را حذف کنیم. خودداری کردن از ساختارهای داده تولید شده این مربوط به نکتهٔ قبل است، جایی که در حال حاضر بسیاری از ساختارهای داده تکراری در زمان اجرا تولید میشوند. باید تولید اکثر آنها در زمان کامپایل کاملاً امکانپذیر باشد. پشتیبانی از کامپایل QML برای بهرهوری از کدهای بومی C++، با وابستگی زیاد به نوع و قوانین جستجوی سادهتر، میتوانیم QML را به کدهای بومی C++ تبدیل کنیم که نتیجهٔ آن به طور قابل توجهی عملکرد زمان اجرا را افزایش میدهد. پشتیبانی از پنهان کردن جزئیات اجرا، روش و خصوصیات «خصوصی» یک نیاز طولانی مدت است تا بتوانید دادهها و عملکردها را در اجزای QML پنهاد کنید. هماهنگسازی و ادغام بهتر ابزارها، مدل کدهای ما غالباً برای QML ناقص است و باعث میشود که تغییر مکان و خطاها را در زمان کامپایل غیر ممکن کند. با تغییرات فوق، میتوان تشخیص کامپایلر را ارائه داد که بتواند با C++ و همچنین پشتیبانی از آن پالایشِ کدها را بهبود بخشد. نسل بعدی گرافیکها بسیاری از موارد در حوزهٔ گرافیک در نسخهٔ کیوت ۵ تغییر یافتهاند. این باعث میشود که برای حفظ رقابت و توسعه در پُشته انجام شود. با کیوت ۵، ما از رابطهای برنامهنویسی OpenGL را برای گرافیکهای ۳ بعدی استفاده کردیم. از آن زمان به بعد، میزبانی از رابطهای برنامهنویسی جدید نیز تعریف شده است. بنابراین وُلکان (Vulkan) جانشین مشخصی برای OpenGL در لینوکس است، اپل نیز مِتال (Metal) را تحت فشار قرار داد تا آن را جایگزین کند و مایکروسافت DirectX را دارد. این بدان معنی است که کیوت در آینده مجبور است به صورت یکپارچه با تمام رابطهای برنامهنویسی کار کند. برای اینکه این ویژگی امکانپذیر باشد، باید یک لایهٔ جدید که رابطهای برنامهنویسی گرافیکی را انتزاع میکند مانند (QPA برای ادغام سکو) به نام رابط سختافزاری RHering تعریف شود. ما نیز باید زیر ساختهای ارائه شدهٔ خود (Qt Quick Scenegraph، QPainter و پشتیبانی ۳ بعدی) را در بالای آن لایه قرار دهیم. مجموعهٔ رابطهای برنامهنویسی گرافیکی مختلف باعث میشود که ما از زبانهای مختلف سایهزنی پشتیبانی کنیم. ابزار Qt Shader به عنوان یک ماژول به ما کمک میکند تا سیستمِ سایهزنی را به صورت همزمان (کراس-کامپایل) و در زمان اجرا کامپایل کنیم. بحث ۳ بعدی نقش مهم و مهمتری را ایفا میکند، و پشتیبانی فعلی ما یک راه حل یکپارچه برای ایجاد رابط کاربری (UI) هایی که حاوی هر دو عنصر ۲ و ۳ بعدی باشد را ندارد. ادغام QML با محتوا از Qt3D و یا Qt 3D Studio در حال حاضر کار دشواری است و باعث سرریز شدن برخی از کاراییها و عناصر نمایشی میشود. علاوه بر این همگام سازی انیمیشنها و انتقالها بر روی یک فریم با سطح فریم بین محتوای ۲ و ۳ بعدی غیر ممکن است. ادغام جدید محتوای ۳ بعدی با فناوری کیوت کوئیک با هدف حل این مشکل ایجاد شده است. در این حالت، یک سیستم ساخت (رندر) کامل و جدید به شما امکان میدهد تا محتوای ۲ و ۳ بعدی را با هم ظبط کنید. با این کار QML به زبان UI تعریف و تبدیل میشود که سه بعدی هستند و نیاز به فرمت UIP برطرف میشود. ما یک پیشنمایش از کیوت کوئیک جدید با پشتیبانی سه بعدی در حال حاضر با کیوت ۵.۱۴ ارائه میدهیم که اطلاعات بیشتر در یک پست جداگانه ارائه خواهد شد. سرانجام پشتهٔ گرافیکی جدید نیاز به پشتیبانی از خط لولهٔ برای چیزهای گرافیکی هستند که این امکان را میدهد تا آنهایی که در زمان کامپایل برای سخت افزار مورد نظر تهیه شدهاند آماده کرده و از موارد مورد نظر استفاده کند. برای مثال، فایلهای PNG را به بافتهای فشرده تبدیل میکند و بسیاری از آنها را به بافت (Texture) تبدیل کند. سایهها و مِشها را به قالبهای باینری بهینه شده و موارد دیگر تبدیل خواهد کرد. همچنین هدف ما این است که یک موتور متحد برای پوسته/ظاهر در کیوت ۶ ارائه دهیم که به ما این امکان را میدهد تا از نظر ظاهری و احساسات بر روی دسکتاپ و موبایل آن را بر روی هر دو فناوری کیوت ویجت و کیوت کوئیک ارائه کنیم. ابزار یکپارچه و سازگار ابزارهای گرافیکی ما برای ساخت رابطهای کاربری به دو بخش با استودیو کیوت ۳ بعدی (Qt 3D Studio) و استودیو طراحی کیوت (Qt Design Studio) تقسیم بندی شدهاند. علاوه بر آن، استودیو ۳ بعدی اند;ی از بقیه کیوت جدا شده است که باعث میشود کمی بیشتر سعی بر آن شود! ابزارهای طراحی نیز به ایجاد محتوا مانند، محتوای ساخته شده در Photoshop، Sketch، Illustrator، Maya، 3DsMax و دیگر موارد ادغام شده است. ابزارهای توسعه به توجه زیادی برای تمرکز دارد تا بتوانیم بهترینها را در پشتیبانی کلاس برای QML، C++ و پایتون ارائه دهیم. یک ابزار متحد و یکپارچه این اجازه را میدهد که یک طراح UX بتواند از قابلیتهای طراحی در کیوت کریتور استفاده کند و طراحان میتوانند از ویژگیهای ابزارهای توسعهدهنده مانند تهیه یک پروژه یا آزمایش روی یک دستگاه بهرهمند شوند. ابزار ساخت QMake به عنوان ابزار ساخت در کیوت ۵ مورد استفاده قرار میگیرد که تعداد زیادی تغییرات ناگهانی و محدودیتها خواهد دارد. برای کیوت ۶، هدف ما این است که CMake را به عنوان سیستم ساخت ثالث و استاندارد برای ساخت خود کیوت استفاده کنیم. چرا که سیمیک تاکنون پرکاربردترین سیستم ساخت در جهان برای سیپلاسپلاس بوده است و ادغام هرچهبهتر آن کاملاً مورد نیاز است. البته پشتیبانی از QMake ادامه خواهد داشت، اما آن را توسعه نخواهیم داد یا از آن برای ساخت فریمورک کیوت استفاده نخواهیم کرد. بهبود رابطهای برنامهنویسیC++ سیپلاسپلاس طی سالهای گذشته تغییرات بسیار زیادی کرده است؛ در حالی که ما مجبور بودیم کیوت ۵.۰ را روی سیپلاسپلاس ۹۸ پایهگذاری کنیم. اما اکنون میتوانیم به سیپلاسپلاس ۱۷ برای پایهگذاری کیوت ۶ اطمینان کنیم. این بدان معنی است که C++ عملکرد بسیار بیشتری را نسبت به زمان توسعه و اجرای کیوت ۵ که در دسترس نبود ارائه خواهد کرد. هدف ما با کیوت ۶ بهتر شدن با یکپارچهسازی و ادغام قابلیتها بدون از دست دادن پشتیبانی و سازگاری از روشهای پیشین (رو به عقب یا همان backward compatibility) است. برای کیوت ۶، هدف ما این است که برخی از قابلیتهای معرفی شده با QML و فناوری Qt Quick را از طرف C++ در دسترس قرار دهیم. بنابراین ما در تلاش برای معرفی یک سیستم خاص برای QObject و کلاسهای مرتبط هستیم. موتور اتصال دهنده را از QML در هستهٔ کیوت ادغام میکنیم و آن را از سیپلاسپلاس در دسترس قرار میدهیم. این سیستم خاص از موتور اتصال به کاهش قابل توجهی در سربار زمان کار و مصرفه حافظه در اتصال منجر میشود و آنها را برای همهٔ قسمتهای Qt، نه تنها Qt Quick قابل دسترس میکند. پشتیبانی از زبان با کیوت ۵.۱۲، پشتیبانی از پایتون معرفی شده است. همچنین مرورگر را به عنوان پلتفرم جدید از طریق کیوت برای وِب اسمبلی اضافه کردهایم. پس از انتشار کیوت ۶.۰ نگهداشتن و گسترش بیشتر بر روی سطح چند-سکویی بخش مهمی از اهداف و مسیر توسعهٔ سریهای کیوت ۶ خواهد بود. سازگاری با کیوت ۵ و افزایش سازگاریها و بهبودها سازگاری با نسخههای قدیمیتر بسیار مهم است، بنابراین وقتی کیوت ۶ را توسعه میدهیم یک نیاز اساسی محسوب میشود. توسط چهارچوب کیوت میلیونها خط کد نوشته شده است و هرگونه تغییرات در ناسازگاری که انجام شود هزینهای را برای کاربران خواهد داشت. علاوه بر این، کار بیشتری برای تغییرات در کیوت ۶ نیاز است تا کاربران کم کم با آن سازگار شوند که منجر به هزینههای بیشتر از طرف تیم توسعهٔ کیوت برای حفظ آخرین نسخه کیوت ۵ خواهد بود. به این ترتیب، ما باید به فکر جلوگیری از ساطع شدن خطاهای احتمالی در زمان کامپایل و یا زمان اجرا برای کاربران میشود باشیم. در حالی که ما نیاز به حذف بخشهایی از کیوت خواهیم داشت، باید اطمینان حاصل کنیم که کاربران ما از عملکرد مورد نیاز خود برخوردار هستند. این بدان معنا است که کلیدهایی مانند Qt Widgets و سایر قسمتهایی که توسط بخش بزرگی از کاربران ما مورد استفاده قرار میگیرد، در دسترس باشد. ما در حال برنامهریزی برای افزایش بسیاری از پیشرفتها در کلاسهای اصلی و عملکردی هستیم که در سری کیوت ۵ نتوانستیم انجام دهیم. هدف این است که سازگاری کامل منبع را حفظ کنیم، اما از آنجا که میتوانیم سازگاری باینری را با کیوت ۶ بشکنیم، میتوانیم پاکسازیها و اصطلاحات کاملاً زیادی را انجام دهیم که در کیوت ۵ نمیتوانستیم آن را عملی کنیم. با این وجود، ما باید به جلو پیش برویم و برخی از پاکسازیها که در کیوت ۵ در مورد کلاسها، توابع و یا ماژولها عنوان شده بود را در کیوت ۶ به طور کامل اعمال کنیم. این کار باعث میشود ما روی مبنای کدگذاری شدهٔ فعلی تمرکز بیشتر و بهتری داشته باشیم. با این حال، انتقال به دور از قسمتهای منسوخ شده باید تا حد امکان ساده باشد و کاربران ما میتوانند با استفاده از کیوت ۵.۱۵ «پشتیبانی بلند مدت» به صورت ایدهآل این کار را انجام دهند. هدف ما باید این باشد که کیوت ۶ به اندازهٔ کافی با نسخهٔ ۵.۱۵ سازگار باشد تا فرد بتواند به راحتی یک بخش اعظمی از کد خود را حفظ کند، به طوری که کد آن در هر دو نسخهٔ ۵ و ۶ قابل کامپایل باشد. بازار و ساختار فنی محصول علاوه بر بهبود چهارچوب و ابزارهای کیوت، هدف ما ایجاد بازار جدیدی برای قطعات و ابزارهای توسعه است. این بازار بر روی کاربران مستقیم ما متمرکز خواهد شد که برنامههای کاربردی و دستگاههای تعبیه شده را طراحی و توسعه میدهند؛ به این ترتیب این یک مرکز تجمع اصلی برای اکو سیستم کیوت خواهد بود که این امکان را به شخص ثالث میدهد تا نسخههای اضافی خود را در کیوت منتشر کنند و هم محتوای رایگان و تجاری را که برای آن هزینه پرداخت میکنند. کیوت طی سالهای گذشته رشد بسیار زیادی داشته است، تا جایی که ارائهٔ نسخهٔ جدید آن یک کار مهم است. با استفاده از کیوت ۶ فرصتی برای بازسازی محصولات ارائه شده ما وجود دارد و یک محصول اصلی و کوچکتر که شامل چهارچوبها و ابزارهای اساسی است. ما از بازار استفاده خواهیم کرد تا چهارچوب و ابزارهای اضافی خود را ارائه دهیم، نه به عنوان یک بستهنرمافزاری وابسته به کیوت! چشمانداز فنی تا اولین نسخهٔ کیوت ۶ تکامی خواهد یافت. اگرچه معتقد هستیم که این سند بسیاری از مهمترین نکات را برای نسخهٔ بعدی کیوت معرفی میکند اما مطمئناً کامل نیست. اگر شما هم ایدهٔ دیگری دارید میتوانید آن را با ما در میان بگذارید.
-
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 امتیازبا سلام وقت بخیر, در این مطلب میخواهیم در مورد روش کارکرد پیام رسان ها بیشتر بدانیم و با یکدیگر کد یک پیام رسان ساده را پیاده و بررسی کنیم. طرز کار کرد پیام رسان در نظر داشته باشید که هر پیام رسانی که بر ساختار ها پیاده شده باشد از دو قسمت تشکیل شده است. نرم افزار اصلی برای مدیریت درخواست ها (سرور) نرم افزار برای کاربران (کاربر) به نرم افزار اولی سمت SERVER خواهیم گفت و به بعدی سمت CLIENT خواهیم گفت. روم یا تالار گفتگو ما تنها یک اتاق برای گفتگو در نظر میگیریم و هر کاربری که به سرور متصل شود را در همان تالار اضافه خواهیم کرد. تالار های گفتگو صرفا برای تقکیک سازی ارسال و دریافت ها و محدود کردن بازه ی کاربران مورد نظر... (ممکن است یک کاربر در چند اتاق بطور همزمان باشد.) سیستم های پیام رسان پیشرفته تر مانند تلگرام و ... تالار های زیادی را شامل می شوند. (هر کاربر خودش در کانال و گروه های مختلفی عضو است که هر کدام از آنها یک کانال متفاوت محسوب می شوند.) * دقت شود که منظور از کانال صرفا یک اتاق یا تالار گفتگو است و منظور کانال ارتباطی و پروتکل نیست. نرم افزار اصلی نرم افزار اصلی وظیفه دارد تا تمام کاربرانی که وارد تالار شده اند را به یاد داشته باشد و هر لحظه اماده دریافت درخواست هایی از طرف کاربرانش باشد. و پیام هایی را که از کاربران دریافت می کند برای تمامی کاربران دیگر هم ارسال کند که بسته به خلاقیت و نیاز می تواند هر یک از این بخش ها متفاوت طراحی شود. نرم افزار اصلی باید از قبل اجرا شده باشد. تا کاربران دیگر با استفاده از نرم افزار مخصوص به خودشان بتوانند به سرور متصل شوند و ارسال و دریافت داشته باشند. در نظر داشته باشید که اگر در نرم افزار اصلی اختلالی پیش بیایید و متوقف بشوند. قطا برای تمام کاربران مشکل پیش می آید. مگر اینکه از پایگاه های داده ی داخلی استفاده کرده باشند. (با خلاقیت می توان به گونه های متفاوتی چنین ساختاری را پیاده کرد) نرم افزار کاربران این نرم افزار جذاب ترین بخش است چرا تمام قابلیت هایی را که در اختیار کاربر قرار می دهیم را مستقیما طراحی می کنیم. در نظر داشته باشید که هر چیزی که در این نرم افزار طراحی می شود باید در نرم افزار اصلی پشتیبانی شوند... بنابراین اگر این دو بخش توسط دو فرد یا دو گروه مجزا طراحی می شوند آنها باید توسط داکیومنت ها و جلساتی به نظرات مشابه ای رسیده باشند. (اگرچه اینها تخصص و وظیفه ی تحلیلگر سیستم است! نه بطور همزمان وظیفه توسعه دهنده و برنامه نویس نرم افزار) پیاده سازی یک نمونه اکنون در نظر داریم تا با استفاده از ساختار کتابخانه BoostAsio پروژه ای را با نام BoostAsioChat ایجاد کنیم که در آن می خواهیم یک پیام رسان با حداقل ترین امکانات پایه طراحی کنیم که بیشتر جنبه شخصی و تفریحی دارد. زیرا از ساختار های استاندارد و ایمن و کاربری کاملا بدور است! (می توانید خودتان توسعه دهید و آنرا جالب تر بسازید) ساختار نرم افزار اصلی و سرور را به این صورت تعریف می کنیم : typedef deque<message> messageQueue; class participant { public: virtual ~participant() {} virtual void deliver(const message& messageItem) = 0; }; typedef shared_ptr<participant> participantPointer; class room { public: void join(participantPointer participant); void deliver(const message& messageItem); void leave(participantPointer participant); private: messageQueue messageRecents; enum { max = 200 }; set<participantPointer> participants; }; class session : public participant, public enable_shared_from_this<session> { public: session(tcp::socket socket, room& room) : socket(move(socket)), room_(room); void start(); void deliver(const message& messageItem); private: void readHeader(); void readBody(); void write(); tcp::socket socket; room& room_; message messageItem; messageQueue Messages; }; class server { public: server(boost::asio::io_context& io_context, const tcp::endpoint& endpoint) : acceptor(io_context, endpoint); private: void do_accept(); tcp::acceptor acceptor; room room_; }; int main(int argc, char* argv[]); ساختار نرم افزار کاربر را هم به این صورت تعریف می کنیم : typedef deque<message> messageQueue; class client { public: client(boost::asio::io_context& context, const tcp::resolver::results_type& endpoints) : context(context), socket(context); void write(const message& messageItem); void close(); private: void connect(const tcp::resolver::results_type& endpoints); void readHeader(); void readBody(); void write(); boost::asio::io_context& context; tcp::socket socket; message readMessage; messageQueue writeMessage; }; int main(int argc, char* argv[]); در نظر داریم تا در این پروژه از thread ها نیز استفاده کنیم... در مورد این مفهوم ها می توانید بصورت مجزا تحقیق کنید. بنابراین روش کامپایل این پروژه به این صورت خواهد بود : $ g++ client.cpp -lpthread -o client $ g++ Server.cpp -lpthread -o server آزمایش همانطور که گفته شد در ابتدا نرم افزار اصلی و سرور باید اجرا شود. در اینجا ما تمام ارتباطات شبکه را بر روی یک سیستم در شبکه داخلی برقرار خواهیم کرد... پس نگرانی در مورد ساختار های درونی شبکه و آی پی / دی ان اس / دامین نخواهیم داشت. بنابراین ای پی را می توانید ای پی داخلی یا localhost در نظر بگیرید. برای آزمایش پورت فرضی 4000 را در نظر میگیریم و نرم افزار اصلی را روی این پورت اجرا میکنیم : $ ./server 4000 در این مرحله متوجه می شوید که نرم افزار اصلی با موفقیت اجرا شده است و همچنان اجرا مانده است. بله درست است... نرم افزار اصلی هر لحظه باید منتظر دستور کاربران باشد. اگر لحظه ای برای نرم افزار اصلی اختلالی پیش آید نخواهد توانست دستورات کاربران را انجام یا پاسخ دهد. بنابراین این پردازش را قطع نکنید و اجازه دهید تا نرم افزار اصلی اجرا بماند. در محیط دیگری نرم افزار سمت کاربر را نیز اجرا کنید. این نرم افزار را می توانید به تعداد دلخواه وارد کنید. (همانطور که ممکن است 6 نفر همزمان به سرور متصل باشند / یا ممکن است هیچ فردی به سرور متصل نشوند) ابتدا یک کاربری را به سرور با پورت 4000 و شبکه داخلی وصل می کنیم : $ ./client localhost 4000 first user: you can type message here... حال در محیط دیگری با کاربر جدیدی نیز وارد می شویم : $ ./client localhost 4000 second user: you can type message here... در این پروژه نمونه از کاربران نام کاربری یا نام نمی پرسیم.. و صرفا وقتی وارد محیط گفتگو می شوند... یا زمانی که به سرور متصل می شوند منتظر هستیم تا انها پیامی را بنویسند... هر پیامی را که بنویسند به سرور ارسال می شود و سرور وظیفه دارد تا آنرا برای تمام کاربران بفرستد. و این روند درون یک حلقه بی نهایت تکرار می شوند. پس این ارتباط دو طرفه خواهد بود و هم کاربران برای سرور اطلاعات ارسال می کنند و هم سرور برای کاربران اطلاعات ارسال خواهد کرد. در نظر داشته باشید که کاربر اول می تواند پیامی را بنویسد و به کاربران دیگر ارسال شود. ممکن است کاربر سومی اصلا تصمیمی به نوشتن پیام نداشته باشد و صرفا تمایل به خواندن پیام دیگران داشته باشند. و این کاملا اختیاری است. و ما کاربران را اجباری نمیکنیم. اگرچه شما می توانید با خلاقیت خودتان اینها را با متغییر های کمکی و دستورات شرطی پیاده کنید. کد ها برای پیام ها یک ساختار در نظر میگیریم و بصورت مشترک در هر دو نرم افزار استفاده خواهیم کرد... بنابراین اینرا در هدر پیاده خواهیم کرد. هدر پیام : (message.hpp) #ifndef message_HPP #define message_HPP #include <cstdio> #include <cstdlib> #include <cstring> using namespace std; class message { public: enum { headerLength = 4 }; enum { maxBodyLength = 512 }; message() : bodyLength_(0) { } const char* data() const { return data_; } char* data() { return data_; } size_t length() const { return headerLength + bodyLength_; } const char* body() const { return data_ + headerLength; } char* body() { return data_ + headerLength; } size_t bodyLength() const { return bodyLength_; } void bodyLength(size_t new_length) { bodyLength_ = new_length; if(bodyLength_ > maxBodyLength) bodyLength_ = maxBodyLength; } bool decodeHeader() { char header[headerLength + 1] = ""; strncat(header, data_, headerLength); bodyLength_ = atoi(header); if(bodyLength_ > maxBodyLength) { bodyLength_ = 0; return false; } return true; } void encodeHeader() { char header[headerLength + 1] = ""; sprintf(header, "%4d", static_cast<int>(bodyLength_)); memcpy(data_, header, headerLength); } private: char data_[headerLength + maxBodyLength]; size_t bodyLength_; }; #endif نرم افزار اصلی و سرور : (server.cpp) #include <iostream> #include <cstdlib> #include <deque> #include <memory> #include <list> #include <set> #include <utility> #include <boost/asio.hpp> #include "message.hpp" using boost::asio::ip::tcp; using namespace std; typedef deque<message> messageQueue; class participant { public: virtual ~participant() {} virtual void deliver(const message& messageItem) = 0; }; typedef shared_ptr<participant> participantPointer; class room { public: void join(participantPointer participant) { participants.insert(participant); for(auto messageItem: messageRecents) participant->deliver(messageItem); } void deliver(const message& messageItem) { messageRecents.push_back(messageItem); while(messageRecents.size() > max) messageRecents.pop_front(); for(auto participant: participants) participant->deliver(messageItem); } void leave(participantPointer participant) { participants.erase(participant); } private: messageQueue messageRecents; enum { max = 200 }; set<participantPointer> participants; }; class session : public participant, public enable_shared_from_this<session> { public: session(tcp::socket socket, room& room) : socket(move(socket)), room_(room) { } void start() { room_.join(shared_from_this()); readHeader(); } void deliver(const message& messageItem) { bool write_in_progress = !Messages.empty(); Messages.push_back(messageItem); if(!write_in_progress) { write(); } } private: void readHeader() { auto self(shared_from_this()); boost::asio::async_read(socket, boost::asio::buffer(messageItem.data(), message::headerLength), [this, self](boost::system::error_code ec, size_t) { if(!ec && messageItem.decodeHeader()) { readBody(); } else { room_.leave(shared_from_this()); } }); } void readBody() { auto self(shared_from_this()); boost::asio::async_read(socket, boost::asio::buffer(messageItem.body(), messageItem.bodyLength()), [this, self](boost::system::error_code ec, size_t) { if(!ec) { room_.deliver(messageItem); readHeader(); } else { room_.leave(shared_from_this()); } }); } void write() { auto self(shared_from_this()); boost::asio::async_write(socket, boost::asio::buffer(Messages.front().data(), Messages.front().length()), [this, self](boost::system::error_code ec, size_t) { if(!ec) { Messages.pop_front(); if(!Messages.empty()) { write(); } } else { room_.leave(shared_from_this()); } }); } tcp::socket socket; room& room_; message messageItem; messageQueue Messages; }; class server { public: server(boost::asio::io_context& io_context, const tcp::endpoint& endpoint) : acceptor(io_context, endpoint) { do_accept(); } private: void do_accept() { acceptor.async_accept([this](boost::system::error_code ec, tcp::socket socket) { if(!ec) { make_shared<session>(move(socket), room_)->start(); } do_accept(); }); } tcp::acceptor acceptor; room room_; }; int main(int argc, char* argv[]) { try { if(argc < 2) { cerr << "Usage: server <port> [<port> ...]\n"; return 1; } boost::asio::io_context io_context; list<server> servers; for(int i = 1; i < argc; ++i) { tcp::endpoint endpoint(tcp::v4(), atoi(argv[i])); servers.emplace_back(io_context, endpoint); } io_context.run(); } catch (exception& e) { cerr << "Exception: " << e.what() << "\n"; } return 0; } نرم افزار دوم و سمت کاربر : (client.cpp) #include <iostream> #include <thread> #include <cstdlib> #include <deque> #include <boost/asio.hpp> #include "message.hpp" using boost::asio::ip::tcp; using namespace std; typedef deque<message> messageQueue; class client { public: client(boost::asio::io_context& context, const tcp::resolver::results_type& endpoints) : context(context), socket(context) { connect(endpoints); } void write(const message& messageItem) { boost::asio::post(context, [this, messageItem]() { bool write_in_progress = !writeMessage.empty(); writeMessage.push_back(messageItem); if(!write_in_progress) { write(); } }); } void close() { boost::asio::post(context, [this]() { socket.close(); }); } private: void connect(const tcp::resolver::results_type& endpoints) { boost::asio::async_connect(socket, endpoints, [this](boost::system::error_code ec, tcp::endpoint) { if(!ec) { readHeader(); } }); } void readHeader() { boost::asio::async_read(socket, boost::asio::buffer(readMessage.data(), message::headerLength), [this](boost::system::error_code ec, size_t) { if(!ec && readMessage.decodeHeader()) { readBody(); } else { socket.close(); } }); } void readBody() { boost::asio::async_read(socket, boost::asio::buffer(readMessage.body(), readMessage.bodyLength()), [this](boost::system::error_code ec, size_t) { if(!ec) { cout.write(readMessage.body(), readMessage.bodyLength()); cout << "\n"; readHeader(); } else { socket.close(); } }); } void write() { boost::asio::async_write(socket, boost::asio::buffer(writeMessage.front().data(), writeMessage.front().length()), [this](boost::system::error_code ec, size_t) { if(!ec) { writeMessage.pop_front(); if(!writeMessage.empty()) { write(); } } else { socket.close(); } }); } boost::asio::io_context& context; tcp::socket socket; message readMessage; messageQueue writeMessage; }; int main(int argc, char* argv[]) { try { if(argc != 3) { cerr << "Usage: client <host> <port>\n"; return 1; } boost::asio::io_context context; tcp::resolver resolver(context); auto endpoints = resolver.resolve(argv[1], argv[2]); client c(context, endpoints); thread t([&context](){ context.run(); }); char line[message::maxBodyLength + 1]; while(cin.getline(line, message::maxBodyLength + 1)) { message messageItem; messageItem.bodyLength(strlen(line)); memcpy(messageItem.body(), line, messageItem.bodyLength()); messageItem.encodeHeader(); c.write(messageItem); } c.close(); t.join(); } catch (exception& e) { cerr << "Exception: " << e.what() << "\n"; } return 0; } این پروژه آزمایشی بصورت رایگان و اوپن سورس در اینترنت بخصوص اینجا وجود دارد و می توانید آنرا مستقیما بصورت کامل دانلود کنید. با تشکر, Max Base / مکس بیس
-
5 امتیازخب ! Build System چیست ؟ تمام برنامههایی که مینویسیم، معمولاً یک main.c دارند که نقطهٔشروع (start point) برنامهٔما هست. آیا همیشه همین یک فایله ؟ آیا همیشه نیازه که به یکصورت برنامه را کامپایل کنیم ؟ خب مسلماً جواب "نه" هست. چرا که ممکنه برنامهٔ شما دارای دهها فایل داشتهباشه، و نیاز داشتهباشید که هر فایل رو به صورتخاصی با فلگهای خاصی کامپایلکنید. اینجاس که "بیلد سیستم"ها وارد کار میشوند. به احتمال زیاد نمونههای زیادی مشاهده کردید که وقتی یک سورسیرا (source) از مخازن آنلاین گیت، مثل گیتهاب یا گیتلب دریافت میکنید در فایل راهنما (README.md) در بخش Build نوشته که وارد دایرکتوری بشید و دستور make و بعد make install را وارد کنید، دقیقاً کاری که میکنید اینکه برنامهٔ GNU Make را صدا میزنید که فایل تنظیمات رو از دایرکتوری جاری بخواند و دستورات تعیین شده رو انجام بده، این دستورات در فایلی به نام Makefile نوشته میشود. نصب کردن GNU Make این برنامه معمولاً روی تمام سیستمعاملهای معقول مثل GNU/Linux یا اقوام BSD نصب هست، درصورتیکه نبود میتوانید با استفاده از مدیربستهٔ سیستمعاملتون اقدام به نصب کنید، مثلاً برای نصب روی سیستمعامل Debian - Ubuntu - Ubuntu Mint میتوانید به اینصورت عمل کنید : $> apt install make چه کنیم با GNU Make ؟ اوّل از همه باید یک برنامهای داشتهباشیم که بخوایم براش Build System تعیین کنیم و دستورات Makefileش رو بنویسیم. یک نمونهٔ ساده کد چند تکهای را میتوانید از اینقسمت دریافت کنید. ما سه فایل arg.c/arg.h و main.c را به اینصورت داریم (یک ساختار معقول) : . ├── build ├── obj └── src ├── arg.c ├── arg.h └── main.c خب حالا ما باید Makefile خودمان را داخل دایرکتوری ریشه درست کنیم، قبلاً هم گفتم : "برنامهٔ GNU Make به دنبال فایلی به اسم Makefile یا GNUmakefile یا makefile میگرده". در Makefile میتوانیمما قوانین (rule) برای ساخته شدن چیزی و متغیرهایی تعریف کنیم. اینجا من توضیحات خلاصهای را میگویم، باقیماندهٔ مطالب را باید از مستنداترسمی GNU Make یا راهنمای سریع دنبال کنید. هر قوانینای که تعریف میکنیم دارای این ساختار هست : نیازها : هدفها دستورات مثلاً ما میخواهیم که برنامهٔکامپایل شدهٔمان، با اسم args در دایرکتوری build/ قرار بگیره. اینجا "هدف"ما میشه build/args و نیازما هم فایلهای کامپایل شدهٔ arg.c و main.c هست. اوه ! یک هدف دیگههم پیدا شد؛ الآن هدف دوّمما فایلهای کامپایل شدهٔ obj/arg.o و obj/main.o هست و نیازمان هم سورسهای این فایلها یعنی src/arg.h و src/arg.c و src/main.c. خب خیلی زیاد شدن، بهتره که از آخر شروع کنیم و نیازهایمان را برطرف کنیم، اوّلین نیاز فایلهای کامپایلشده هستن : obj/main.o obj/arg.o : src/main.c src/arg.c src/arg.h gcc -c -o obj/main.o src/main.c gcc -c -o obj/arg.o src/arg.o * نکته : سعی نکنید دستورات Makefile را از منطقهٔ کد کپی نکنید، کمی تلاش کنید و بنویسید. خب قبول دارم خیلی زیاد و زشت شد، بیاید این قانون (rule) را به دو تیکه قسمت کنیم : obj/arg.o : src/arg.c src/arg.h gcc -c -o obj/arg.o src/arg.c obj/main.o : src/main.c gcc -c -o obj/main.o src/main.c اگر تا انتها متن ادامه بدید حتماً کوتاهترم خواهد شد :). خب؛ object fileها یا همان فایلهای کامپایل شدهیمان را به دستآوردیم. حالا باید قانون (rule) نیاز اوّلمان را بنویسیم، چه چیزی نیاز داشتیم ؟ فایل کامپایل شدهٔ build/args که نیاز به object fileها داشت، حالا object fileها را داریم و باید نیاز هدفمان را برطرف کنیم : build/args : obj/main.o obj/arg.o gcc -o build/args obj/main.o obj/arg.o obj/arg.o : src/arg.c src/arg.h gcc -c -o obj/arg.o src/arg.c obj/main.o : src/main.c gcc -c -o obj/main.o src/main.c تمام شد. ما دستورات Build System خودمان را به زبان برنامهٔ GNU Make نوشتیم؛ حالا کافیه که فقط وارد دایرکتوریای که فایل Makefile هست بشیم و از ترمینال برنامهٔ make را فراخوانی کنیم : $> make gcc -c -o obj/main.o src/main.c gcc -c -o obj/arg.o src/arg.c gcc -o build/args obj/main.o obj/arg.o حالا میتوانیم برنامهٔ خودمان را اجرا کنیم : $> build/args -name Ghasem -family Ramezani Input Name is [Ghasem] Input Family is [Ramezani] دقّت کرده باشید ما توی نوشتن Makefileمان نیازمندیهارو یکی بالاتر از دیگری نوشتیم. چرا ؟ به خاطر اینکه GNU Make میاد از اوّل فایل شروع میکنه و قوانین (rules)ها را اجرا میکنه. بزارید با یک مثال نشان بدم. Makefile زیر را مدنظرتون داشتهباشید : obj/arg.o : src/arg.c src/arg.h gcc -c -o obj/arg.o src/arg.c obj/main.o : src/main.c gcc -c -o obj/main.o src/main.c build/args : obj/main.o obj/arg.o gcc -o build/args obj/main.o obj/arg.o ما نیاز اصلی خودمان را آخرین قانون (rule) نوشتیم. حالا برنامهٔ make را اجرا میکنیم تا رفتارَش را بهتر متوجه بشیم : $> make gcc -c -o obj/arg.o src/arg.c دیدید ؟ خیلی ساده برخورد کرد، اوّلین قانون (rule) را نگاه کرد تنها نیازمندیش فایلهای src/arg.c و src/arg.v بودن که وابسته به چیزی نبودند و هدفشان را تأمین کردند. اگر بخواهیم باقی قوانین (rules) را فراخوانی کنیم، باید صراحتاً مشخص کنیم : $> make obj/main.o gcc -c -o obj/main.o src/main.c $> make build/args gcc -o build/args obj/main.o obj/arg.o خب دیگه امیدوارم دلیل اینکهما نیازمندی اصلیه خودمان را اوّلین قانون (rule) قرار دادیم را متوجه شده باشید. وقتی make به نیازمندیه obj/arg.o و obj/main.o برای تأمین build/args برمیخوره ادامهٔ قوانین را پیمایش میکنه تا نیازمندیها را برطرف کنه. (اگر گیج شدید احتمالاً، پیشنهاد میکنم همین موارد را روی کاغذ کشیده و قسمت : نیازمندیها و هدفها و دستورات هر قانون را مشخص کنید.) میتوانیم قوانینی (rules) تعریف کنیم برای کارهای خاصی، مثلاً همان make install، یعنی قانون install را فراخوانی کن؛ حالا ما قانون clean را برای حذف کردن فایلهای کامپایلشده مینویسیم : clean : yes | rm -vf build/* obj/* البته باید در اینجا نکتهای را هم حواسمان باشد، باید به GNU Make بگوییم که قانون clean ، یک قانون الکیهست، و با یک "هدف" اشتباه نشود. به اینصورت قانون را ویرایش میکنیم : .PHONY : clean clean : yes | rm -vf build/* obj/* نگرانیای هم دربارهٔ Wildcard ها نداشتهباشید، GNU Make دستتون را باز گذاشته :). متغیرها در GNU Make مسلماً هرجا سخنی از متغیراست، سر و کلهٔ راحتیکار (و تا حدودی پیچیدگی) پیدا میشود. ما میتوانیم متغیرهم داخل Makefile خودمان داشتهباشیم. مثلاً فرض کنید که نیاز دارید تمام سورسکدها با کامپایل clang و سطحبهینهسازیه 3 کامپایل بشند. نیازی نیستکه هربار اینارو تایپ کنیم. کافیه براشون متغیرتعریف کنیم : CC = clang OP = -O3 OBJECT = obj/main.o obj/arg.o ARGS = src/arg.c src/arg.h build/args : $(OBJECT) $(CC) $(OP) -o build/args $(OBJECT) obj/arg.o : $(ARGS) $(CC) $(OP) -c -o obj/arg.o src/arg.c obj/main.o : src/main.c $(CC) $(OP) -c -o obj/main.o src/main.c clean : yes | rm -vf build/* obj/* متغیرهای به خصوصی نیز در GNU Make تعریف شدهاند که میتوانند کار مارا بسیار راحتتر کنند، برای مثال میتوانیم قانون object fileها را به اینصورت بازنویسی کنیم : obj/%.o : src/%.c $(CC) $(OP) -c -o $@ $? برای اطلاعات بیشتر به راهنمایسریع GNU Make مراجعه کنید. یادداشتها یا Code Comments برای استفاده از قابلیت Comment گذاری در کد، کافیه که اوّل خط خودتون از کاراکتر # استفاده کنید. خب دوستان، سعی کردم کلیّات مبحث را بگم؛ ابزار Make قابلیتهای بسیار زیادی داره که حتماً باید خودتون مطالعه کنید. مثلاً خواستید Makefile شما یک Makefile دیگه را صدا بزنه، یا حتیٰ دستورات شرطی اجرا بکند و یا از همه مهمتر بر اساس معماری پلتفرم شما عملیات کامپایل را انجام بده و ... . - موفقوپیروز باشید. ?
-
5 امتیازبا سلام، طبق بررسیهای لازم تغییراتی در گروههای کاربری اعمال شده است که از این پس کاربرانی که به عنوان کاربران فعال در حوزهٔ یادگیری و مشارکت در بحثها فعال میکنند از گروه پیشفرض کاربران عادی به کاربران رسمی تغییر دسترسی خواهند داشت. طبق آخرین اصلاحیه در سند( شرایط کسب مجوز فعالیتی و ارتقا حسابکاربری) ، کاربران عضو در این گروه دسترسی لازم برای ارسال تصویر، افزودن امضاء و همچنین عدم نیاز به تایید مطالب توسط مدیریت را خواهند داشت.
-
5 امتیازمعرفی سیاههی تغییرات (Change Log) سیاههی تغییرات (changelog یا CHANGELOG) اشاره به یک سیاهه یا تاریخچهی تغییراتی دارد که در یک پروژه همانند یک وبسایت اینترنتی یا یک پروژه نرمافزاری اعمال میشوند. یک پروندهی سیاههی تغییرات شامل یک لیستی است از تغییرات قابل توجه برای هر نسخه از یک پروژه. این تغییرات عموماً به عنوان اصلاحات باگها، قابلیتهای جدید و ... در این سیاهه نوشته میشوند. برخی از پروژههای متنباز فایل سیاههی تغییرات را در دایرکتوری سطح بالای کدهای منبع پروژه خود قرار میدهند. هرچند که قرارداد متعارف نامگذاری این فایل ChangeLog است، این فایل گاهی اوقات به صورت CHANGES یا HISTORY هم نامگذاری میشود (باید توجه داشت که NEWS فایل متفاوتی است که تغییرات بوقوع پیوسته از یک نسخه به نسخه دیگر در آن نوشته میشود، نه تغییراتی که از یک کامیت به کامیتی دیگر اتفاق افتادهاند). برخی از نگهدارندههای پروژهها پسوند .txt را هم به انتهای این فایل اضافه میکنند. برخی از سیستمهای نسخهبندی قادر به تولید کردن اطلاعاتی هستند که مناسب قرارگرفتن در یک فایل سیاههی تغییرات است. چرا باید از سیاههی تغییرات جهت حفظ تغییرات استفاده شود؟ برای اینکه کاربران و مشارکت کنندگان به راحتی بدانند که دقیقاً چه تغییرات قابل توجهی بین هر نسخهی انتشار یافته و دیگر نسخهها ایجاد شده است، بهتر است از این اصول پیروی شود. چه کسانی به سیاههی تغییرات نیاز دارند؟ چه مصرفکنندگان و چه توسعهدهندگان، کاربران نهایی نرمافزار، انسانهایی هستند که به آنچه در نرمافزار تغییر پیدا میکند اهمیت میدهند؛ هنگامی که نرمافزار تغییر پیدا میکند، مردم میخواهند بدانند که چرا و چطور این تغییرات اعمال شده است. بنابراین استفاده از این قالب علاوه بر ارائهی ارزشی در بحث تجربهکاربری، در روند توسعه اهمیت بسیاری دارد. چطور میتوانم یک سیاههی تغییرات خوب ایجاد کنم؟ راهنمای اصول سیاههی تغییرات برای انسانها هستند نه ماشین. برای هر کدام از نسخهها باید یک مدخل وجود داشته باشد. انواع مشابه تغییرات باید دستهبندی شوند. نسخهها و بخشها باید پیوند پذیر باشند. آخرین نسخه اول میآید. تاریخ عرضهی هر کدام از نسخهها، نمایش داده میشود. از استاندارد و اصول نسخهبندی معنایی استفاده و آن را رعایت کنید. انواع تغییرات Added برای امکانات جدید. Changed برای تغییر در عملکرد موجود. Deprecated برای امکاناتی که به زودی حذف میشوند. Removed برای امکانات حذف شده. Fixed برای هر نوع رفع خطا. Security در صورت وجود هرگونه آسیبپذیری امنیتی. برای ردیابی تغییرات آتی یک بخش با عنوان Unreleased در بالا نگهدارید، این کار دو هدف دارد: مردم میتوانند ببیند که در نسخههای آینده چه تغییراتی را میتوان انتظار داشت. در زمان انتشار، میتوانید تغییرات بخش Unreleased را به بخش نسخهی جدید منتقل کنید. آیا استانداردی برای سیاههی تغییرات وجود دارد؟ حقیقتاً خیر، هرچند سبکی از گنو و همچنین بخشی از فایل خبر گنو به این مورد اشاره دارند، اما اینها ناکافی میباشند. نام فایل سیاههی تغییرات چه باید باشد؟ میتوانید آن را CHANGELOG.md بنامید. برخی از پروژهها از HISTORY، NEWS و یا RELEASES استفاده میکنند. هرچند مهم نیست که نام فایل نهایی این روند چه چیزی باشد، اما طوری باید باشد که کاربر متوجه هدف فایل تغییرات باشد. یک مثال از قالب صحیح از سیاههی تغییرات # Changelog All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] ## [1.0.0] - 2017-06-20 ### Added - New visual identity by [@tylerfortune8](https://github.com/tylerfortune8). - Version navigation. - Links to latest released version in previous versions. - "Why keep a changelog?" section. - "Who needs a changelog?" section. - "How do I make a changelog?" section. - "Frequently Asked Questions" section. - New "Guiding Principles" sub-section to "How do I make a changelog?". - Simplified and Traditional Chinese translations from [@tianshuo](https://github.com/tianshuo). - German translation from [@mpbzh](https://github.com/mpbzh) & [@Art4](https://github.com/Art4). - Italian translation from [@azkidenz](https://github.com/azkidenz). - Swedish translation from [@magol](https://github.com/magol). - Turkish translation from [@karalamalar](https://github.com/karalamalar). - French translation from [@zapashcanon](https://github.com/zapashcanon). - Brazilian Portugese translation from [@Webysther](https://github.com/Webysther). - Polish translation from [@amielucha](https://github.com/amielucha) & [@m-aciek](https://github.com/m-aciek). - Russian translation from [@aishek](https://github.com/aishek). - Czech translation from [@h4vry](https://github.com/h4vry). - Slovak translation from [@jkostolansky](https://github.com/jkostolansky). - Korean translation from [@pierceh89](https://github.com/pierceh89). - Croatian translation from [@porx](https://github.com/porx). - Persian translation from [@Hameds](https://github.com/Hameds). - Ukrainian translation from [@osadchyi-s](https://github.com/osadchyi-s). ### Changed - Start using "changelog" over "change log" since it's the common usage. - Start versioning based on the current English version at 0.3.0 to help translation authors keep things up-to-date. - Rewrite "What makes unicorns cry?" section. - Rewrite "Ignoring Deprecations" sub-section to clarify the ideal scenario. - Improve "Commit log diffs" sub-section to further argument against them. - Merge "Why can’t people just use a git log diff?" with "Commit log diffs" - Fix typos in Simplified Chinese and Traditional Chinese translations. - Fix typos in Brazilian Portuguese translation. - Fix typos in Turkish translation. - Fix typos in Czech translation. - Fix typos in Swedish translation. - Improve phrasing in French translation. - Fix phrasing and spelling in German translation. ### Removed - Section about "changelog" vs "CHANGELOG". ## [0.3.0] - 2015-12-03 ### Added - RU translation from [@aishek](https://github.com/aishek). - pt-BR translation from [@tallesl](https://github.com/tallesl). - es-ES translation from [@ZeliosAriex](https://github.com/ZeliosAriex). ## [0.2.0] - 2015-10-06 ### Changed - Remove exclusionary mentions of "open source" since this project can benefit both "open" and "closed" source projects equally. ## [0.1.0] - 2015-10-06 ### Added - Answer "Should you ever rewrite a change log?". ### Changed - Improve argument against commit logs. - Start following [SemVer](https://semver.org) properly. ## [0.0.8] - 2015-02-17 ### Changed - Update year to match in every README example. - Reluctantly stop making fun of Brits only, since most of the world writes dates in a strange way. ### Fixed - Fix typos in recent README changes. - Update outdated unreleased diff link. ## [0.0.7] - 2015-02-16 ### Added - Link, and make it obvious that date format is ISO 8601. ### Changed - Clarified the section on "Is there a standard change log format?". ### Fixed - Fix Markdown links to tag comparison URL with footnote-style links. ## [0.0.6] - 2014-12-12 ### Added - README section on "yanked" releases. ## [0.0.5] - 2014-08-09 ### Added - Markdown links to version tags on release headings. - Unreleased section to gather unreleased changes and encourage note keeping prior to releases. ## [0.0.4] - 2014-08-09 ### Added - Better explanation of the difference between the file ("CHANGELOG") and its function "the change log". ### Changed - Refer to a "change log" instead of a "CHANGELOG" throughout the site to differentiate between the file and the purpose of the file — the logging of changes. ### Removed - Remove empty sections from CHANGELOG, they occupy too much space and create too much noise in the file. People will have to assume that the missing sections were intentionally left out because they contained no notable changes. ## [0.0.3] - 2014-08-09 ### Added - "Why should I care?" section mentioning The Changelog podcast. ## [0.0.2] - 2014-07-10 ### Added - Explanation of the recommended reverse chronological release ordering. ## [0.0.1] - 2014-05-31 ### Added - This CHANGELOG file to hopefully serve as an evolving example of a standardized open source project CHANGELOG. - CNAME file to enable GitHub Pages custom domain - README now contains answers to common questions about CHANGELOGs - Good examples and basic guidelines, including proper date formatting. - Counter-examples: "What makes unicorns cry?" [Unreleased]: https://github.com/olivierlacan/keep-a-changelog/compare/v1.0.0...HEAD [1.0.0]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.3.0...v1.0.0 [0.3.0]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.2.0...v0.3.0 [0.2.0]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.1.0...v0.2.0 [0.1.0]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.8...v0.1.0 [0.0.8]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.7...v0.0.8 [0.0.7]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.6...v0.0.7 [0.0.6]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.5...v0.0.6 [0.0.5]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.4...v0.0.5 [0.0.4]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.3...v0.0.4 [0.0.3]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.2...v0.0.3 [0.0.2]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.1...v0.0.2 [0.0.1]: https://github.com/olivierlacan/keep-a-changelog/releases/tag/v0.0.1
-
5 امتیازفایلها/تغییرات پروژه را چطوری کنترل کنیم ؟ در وهلهٔ اوّل شاید بگید چه نیازیه ؟ خب برنامه رو مینویسیم و میریم دیگه !. درسته برنامهاتون را مینویسید و میروید؛ امّا به کجا چنین شتابان ؟ آیا همیشه برنامهٔ شما کوچکخواهد بود ؟ آیا قراره برنامهٔ شما در صد خط تمام بشه ؟ یا اینکه کلاً قصد توسعهاش رو دیگه ندارید ؟ خب شاید یکی دیگه داشت :). فرض کنید برنامهٔتان را نوشتید : void parsing(int argc, char **argv){ top = 0; for (unsigned i=1; i < (unsigned)argc; i+=2){ listArgs[top].name = argv[i]; listArgs[top].value = argv[i+1]; top++; } } خب، برنامهکار میکنه و میرید و یک هفتهٔ دیگه میاید و مثلاً خط : top = 0; را حذف میکنید. و برنامه در اجرای اوّل درست کار میکنه؛ پیشخودتون میگید خب چه نیازی بود، الکی ماهم کد نوشتیم :). امّا بعداً در اجراهای متوالی برنامه شروع میکنه به دادن خروجیهای نامتعارف. اینجاس که باید ساعتها وقت بزارید و بگردید ببینید آخرینبار چه چیزی رو تغییر دادید و کدوم فایل را ویرایش کردید. کار مسخره و اعصابخورد کنی میشه، درسته ؟. امّا برای مدیریت این دَنگٌوفَنگها میتونید از سیستمهایمدیریتپروژه استفاده بکنید. مثل Git حالا اینکه چرا گیت ؟ به خاطر اینکه راحتترینه و بهترینه. چرا ؟ چون امتحانش را پس داده، پروژهٔ بزرگ "کرنللینوکس" را داره مدیریت میکنه. حالا بیاید ببینیم اگه ما ازت گیت (git) استفاده میکردیم، چطوری میتوانستیم بفهمیم که چه بلایی سر کد آمده : ۱- اوّل گزارشات را چک میکنم، تا ببینم آخرین گزارشی که از تغییرات ذخیره کردم چه بوده ؟: $> git log commit bb513a5f9ec429222de03afa690e7fa5d2fbdf6e (HEAD -> master) Author: Ghasem Ramezani <g1999ramezani@gmail.com> Date: Sun May 5 00:05:22 2019 +0430 create a bug commit ab176fa8a282a74e6badfc285c0986bc66ee6b7d (origin/master, origin/HEAD) Author: Ghasem Ramezani <g1999ramezani@gmail.com> Date: Sat May 4 10:40:32 2019 +0430 make `top` to be 0 at first of parsing() function and make class storage of listArgs to be `extern` and getOption() function return "NULL" on Failure. خب فهمیدم که آخرین تغییرم با عنوان create a bug ثبت شده، حالا باید از شناسهاش استفاده کنم. ۲- تغییراتی که در آن گزارش ثبت شده است را مشاهده میکنم. : $> git show bb513a5f9ec429222de03afa690e7fa5d2fbdf6e commit bb513a5f9ec429222de03afa690e7fa5d2fbdf6e (HEAD -> master) Author: Ghasem Ramezani <g1999ramezani@gmail.com> Date: Sun May 5 00:05:22 2019 +0430 create a bug diff --git a/source/arg.c b/source/arg.c index c776ff2..a75c91d 100644 --- a/source/arg.c +++ b/source/arg.c @@ -7,7 +7,6 @@ unsigned top=0; struct ARGS listArgs[MAX_ARG]; void parsing(int argc, char **argv){ - top = 0; for (unsigned i=1; i < (unsigned)argc; i+=2){ listArgs[top].name = argv[i]; listArgs[top].value = argv[i+1]; دیدی به چه سادگی توانستیم تغییری که دادیم را پیدا کنیم ؟ البته این انتهای ماجرا نیست ! الآن که متوجه شدیم در کدام گزارشما خرابکاری کردیم؛ کافیه که تغییرات را به گزارش قبل از خرابکاری برگردانیم : $> git reset --hard ab176fa8a282a74e6badfc285c0986bc66ee6b7d البته قابل ذکره که ما اینجا تنها داخل این گزارش فقط یک تغییر داشتیم، مسلماً کار میتونه کمی پیچیدهتر بشه اگه تغییرات زیاد باشن، که همیشه هستن ?. چگونه با گیت (git) کار کنیم ؟ بسیار ساده، مسلماً اوّل نیاز دارید که این برنامه را نصب کنید. این برنامه به طور پیشفرض در سیستمعاملتون نصب نیست. کافیه که از مدیربستهٔ سیستمعاملتون کمک بگیرید، مثلاً برای Debian - Ubuntu - Ubuntu Mint به اینصورت کار تمام میشود : $ apt install git حالا بعد از نصب، نیاز دارید که مشخصاتتان را ثبت کنید، دقت کنید که تمام توضیحاتی که بنده میدهم را میتوانید بهصورت کاملتر از سایت گیت (git) دنبال کنید. $> git config --global user.name "Ghasem Ramezani" $> git config --global user.email "g1999ramezani@gmail.com" $> git config --global core.editor emacs دو مورد اوّل که واضح هستن، امّا مورد آخر دلبخواه خودتان هست، زمانیکه نیاز باشه گیت (git) ویرایشگرمتنی را جهت ویرایشباز بکند باید بداند که کدام ویرایشگر مورد علاقهٔ شماست. میتوانید هر برنامهای را قرار بدهید. امّا دقت کنید که بهترین ویرایشگرها میتوانند Vim, Emacs, Notepad++ باشند؛ فایل این تنظیمات را میتوانید از این مسیرها دنبال کنید : User Space : ~/.gitconfig System Wide: /etc/gitconfig ساخت مخازن (repository) خب حالا که نصب/پیکربندی انجام شد، کافیه که مخزن (repository) خودمان را راهاندازی کنیم. یک پروژهٔ جدید درست کنید و گیت (git) را مقداردهی (Initialize) کنید : $> mkdir project ; cd project $> git init ما یک دایرکتوری به اسم project درست کردیم، و مخزن (repository) خودمان را با دستور git init راهاندازی کردیم، یک سری فایلهایی گیت (git) برای ما داخل آن دایرکتوری با اسم .git درست کرده. تغییراتیکه نیاز رو انجام میدیم، مثلاً در وهلهٔ اوّل دایرکتوریها و فایلهای پروژه را راهاندازی میکنیم : $> mkdir header source build object $> touch header/arg.h source/arg.c Makefile $> tree . ├── build ├── Makefile ├── header │ └── arg.c ├── object └── source └── arg.h 4 directories, 3 files $> اگه درمورد Makefile نمیدانید، میتوانید از اینجا با GNU Make و Makefile آشنا بشید. الآن بد نیست که خروجی دستور git status را ببینیم تا توضیحاتی در اینباره بدیم (این دستور، وضعیتجاری مخزنمان را نشان میدهد) : $> git status On branch master No commits yet Untracked files: (use "git add <file>..." to include in what will be committed) Makefile header/ source/ nothing added to commit but untracked files present (use "git add" to track) عکس زیر را مشاهدهکنید تا توضیحبهتری بدم : فایلهای شما داخل گیت (git) دارای حالاتهای مختلفیهستن، به طورکلّی یا شناختهشدناند (tracked) یا ناشناختهاند (untracked)؛ فایلها/دایرکتوریهایی که ما بعد از مقداردهی مخزنمان ساختیم، در حالت ناشناخته (untracked) هستند. که خود گیت (git) هم همینرا به ما گفتهاست : Untracked files: (use "git add <file>..." to include in what will be committed) برای اینکه شناختهشده (tracked) بشند، باید آنها را به صحنه (stage) ببریم. برای اینکار خود گیت گفتهاست که باید چه کرد که میتوانیم به دوصورت انجام دهیم : $> git add Makefile source header $> git add -A خب حالا دوباره خروجی git status را نگاه میکنیم : $> git status On branch master No commits yet Changes to be committed: (use "git rm --cached <file>..." to unstage) new file: Makefile new file: header/arg.c new file: source/arg.h الآن فایلهای ما به stage رفتند، و آمادهٔ اینهستند که گزارش (commit) بشوند. دقت کنید که Git از خِیر دایرکتوریهای خالی میگذرد. حالا کافیهکه ما تغییراتی که دادیم را گزارش کنیم، که با دستور git commit به دوصورت انجام میشود : $> git commit $> git commit -m "My Message" در حالتاوّل، گیت ادیتور پیشفرضتان را باز میکند و از شما میخواهد که یک توضیحکوتاه درمورد تغییراتیکه دادهاید بنویسید، در حالتدوّم، شما مستقیم توضیحکوتاه خود را وارد میکنید. حال دوباره برگردیم و خروجی دستور git status را ببینیم : $> git status On branch master nothing to commit, working tree clean خیلیهم عالی، این نشان دهندهٔ ایناست که ماهیچ فایل ناشناخته (َUntracked) یا دستکاریشده (Modified) یا درصحنه (Stage) نداریم. هنگامیکه تغییراتی را در فایلهای شناختهشده (Tracked) بدید، آن فایل از حالت دستکارینشده (Unmodified) به حالت دستکاریشده (Modified) درمیاید، که نیاز است شما تغییرات را درصورتنیاز وارد صحنه (Stage) کنید و بعد گزارشکنید (Commit). حال تغییراتیاعمال میکنیم، و مراحلمورد نیاز تا درصحنه (Stage) بردنفایلها انجام میدهیم : $> git add -A $> git status On branch master Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: Makefile modified: header/arg.h modified: source/arg.c امّا شاید شما نخواید که مثلاً Makefile گزارشش با مابقیه فایلها یکی باشه، و نیاز دارید که از Stage بیرون بیاریدش؛ دقّت کنید خود Git هم راهنمایی کرده که باید چهکار کرد : $> git reset HEAD Makefile $> git status On branch master Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: header/arg.h modified: source/arg.c Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: Makefile و حالا میتوانید به راحتی گزارش فایلهای خودتان را برای header/arg.h و source/arg.c بنویسید : $> git commit -m "Done With Print() Function" فایل .gitignore بیاید تا make را اجرا کنیم (درصورتیکه با GNU Make آشنا نیستید، برای آشنایی اینقسمت را مطالعه کنید) : $> git status On branch master Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: Makefile Untracked files: (use "git add <file>..." to include in what will be committed) build/ object/ no changes added to commit (use "git add" and/or "git commit -a") اینجا دایرکتوریهای build و object هم اضافه شدند،امّا ما نیازی نداریم که Git این دایرکتوریها را مدیریت کند، پس کافیه که یک فایل به اسم .gitignore درست کنیم. و فایلها و دایرکتوریهایی که نمیخواهیم Git آنها را دنبال کند را در آن ذکر کنیم : $> echo -e "/build/*\n/object/*" > .gitignore $> cat .gitignore /build/* /object/ $> git status On branch master Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: Makefile Untracked files: (use "git add <file>..." to include in what will be committed) .gitignore no changes added to commit (use "git add" and/or "git commit -a") و مشاهده میکنید که دیگر Git اخطاری برای دایرکتوریهای build و object نداد. خب دوستان،امیدوارم دلیل اهمیّت Git و کلاً برنامههای کنترلورژن را درککرده باشید؛ امّا شرمنده، دنیای Git بزرگتر از آنچه هست که من بخوام خلاصهای از هر قسمت را در یک پست بازگو کنم؛ شدیداً پیشنهاد میکنم که اینکتاب را برای فراگیری هرچه بهتر Git بخوانید. - موفق و پیروز باشید. ?
-
5 امتیاز
نگارش 11.0.1
31 دریافت
کامپایلر کلَنگ (Clang) یک مترجم روبه جلو برای زبانهای برنامه نویسی C و ++C و Objective-C و ++Objective-C میباشد که از LLVM بعنوان زیر ساخت روبه عقب استفاده میکند. آرمان کلنگ این است که جایگزین کامپایلر جیسیسی شود. کلنگ بصورت کاملاً متن باز توسعه میابد و توسط کمپانیهای بزرگی مانند گوگل و اپل پشتیبانی میشود.رایگان
-
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 امتیازکامپایلر Cling یک مترجم تعاملی برای سیپلاسپلاس است، این مترجم تحت بالاترین کتابخانههای Clang و LLVM ساخته شده است. در واقع از آنجایی که کامپایلر Clang از آخرین ویژگیها و استانداردهای زبان سیپلاسپلاس پشتیبانی میکند، Cling اجازه میدهد تا توسعهدهندگان اسکریپتهای خود را با استفاده از C و C++ بنویسند. اگر شما به طور مستقیم مترجم را اجرا کنید، یک محیط زنده برای آغاز برنامه نویسی با سیپلاسپلاس را خواهید داشت که به عنوان بخشی از استاندارد نحو سی و سیپلاسپلاس به شمار میآید. همچنین میتوانید دیگر دستورات را با نقطهی "." آغاز در اختیار داشته باشید. وقتی از مترجم تعاملی استفاده میکنید، میتوانید کد زیر را بنویسید: #include <stdio.h> printf("hello world\n"); همانطور که میبینید نیازی نیست تا در مورد حوزهی دامنهها نگران باشید؛ کافی است شما تابع مورد نظر خود را صدا بزنید. اگر قصد شما این است که از Cling به عنوان یک مترجم برای ساخت اسکریپتها استفاده کنید، باید همه چیز را در داخل یک تابع قرار دهید.چرا که نقطهی ورود به اسکریپت به طور پیشفرض همانند نام فایل میباشد. میتوان آن را برای صدا زدن دیگر توابع سفارشی سازی کرد. بنابراین مثال قبل میتوانید به شکل زیر تغییر کند: #include <stdio.h> void _01_hello_world() { printf("foo\n"); } یک نسخهی دیگر در قالب سیپلاسپلاس #include <iostream> void _02_hello_world() { std::cout << "Hello world" << std::endl; } مثالها کاملاً ساده هستند، اما آنها به شما نشان میدهند که چگونه باید شروع کنید. در مورد کیوت چطور؟ #include <QtWidgets/qapplication.h> #include <QtWidgets/qpushbutton.h> void _03_basic_qt() { int argc = 0; QApplication app(argc, nullptr); QPushButton button("Hello world"); QObject::connect(&button, &QPushButton::pressed, &app, &QApplication::quit); button.show(); app.exec(); } اما توجه داشته باشید که کد قبلی کار نخواهد کرد، شما باید برخی از پارامترهای سفارشی را در Cling مشخص کنید. cling -I/usr/include/x86_64-linux-gnu/qt5 -fPIC -lQt5Widgets 03_basic_qt.cpp شما میتوانید Cling را برای خودتان بر اساس آن چیزی که برای اسکریپت خود نیاز دارید سفارشی سازی کنید. همچنین شما میتوانید Cling را به عنوان یک کتابخانه در اپلیکیشنهای خود آورده و از سیپلاسپلاس به عنوان زبان برنامهنویسی استفاده کنید. این پُست در آینده ادامه خواهد داشت. ?
-
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 امتیازمدتی است در مورد مسدود شدن اپلیکیشنهای ایرانی برای iOS از طرف شرکت اپل خبرهایی به گوش میرسد که در سایتها و پایگاههای خبری از سمت نویسندگان و افراد غیرفنی تجزیه تحلیل و روشهای دور زدن آنها ارائه میشود. واقعیت بر دلیل نوشتن این مقاله این است که این فرصت و مشکلات کنونی آبی گلآلود برای سودجویانی شده است که کاربران از آن بیخبرند! هر روز یک توسعهدهنده یک سایت جدید راهاندازی میکند و با ادعای ارائه بستری نامحدود اقدام به تبلیغات میکند. بنده نیز به عنوان توسعهدهنده وظیفهٔ خودم میدانم که یک بار برای همیشه توضیحات شفاف و روشنی را در اختیار کاربران iOS قرار دهم تا متوجه اصلِ موضوع باشند (بعد از آن تصمیم با خود شما)! اول از خودمان شروع کنیم، آیا واقعاً حرکتهایی که ما داشتهایم درست بوده است؟ به گونهای که انگار اقدامات ما ایرانیها بدون عیب و ایراد بوده و اپل بدون دلایل منطقی اقدام به تحریم ما کرده است! (هدف از این مقاله به هیچ عنوان طرفداری از اقدامات شرکت اپل نیست، چرا که این شرکت به عنوان فروشندهٔ محصولات خود وظیفه دارد به پشتیبانی و ارائهٔ خدمات به کاربرانش باشد نه اینکه هم سود کند و هم به خاطر مسائل سیاسی برخی از مشتریان خود را محدود کند. بنابراین ما اپل را هم محکوم به آن میکنیم که هیچ ارزشی به کاربران و توسعهدهندگان ایرانی به خاطر مسائل سیاسی قائل نیست)، و در مقابل مشترکین و حتی شرکتها و فروشگاههای اپلیکیشن موظف هستند به جای توجیح کارهای غیر قانونی و ناعادلانهٔ خود (و استفاده از چنین فرصتها)، اقدامات به شفاف سازی روشهای انتشار و توسعه کنند که مسلماً کاربران عادی و غیر حرفهای از این امر بی خبرند! به گونهای که انگار ما عادت کردهایم هر زمان که مشکلی گریبان گیر ملت ما میشود به جای حل آن از روش صحیح و قانونی، اقدام به فشار بیشتر و سوء استفاده از آن فرصت کنیم که اصلاً روش انسان دوستانهای نیست (حداقل از فرهنگ اصیل ایرانی چنین انتظاراتی نداریم). اما واقعیت امر در چیست و دلایل مسدود سازی نرمافزارها بر روی iOS در چیست؟ اینطور که به گوش میرسد و به گفتهٔ پایگاههای خبری و سایتهای فناوری خبرها اینگونه است که، اپل تا کنون چندین بار برخی اپلیکیشنهای ایرانی را مسدود یا رَد اعتبار کرده است ولی این بار، اپلیکیشنهای پرداخت الکترونیکی و موبایلی مانند آسان پرداخت و نرمافزار بانکهای معروف ایرانی تحریم شدند. افزون بر این، اپهای محبوب و پر کاربردی مانند اسنپ، تپسی، فونپی، دیجیکالا، فیدیبو، سیباپ نیز جزو تحریم شدهها هستند. در قدم اول ممکن است دلایل این کار را به خاطر مسائل سیاسی بدانیم، این مسئله تا حدی ممکن است درست باشد، اما با بازنگری و یادآوری حریم خصوصی و حقوق مشتری در جامعهٔ بشری از سمت اپل نیز حکم میکند که جوابگوی خدمات پس از فروش خودش باشد. بنابراین بهانه تراشی بخشی از اقدامات میتواند باشد اما مسئلهٔ اصلی این نیست! اجازه دهید جایگاه خودمان را برعکس در نظر بگیریم، با این حساب که ما به عنوان خدمات دهندههای ایرانی بستری را فراهم کرده باشیم که به جامعهٔ بزرگی از دنیا خدمات ارائه میدهیم. بنابراین قوانین و چهارچوبهای شفاف و مشخصی را عنوان خواهیم کرد که خارج از آن باید اقدام به یادآوری و گوشزد، تذکر و در نهایت برخورد قانونی و تحریم را در برنامه داشته باشیم که یک روند قانونی و طبیعی است. این قوانین در صورتی اجرا میشوند که حقوق توسعه، تولید، نشر و پشتیبانی رسمی محصولات نادیده گرفته شود. بنابراین فرض کنید شما صاحب فروشگاهی هستید که نویسندگان (توسعهدهندگان) و ارائهدهندگان خدمات آن همگی ساعتها، ماهها و سالها زمان بر توسعه و تولید محصولات خود گذاشتهاند. حال ممکن است آن را رایگان و یا حتی با دیدگاه تجاری در اختیار کاربران قرار دهند. بنابراین عقل و منطق اجازه میدهد که شما نرمافزار رایگان را به صورت رایگان و نرمافزارهای تجاری را در قبال پرداخت هزینهٔ آن مورد استفاده قرار دهید. در غیر این صورت اگر محصولی که شما ارائه دادهاید با نقض این موارد مواجه شود (بدون شک اولین تصمیمی که خواهید گرفت حذف خدمات پس از فروش، پشتیبانی و ... خواهد بود). اما واقعیت این مسئله چیست؟ آیا اپل اقدام به تحریم بی دلیل بر روی اپلیکیشنهای ایرانی داشته است؟ اگر منطقی به قضیه فکر کنیم، به راحتی میتوان این مسائل را بررسی و دلایل تحریم را درک کرد؛ من در این مقاله ابتدا به دلایل تحریم اپل میپردازم که پاسخ روشن و صریح این اقدامات اخیر را در این باره به شما خواهد داد. هرچند من به عنوان یک برنامهنویس باید به دنبال توسعه و تولید محصولات و حتی دور زدن تحریمهای ناشیانه در این حوزه باید باشم، اما اینکه هم نوعان و همکاران خودم هم در این باره خبرها و اطلاعات دروغ را به مشتریان این حوزه میدهند قابل تحمل نیست! چرا که اول باید از خودمان شروع کنیم! بهتر است در نظر داشته باشیم قوانینی که در اپل نیز ذکر شدهاند به این اشاره دارد که در صورت خروج از این چهارچوب که ممکن است امنیت و حقوق مادی و معنوی توسعهدهنده و ناشر را پایمال کند، هیچ گونه تعهدی در رابطه با ادامهٔ همکاری و یا پشتیبانی از آن خدمات را نخواهند داشت. بنابراین شخصاً ندیدم حتی در یکی از فروشگاههای ایرانی اشارهای به این حقوق شده باشه (حتی برعکس و شدیداً بر خلاف مواردی هستند که ذکر شدهاند که با دلیل و اسناد معتبر خود مرجع اپل آنها را شفاف سازی خواهم کرد). به عنوان مثال، اگر شما یک کاربر عادی یا حتی تازه کار باشید، یا اگر شما یک توسعهدهندهٔ تازهکار و حتی حرفهای باشید بهتر است به این بخش از قوانین اپل (App Store Review Guidelines) توجه جدی کنید! این بخشی از قوانین صریح و شفاف اپل در حوزهٔ اپلیکیشنهای iOS و فروشگاه خودش است که در زیر آمده است: App Store Review Guidelines Introduction Apps are changing the world, enriching people’s lives, and enabling developers like you to innovate like never before. As a result, the App Store has grown into an exciting and vibrant ecosystem for millions of developers and more than a billion users. Whether you are a first time developer or a large team of experienced programmers, we are excited that you are creating apps for the App Store and want to help you understand our guidelines so you can be confident your app will get through the review process quickly. The guiding principle of the App Store is simple - we want to provide a safe experience for users to get apps and a great opportunity for all developers to be successful. We do this by offering a highly curated App Store where every app is reviewed by experts and an editorial team helps users discover new apps every day. For everything else there is always the open Internet. If the App Store model and guidelines are not best for your app or business idea that’s okay, we provide Safari for a great web experience too. On the following pages you will find our latest guidelines arranged into five clear sections: Safety, Performance, Business, Design, and Legal. The App Store is always changing and improving to keep up with the needs of our customers and our products. Your apps should change and improve as well in order to stay on the App Store. A few other points to keep in mind: We have lots of kids downloading lots of apps. Parental controls work great to protect kids, but you have to do your part too. So know that we’re keeping an eye out for the kids. The App Store is a great way to reach hundreds of millions of people around the world. If you build an app that you just want to show to family and friends, the App Store isn’t the best way to do that. Consider using Xcode to install your app on a device for free or use Ad Hoc distribution available to Apple Developer Program members. If you’re just getting started, learn more about the Apple Developer Program. We strongly support all points of view being represented on the App Store, as long as the apps are respectful to users with differing opinions and the quality of the app experience is great. We will reject apps for any content or behavior that we believe is over the line. What line, you ask? Well, as a Supreme Court Justice once said, “I’ll know it when I see it”. And we think that you will also know it when you cross it. If you attempt to cheat the system (for example, by trying to trick the review process, steal user data, copy another developer’s work, manipulate ratings or App Store discovery) your apps will be removed from the store and you will be expelled from the Developer Program. You are responsible for making sure everything in your app complies with these guidelines, including ad networks, analytics services, and third-party SDKs, so review and choose them carefully. Some features and technologies that are not generally available to developers may be offered as an entitlement for limited use cases. For example, we offer entitlements for CarPlay Audio, HyperVisor, and Privileged File Operations. Review our documentation on developer.apple.com to learn more about entitlements. We hope these guidelines help you sail through the App Review process, and that approvals and rejections remain consistent across the board. This is a living document; new apps presenting new questions may result in new rules at any time. Perhaps your app will trigger this. We love this stuff too, and honor what you do. We’re really trying our best to create the best platform in the world for you to express your talents and make a living, too. در قوانین ذکر شده به صراحت عنوان شده است که اگر به فکر برنامههای آزمایشی هستید بهتر است از محیط Xcode با همان حساب توسعهدهندگی استفاده کنید که تنها بر روی دستگاه خودتان میتواند اجرا شود. در صورتی که به فکر بحث تجاری آن هستید باید تمامی حقوق مربوطه را رعایت کنید و حتی نباید به فکر کپی کردن، درز اطلاعات، به خطر اندازی حریم خصوصی و دیگر مسائل بپردازید که در این صورت اپل محصول شما را رَد خواهد کرد. فشار دو طرفه، بهانه تشدید بهانه... بهانه و باز هم بهانه!!! مسلماً برای همه روشن است که سیاستهای آمریکایی و شرکتهای آن منتظر بهانههایی هستند که سریعاً فشارها را به سمت ملت ایران وارد کنند، بنابراین مانند اقدامات اخیر Github که متأسفانه مجبور هستند بر اساس سیاستهای دولتی خود اقدام به محدود سازی خدمات خود به ایرانیها باشند (اپل بسیار مشتاقانهتر به دنبال بهانه و ایجاد فشار به ملت ما میشتابد). بنابراین باز هم یادآوری کنیم محصولی که بابت آن پول پرداخت میشود اعمال محدودیت و فشار بر آن دیگر جایز و انساندوستانه نیست! جالبتر از این موارد یادآوری این موضوع است که دوستان داخلی به جای حل مشکلات با فرصت طلبیها و سوء استفادهها و بیانصافیها هم فشار وارده را بر کاربران iOS بیشتر کردهاند و هم وضعیت و بهانههای بیشتری به دست شرکت اپل میدهند! این واقعیتی است که باید پذیرفت (به گونهای که در شرایط اقتصادی کنونی هم فشار از خارج هم داخل بر ملت ما وارد است). کاش منصفانه به فکر راه حلهای مشکلات کنونی باشیم... ملت ما در چنین شرایطی هر جا که به کمک هم شتاب کردهاند موفقتر بودهاند و خواهند بود (اما به روش درست نه غلط!!!). حال با در نظر گرفتن نقض قوانین صریح از سمت فروشگاههای ایرانی که به آن هم افتخار میکنند، آیا نباید انتظار داشت تا روزی اپل یا هر شرکت دیگری صبرش به پایان برسد و خیس و خُشک را باهم بسوزاند؟! بخشی از ادعاهایی که بزرگترین مرجع ایرانی (سیباپ) اپلیکیشنهای iOS ارائه شده است به صورت زیر میباشد: زمانی که دسترسی به هزاران اپلیکیشن خارجی با ارزش ۵۰،۰۰۰ دلار در کشور ما با افتخار حقوق توسعهدهنده و ناشر را زیر سوأل میبرد نباید انتظار داشت چنین تحریمهایی حق ماست؟ حال آنکه چنین فروشگاههایی جدیداً از محدودیتهای اخیر سوء استفاده کرده و حتی با وعدههای دروغین اقدام به فروش اشتراک ویژه میکنند که در ازای آن هیچ تضمینی از امنیت، حقوق مادی و معنوی و حتی اجرا شدن نرمافزارهای موجود در آن فروشگاه وجود ندارد! متأسفانه دروغها و فرصت طلبیها از چنین فرصتها به جای حل مسائل و اختلافهای سیاسی و تجاری چیزی به جز بدتر کردن وضعیت کنونی نخواهد داشت. حتی هیچ شانسی برای بهتر شدن وضعیت کنونی باقی نخواهد ماند. نقل قول زیر از طرف سیباپ است که ادعا کرده است با پرداخت اشتراک شما قادر به دانلود بدون مشکل اپلیکیشنها خواهید بود. راه حلهای ناشیانه و واقعا مسخره که از طرف فروشگاهها و نویسندگان خبری اخیر به دستمان رسیده است به صورت زیر هستند: استفاده از نسخه وب اپلیکیشن حقیقت نفهته در پشت این راه حلها به این صورت است که یک فناوری به عنوان PWA یا همان (Progressive web applications) وجود دارد که همان نسخهٔ وب به شمار میآید! در واقع اپلیکیشنهای نوشته شده به این روش بسیار بدتر از حتی یک وبسایت کامل هستند و تنها به روشهای غیر بومی و خارج از محیط Xcode تحت فناوریهای وب مانند HTML, CSS و JavaScript توسعه داده میشوند. در نهایت هیچ ربطی به نسخهٔ اصلی و نوشته شده به روش طبیعی نرمافزارهای iOS ندارد و تنها نسخهٔ محدود شدهای از وبسایت خدماتی است که با حقههای فریبنده و کاملاً ناشیانه اقدام به ساخت میانبر و ایجاد آیکون بر روی صفحه گوشی شما میکنند که اینطور برداشت کنید نسخهٔ واقعی اپلیکیشن را نصب کرده اید!!! در حالی که بهتر است به جای آن از همان وبسایت استفاده کنید. مسخره است نه؟! دسترسی به برنامههایی که پیشتر از اپ استور دانلود کردهاید دسترسی به برنامههایی که پیشتر از اپاستور دانلود شده است روشی کاملاً مسخرهتر است که به شما پیشنهاد میدهد تا نسخههای قدیمی اپلیکیشنهایی که اپل آنها را نگهداشته است اما توسعهدهندهگان آنها هم نمیتوانند آن را بهروز رسانی کنند استفاده کنید! این کار چه فایدهای دارد دقیقاً؟ تعداد اپلیکیشنهایی این چنینی بسیار محدود هستند مانند دیوار ... که آخرین بهروز رسانی آن به ۲ سال پیش مربوط است!!! جیلبریک کردن این روش ممکن است کارایی داشته باشد، اما تمامی مسائل امنیتی و خدماتی که اپل آنها را ارائه میکند را از بین برده و در واقع در این روش هیچ تضمینی برای حفظ اطلاعات و صحت عملکرد دستگاه شما وجود ندارد (در واقع شما از روش بسیار خطرناک از بین هزاران حفرههای شکافته شدهٔ امنیتی عبور کرده و از برنامهٔ مورد نظرتان که شاید آن یک اپلیکیشن بانکی و ... باشد استفاده میکنید). راه حل سیب اپ (بزرگترین فروشگاه ایرانی برای برنامه های iOS) این پیشنهاد زمانی معتبر است که فروشگاه و یا فروشگاههای مربوطه با شفافیت کامل بیان کنند که راهحلهای فعلی هیچکدام نهایی نیست و اصلاً مخصوص کاربر نیست!!! چرا که مشتری نه توسعهدهنده است و و نه شرکت! بنابراین زمانی که با حرکتهای ظاهراً حرفهای اما در حقیقاً کاملاً غیر حرفهای از هر کاربر یک توسعهدهنده یا شرکت و یا سازمان میسازند طبیعی است که باید هزینههایی مانند ۹۹ تا ۲۹۹ دلار در سال را بپردازند که مسلماً منجر به پولی شدن حق نصب اپلیکیشن خواهد بود که از بیخ غلط است! بنابراین انتظار میرود تحت هیچ شرایطی مردم را نَفَهم فرض نکنیم! مطمئنان هر عقل سلیمی میتواند تشخیص دهد که این روش دقیقاً همان مثال معروف (ماهی گرفتن از آب گلآلود است) در واقع شما باید پول به چیزی بپردازید که خودش روش غیرقانونی و نامناسب است!!! برخی از توسعهدهندگان و سایتهای خبری و حتی استورها چنین ادعا میکنند که هیچ محدودیتی در توسعه و انتشار برنامههای iOS وجود ندارد، آیا این حقیقت است؟ طبق توضیحاتی که در بالا اشاره کردم، هیچ روش منطقی در داخل کشور وجود ندارد که قانونی باشد، اگر کسی مدعی به انتشار است مطمئنان از همین روشهایی که اشاره شد استفاده میکند که خارج از این نیست. فروشگاههای جدید و مدعی بدون محدودیت چگونه کار میکنند؟ متأسفانه با وجود شرایط کنونی و محدودیتهای اپل افراد و فروشگاههای زیادی در چندین ماه اخیر ایجاد شدهاند که از این فرصت برای ارائه خدمات به شیوهٔ PWA و دو روش دیگر که ذکر شد استفاده میکنند که هیچ یک از آنها ارائه دهندهٔ خدمات واقعی نیستند. (اگر شما فروشگاهی را میشناسید که از روشهای قانونی برای نشر برنامهها استفاده میکند که نیاز نباشد هر چند وقت یک بار برنامه را حذف و دوباره نصب کنند و یا در بهترین حالت شما را به عنوان توسعهدهندهٔ اپل معرفی نکنند به ما معرفی کنید تا به گوش همگان برسانیم!). روشهای پیشنهادی و رسمی اپل چیست؟ طبق اسناد رسمی، اپل میگوید اگر شما برنامهٔ خودتان را به صورت استاندارد توسعه دادهاید میتوانید به دو روش آن را منتشر کنید؛ روش اول این است که آن را در فروشگاه اپل منتشر کنید (که در این روش بنابر اساس سیاستهایی که دارند مسلماً تحریم ما خواهد بود که شاهدش بودیم - حذف اپلیکیشنهای ایرانی از فروشگاه اپل). روش دوم آن است که شما اپلیکیشن خود را در قالب روشهای Ad-Hoc ایجاد کنید که محدود بر ۱۰۰ دستگاه (کاربر) خواهد بود. این روش نیز به گونهای قابل استفاده است اما محدود بر تعداد کاربران خواهد بود و برای اهداف داخلی و سازمانی خودمان طراحی شده است و بدون شک امضاء و مدیریت آن همراه با تولید آمار بسیار زیادی از تأییدیهها سرسام آور خواهد بود. درواقع اپل میگوید اگر میخواهید در دامنهٔ بزرگتر یعنی جهان، استفاده کنندهٔ اپلیکیشن شما باشد باید در فروشگاه من آن را منتشر کنید تا هم امنیت و هم پشتیبانی آن را تضمین کنم. روشهای دیگر نیز با عنوان (Enterprise Program) مطرح هستند که مخصوص تیمهای توسعهای که در برنامه Enterprise یا همان تجاری ثبت نام کردهاند نیز میتوانند از توزیع داخلی استفاده کنند. این روش همان روشی است که اپل برای عموم اکثراً محدود کرده است و مختص تحریمهای ایران نیست. درواقع همان روشی که بعضی از شرکتهای ایرانی هر روز میگویند اپلیکیشن را از لینک جدید دریافت کنید!!! که البته همراه با هزینهٔ سالانه ۲۹۹ دلار است! روشهای محدودتر دیگری وجود دارد که کاربران با محدودیت بیشتری با آن میتوانند برنامهها را صرفاً برای مصارف ازمایشی و خودمانی استفاده کنند که این دسته با عنوان University Program شناخته شده اند و توانایی نشر برنامه به جامعهٔ هدف بزرگتری را نخواهند داشت. با توجه به این تعاریف مشخص است که دو روش پیشفرض استاندارد و Ad-Hoc باقی مانده است. تکلیف روش اول مشخص است که تا زمانی که تحریمها وجود دارد نباید انتظار داشت که در اپاستور بتوان اپلیکیشنهای ایرانی را بارگذاری کرد. اما روش ادهاک همان روشی است که اجازه میدهد با خرید و ثبت دستگاه در بانک گواهیهای معتبر اپل اپلیکیشنهای خود را به مدت ۱ سال یا بیشتر امضا کنید (این روش برای توسعهدهندگان) پیشنهاد شده است که احتمالاً روشهای فعلی استورها این باشد! مسلماً این روش هزینهٔ شارژ و امضای توسعهدهنده را خواهد داشت. البته لازم به ذکر است این روش قطعی نیست و اگر اپل بداند که به زودی هم خواهد دانست میلیونها کاربر توسعهدهنده پیدا کرده است! مسلماً طی اقداماتی روشهایی برای حل آن ارائه خواهد داد. خب راه حل منطقی چیست؟ با توجه به مستندات و منابع رسمی که اعلام کردهاند، از اولین ساعتهای مسدود شدن نرمافزارهای بانکی و پرداختی، شرکتهایی که در این مجموعه اپ یا اپهایی داشتند؛ راهحل موقت خود را ارایه کردند، عمدهترین راهحل استفاده از اپهای مسدود شده روی گوشیهای آیفون، مراجعه به نسخه وب اپلیکیشن یا استفاده از پلتفرمهای دیگری مانند اندروید است. مدیران اسنپ و دیجیکالا از کاربرانشان درخواست کردند به طور موقت نسخه وب آنها را استفاده کنند تا مشکل حل شود. برخی شرکتها مانند سیباپ و تپسی، نسخه جدید و مجزایی از اپاستور ارایه داده و از کاربرانشان درخواست کردند این اپلیکیشن را از روی سایت آنها دریافت و نصب کنند. سیباپ در پیامهای ویدیویی و اطلاعیه رسمی، به کاربران خود وعده داده است بهزودی نسخه جدیدی از اپلیکیشن سیباپ ارایه خواهد شد که دیگر مشکل مسدود بودن یا عدم اعتبارسنجی توسط اپل را ندارد (که این روش زمانی قابل تأیید خواهد بود که به روشهایی غلطی که در بالا اشاره شد عمل نشود و رسالت و شعارهای فریبانهٔ خود را تغییر دهند) که مسلماً باید اول حقوق مادی و معنوی و حریم خصوصی مصرف کننده را تضمین کنند و در نهایت به روشهای قانونی مجوزهای لازم را از اپل دریافت کنند که با توجه به شرایط حاکم کمی غیر ممکن و دور از انتظار است!!! روشهای بهتری جهت نصب و راهاندازی اپلیکیشنهای ایرانی وجود دارد که با نامهای Add-Hoc نیز معروف هستند که محدود به نوع توسعهدهنده و تجاری معرفی میشوند. البته روشهای تجاری همان روشهایی است که سیباپ و دیگر شرکتها مورد استفاده قرار دادهاند. اما روش روش نوع توسعهدهنده میتواند با در نظر گرفتن ثبت دستگاه شما در پروفایل این مشکل را تا حدی برطرف کند که فروشگاههایی مانند اناردونی با در نظر گرفتن هزینهٔ ثبت دستگاه آن را تا به مدت ۱ سال تضمین میکنند. روش درست و صحیحتر آن است که دقیقاً طبق قوانین اپل عمل شود، در واقع تمامی مادهها و تبصرههای عنوان شده توسط شرکت اپل در اپاستور را باید پذیرفت. اما مشکل اصلی و اساس این مشکلات این است که اپل قبلاً هم گفته است حاضر به ارائهٔ خدمات به ایران نیست. (یاد شعار استیو جابز مرحوم افتادم که ما خواهیم گفت کاربر از چه چیزی باید استفاده کنند نه آنها) در واقع اپل با این اقدامات و فشارهای خود رسماً میگوید شما بهتر است از محصولات دیگر استفاده کنید که عمل زشت و بسیار نژادپرستانه است. آیا فروشگاههای داخلی به داد مردم میرسند یا از آب گلآلود ماهی میگیرند؟ قضیه این است!!! خوشبختانه در حالت عادی خدمات فروشگاههای داخلی خوب به نظر میرسد، اما وقتی به واقعیتهای آنها میپردازیم میبینیم که فرصتهای خوبی برای پول به جیب زدنهای خیلی خوشگل فراهم شده است که هرچند برای فراهم سازی بستر آن باید زحمت کشید و پول خرج کرد... اما در ازای چه خدماتی چه چیزی به دست میآورند؟ وقتی به خدماتی قرار است پولی پرداخت شود، آن سرویس باید بدون هیچ دغدغه و مشکلات مادی و معنوی قابل استفاده باشد. با توجه به عدم شفاف سازی کاربران که دلیل آن را نداشتن دانش فنی میدانند. از جانب بعضی از توسعهدهندگان و فروشگاههای ایرانی ترجیح دادهشده است که، خدمات ارائه شود اما با دریافت هزینه! کافی است یک حساب کتاب ساده انجام دهید، وقتی شما قرار است توسعهدهندهٔ اپل باشید باید هزینهٔ سالیانه آن را پرداخت کنید که چیزی حدود ۹۰ تا ۱۲۰ دلار بسته به مالیات متغیر است. و اگر قرار است امضاء از نوع سازمانی داشته باشید باید هزینهای معادل ۲۹۹ دلار برای آن بپردازید که در نهایت هر ۱۰ الی ۲۰ روز یک بار هزینه نزدیک به ۳ میلیون تومان برای خرید اکانت تجاری باید تقدیم کنید! در قبال آن به دست آوردن برخی از فروشگاهها مانند سیباپ هزینهی حداقل ۳۰،۰۰۰ تومان را بابت آن دریافت میکنند. به گفتهٔ خودشان تعداد کاربران میلیونی... با پرداخت چنین هزینههایی معادل صدها شاید هم هزاران و میلیونها برابر آن را به دست خواهند آورد!!! فرصت خوبی برای راهاندازی کسبوکار و به قول قدیمیها (ماهی گرفتن از آب گلآلود) است نه! البته فروشگاههایی هم وجود دارند که با روشهای PWA ادعای به اشتراک گذاری اپلیکیشنها را دارند که از اشاره به نسخه وب بودن و محدودیتهای آن دریغ میکنند. اخیراً هم که با حقهبازیهای هرچه تمام هزینههای چند برابری با وعدههای دروغین به مردم خدمات میدهند که شخصاً با خرید حساب ۱ ساله بعد از ۳ ماه دوباره از ما پول خواستن! حالا که در جریان واقعیت قرار گرفتهاید، بهتر است خودتان قضاوت کنید (چرا که به عنوان یک برنامهنویس این ننگ است که بدانیم اما به زبان نیاوریم که چه چیزی به خُرد ملت میدهیم). آیندهٔ نرمافزارهای iOS ایرانی چطور خواهد شد؟ شما کاربران عزیز باید در نظر داشته باشید که هیچ روش رسمی و قانونی به جز مواردی که اشاره شده است وجود ندارد، مشخص نیست با این وضعیت چه بلایی به بازار اپلیکیشنهای ایرانی در پلتفرم iOS خواهد آمد، اما با توجه به مسائل سیاسی که دولت ایالات متحدهٔ آمریکا اعمال کرده است و تمامی تحریمهای بانکی و ... از قبل گریبان گیر ما شده است کمی بعید است بدون حل مسائل سیاسی این دو کشور به این راحتی ها بتوان راه حلهای دائمی و مطمئن معرفی کرد. بنابراین، باید منتظر ماند تا دید آیا نظر اپل در این بهانه تراشیها تغییر خواهد کرد یا خیر! البته بر اساس نظرات کارشناسی برخی از حقوقدانها و سیاستمداران اینطور عنوان میشود که شرکتها بعضاً مجبور هستند بر خلاف میل خود طبق دستورات دولت خودشان اقدام کنند. در نهایت، باید منتظر ماند و دید که آیا حتی با پذیرفتن هزینههای بسیار بالا و رعایت قوانین کامل اپل باز هم اقدام به مسدود کردن برنامههای ایرانی خواهد کرد یا خیر. هدف از این مقاله این است که با چشمان باز حقیقت پنهاد در پشت این مسائل را بدانید.
-
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 امتیازبرنامهنویس تنها در این عنوان خلاصه نمیشود و لازم است بدانید که برنامهنویسان در چند دسته متفاوت وجود دارند که برخی از آن ها به صورت Back-End و برخی Front-End فعالیت میکنند. در کل به کسانی که توانایی برنامهنویس در بخش Back-End را دارند به آنها Back-End Developer میگویند. همچنین برنامهنویسانی که توانایی توسعه در بخش طراحی رابطکاربری و تجربهکاربری را با عنوان Front-End دارند Front-End Developer میگویند. در نظر داشته باشید که توسعهدهندگان و طراحان بخش تجربهکاربری (UX) و رابطکاربری (UI) خود وظایفی در سمت طراحی یک محصول را دارند که به خودی خود میتوانند به عنوان توسعهدهندهی فرانتاِند محسوب شوند اما ممکن است زمینهی اجرایی آنها با محیطهای توسعه که شامل کدنویسی هستند نباشد! بنابراین شاخهای از حوزهی توسعه در نرمافزار کامپیوتر وجود دارد که میتواند با ترکیب دانش طراحی و کدنویسی و تسلط کامل بر این دو حوزه به صورت ترکیبی با دانش و توانایی بسیار بالا عنوان شود که به آن فولاِستک میگویند. البته فولاِستک ابعاد مختلفِ خود را دارد، برای مثال ممکن است یک توسعهدهندهی فولاِستک تنها در پلتفرم اندروید توانایی طراحی و کدنویسی را به صورت همزمان و بدون نیاز به یار تیمی خود داشته باشد. اما در اصل توسعهدهندههای با تجربه با سابقهی بالا که توانایی مدیریتی پروژه و توسعهی آنها را دارند از نوع فولاِستک تمام عیار محسوب میشوند که در ادامه به ویژگیهای آنها اشاره شده است. یک برنامهنویس حرفهای یا همان فولاِستک میبایست مهارتهای زیر را داشته باشد: مسلط به زبانهای برنامهنویسی پایه آشنایی با UX و UI و مباحث مرتبط با هر یک از آنها مدیریت پروژه بر روی پلتفرمهای مختلف توانایی کنترل کیفیت محصول توانایی کار با انواع فناوریها و کتابخانهها توانایی کار با انواع دیتابیس و مدیریت آنها هک و امنیت بهینه سازی موتورهای جستجو آشنایی و توانایی درک و مدیریت کامپایلرها و مفسرها درک نیازهای کاربران در محصول (UX) آشنایی با سیستم عاملهای مختلف آشنایی و توانایی تولید محصول به صورت چند-سکویی (Cross-Platform) آشنایی با شبکه و پیکربندی آن برای محصول آشنایی با مدیریت سرور و هاستینگ آشنایی با سیستمهای مدیریتی و مجازی مانند VM آشنایی با سخت افزار آشنایی با رابط های برنامه نویسی APIها آشنایی با انواع محیطهای توسعه و موارد دیگر که در یک پروژه از صفر تا صد میتوان به آنها نیاز پیدا کرد. برنامهنویسان Full-Stack Developer به تنهایی میتواند درتولید و توسعه یک محصول موثر باشد و زمانی که با مشکلی مواجه شوند نمیگوید من آن را بلد نیستم، بلکه حتماً آن را حل خواهند کرد. به طور کلی کسب مهارت در سطح بالا در حد یک توسعه دهنده فولاِستک بسیار سخت است اما نباید بگوییم که غیر ممکن است، در صورتی که چنین تعریفی برای یک توسعهدهندهی فولاستک در نظر بگیریم، بدون اغراق باید گفت تعداد اندکی از این برنامهنویسان موجود است که بتوانیم چنین لقبی را به آنها اختصاص بدهیم بنابراین چنین برنامهنویسانی بسیار ارزشمند هستند لذا به خوبی میدانند یک نرم افزار چگونه طراحی میشود و توانایی این را دارند از صفر تا صد یک نرمافزار را طراحی و روانه بازار کنند. علاوه بر این توسعه دهنده Full-Stack کسی است که واژگانی مانند نبود، نمیشه، امکان نداره، نمیتوم، کار من نیست و ... را بر زبان نمیآورند و اگر هم چیزی را ندانند تمام تلاش خود را میکنند تا بدون نیاز به کمک شخصی دیگر آن را حل کنند. این نوع توسعهدهندهها بسیار با ارزش و مهم هستند، و نکته جالب اینجاست که آنها سالها تلاش کردهاند و مسلماً به تنهایی صاحب کسبوکار خود بوده و در انتخاب اول برای کسی کار نمیکنند. برای توسعه دهندهی فولاِستک فرقی نمیکند محصول تحت چه پلتفرمی باشد، او میتواند تحت دسکتاپ، وب، موبایل و دیگر پلتفرم ها آن را تولید کند.
-
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 امتیاز
-
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 امتیاز
-
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 امتیازداخل یک ترد غیر از ترد اصلی برنامه تمام فایلها رو rename کنید. زیاد کردن تعداد تردها برای عملیات IO روی فایل خصوصاً در این مورد هیچ کمکی نمیکنه که هیچ، به احتمال زیاد سرعت رو هم پایین میاره.
-
3 امتیاز
نگارش 1.69.0
58 دریافت
کتابخانه Boost منبعی از کتابخانههای قابل حمل و آزاد ++C را فراهم میکند که از اصطلاح Peer-Reviewed پشتیبانی میکند. ما بر این تاکید میکنیم، Boost کتابخانه ای است که به خوبی با کتابخانه ی استاندارد ++C کار میکند. بوست مجموعه ای از کتابخانههای برنامه نویسی برای زبان برنامه نویسی سی پلاس پلاس است که پشتیبانی از کارهایی مانند جبر خطی، ساخت اعداد شبه تصادفی, ریسهبندی, پردازش تصویر, عبارت باقاعده و آزمایش واحد را ارائه میدهد. بیشتر این کتابخانه ها تحت پروانه نرم افزار بوست منتشر میشوند که به بوست اجازه میدهد هم در یک نرم افزار آزاد و هم در یک نرم آفزار انحصاری استفاده شود. بسیاری از پدید آورندگان بوست عضو کمیته استانداردسازی سی++ هستند و چند کتابخانه بوست برای الحاق به استانداردهای TR1 و C++11 پذیرفته شده اند.رایگان