رفتن به مطلب
مرجع رسمی سی‌پلاس‌پلاس ایران

قاسم رمضانی منش

مدیران مرجع
  • تعداد ارسال ها

    97
  • تاریخ عضویت

  • روز های برد

    25

پست ها ارسال شده توسط قاسم رمضانی منش


  1. درود بر دوستان عزیز؛

    برای اضافه کردن یک کاراکتر به انتهای رشته شاید افراد به این‌صورت عمل کنند :

    string[ strlen(string) ] = char;

    امّا من خواستم بدون وابسته بودن این قسمت به libc؛ این عمل انجام شود به این‌صورت عمل کردم :

    int main (void){
        /* Define variable */
        char c = 'm';
        char* string = NULL;
    
        /* Allocating memory */
        string = malloc(7);
    
        /* Copy char into `string` */
        strcpy(string, (char*)"ghase");
    
        /* Append `c` to end of `string` */
        *((char*)(&string + 1) - 2) = c;
        *((char*)(&string + 1) - 1) = '\0';
    
        /* Result */
        printf("%s\n", string);
    
        return EXIT_SUCCESS;
    }

    امّا با سیگنال SIGSEGV در تابع __strlen_sse2() هنگام فراخوانی printf() مواجه می‌شوم، کلاً حافظهٔ دریافتی از طریق Derefrence کردن string مقادیرش قابل دسترسی نیست (پیغامی که GDB نشان می‌دهد). ولی همچنان می‌توانم به‌اینصورت به مقداردهی که کرده‌ام دسترسی داشته‌باشم :

    printf("%c\n", *((char*)(&string + 1) - 2));

    الآن چه اتفاقی برای حافظهٔ متغیر string می‌افتد ؟


  2. درود و خسته‌نباشید به دوستان؛

    می‌خواهم حالتی را مانند RadioButton که فقط می‌توان «یکی‌ از چندتا» را انتخاب کرد را در دکمه‌هایی که خودم نوشته‌ام پیاده کنم، در حالت عادی به این‌صورت عمل کرده‌ام و خب مشخصاً راه‌حل خوبی نیست استفاده از تابع ()fundOutAndTurnOnButtonLight؛ به چه روشی می‌توان بهتر عمل کرد ؟

    main.qml

    ApplicationWindow {
        id: root; visible: true
        width: 640; height: 480
        color: "gray"
    
        function findOutAndTurnOnButtonLight(id){
            switch(id){
            case pageOne:
                pageTwo.isSelected   = false
                pageThree.isSelected = false
                break
            case pageTwo:
                pageOne.isSelected   = false
                pageThree.isSelected = false
                break
            case pageThree:
                pageOne.isSelected   = false
                pageTwo.isSelected   = false
                break
            }
            id.isSelected = true
        }
    
        Row{
            id: kepper
            anchors.centerIn: parent
            spacing: 20
            MyRec{
                id: pageOne
                onButtonClicked: findOutAndTurnOnButtonLight(pageOne)
            }
            MyRec{
                id: pageTwo
                onButtonClicked: findOutAndTurnOnButtonLight(pageTwo)
            }
            MyRec{
                id: pageThree
                onButtonClicked: findOutAndTurnOnButtonLight(pageThree)
            }
        }
    }

    و کامپوننت MyRec که در فایل MyRec.qml می‌باشد :

    Item {
        id: root
        width: 100; height: 100
        property bool isSelected : false
        signal buttonClicked()
    
        Rectangle{
            id: myButton
            anchors.fill: parent
            color: "red"
            width: parent.width / 4
            height: parent.height / 4
        }
    
        Rectangle{
            id: bar
            anchors{
                bottom: myButton.bottom
                horizontalCenter: myButton.horizontalCenter
            }
            color: "blue"
            width: myButton.width / 2
            height: 5
            visible: isSelected
        }
    
        MouseArea{
            id: clickableArea
            anchors.fill: myButton
            onClicked: buttonClicked()
        }
    
        states:[
            State{
                name: "entered"
                when: clickableArea.pressed
                PropertyChanges{
                    target: myButton
                    color: "yellow"
                }
            }
        ]
    }

     


  3. درود و خسته‌نباشید به دوستان؛

    در مستندات RadioButtonStyle مثالی به این‌صورت زده شده :

    RadioButton {
        text: "Radio Button"
        style: RadioButtonStyle {
            indicator: Rectangle {
                    implicitWidth: 16
                    implicitHeight: 16
     				...
            }
            ...
        }
        ...
    }

    امّا RadioButton خاصیّتی تحت عنوان style ندارد، آیا این مثال اشتباه است ؟ و چگونه می‌توان از RadioButtonStyle استفاده کرد ؟

    این مورد دربارهٔ CheckBoxStyle نیز صدق می‌کند.

     

    ویرایش:

    باتوجه به مستندات :

    Import Statement: import QtQuick.Controls.Styles 1.4
    Since: Qt 5.1

     

    قابلیّت style در ویرایش 1.4 از ماژول QtQuick.Controls.Styles موجود می‌باشد، و پس از import کردن آن خطا رفع می‌شود. آیا اضافه کردن نسخهٔ 1.4 و 2.13 تداخلی به وجود می‌آورد ؟

    • پسندیدن 1

  4. درود و خسته‌نباشید به دوستان؛

    درحال طراحی یک رابط‌کابری‌ساده بوده‌ام که خواستم قسمت رنگ‌آمیزی Itemها و Fontها و ... به راحتی قابل تغییر و برنامه‌ریزی باشد. اینکار را با استفاده از یک فایل QML جدا به اسم Style.qml به شکل زیر انجام دادم :

    pragma Singleton
    import QtQuick 2.13
    
    Item {
        property int   textinputTextSize : 22
    
        property color transparent    : "transparent"
        property color bluredColor    : "#5AAFAAAA"
    
        property int   tabBarWidth    : 50
        property int   tabBarHeight   : 75
        property int   tabBarIconSize : 44
        property int   tabBarTextSize : 20
        property color tabBarIconColor: "#81D8DE"
        property color tabBarTextColor: "#059EAB"
        property color tabBarBackColor: "#0571AB"
    
        property alias sahelRegular : sahel_font.name
        property alias fontAwesome  : font_awesome.name
    
        FontLoader{
            id: sahel_font
            source: "qrc:/assets/fonts/sahel/Sahel-FD-WOL.ttf"
        }
        FontLoader{
            id: font_awesome
            source: "qrc:/assets/fonts/awesome/fontawesome-regular.ttf"
        }
    
        property color mainpageColor        : "#E3F2FD"
        property color mainpageToolbarColor : bluredColor
    }

    آیا این روش بهینه و درست است ؟ و یا راه بهتری هم وجود دارد ؟

    • پسندیدن 1

  5. درود بر شما؛

    برای اینکار می‌توانید شما از 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 فراخوانی کنید.

    خروجی حاصل از کد بالا :

    image.png.57351ca66ea6ae29af412f60586841df.png

    با تشکر از آقای‌رضوی.

    • پسندیدن 2
    • تشکر شده 2

  6. @nabegheh95 درود بر شما؛

    در در 9 مرداد 1398 در 14:06، nabegheh95 گفته است :

    من سالهاست تجربه کار با ویژوال استودیوC++  رو دارم ولی به تازگی میخوام شروع کنم Qt را یا بگیرم.

    لازم به ذکر بود که، برنامهٔ Microsoft Visual Studio یک IDE توسعه داده شده توسط شرکت Microsoft می‌باشد. و برای توسعهٔ هرچه بهتر برنامه‌های سیستم‌عامل Windows تحت Microsoft .Net می‌باشد. درواقع شما با کامپایلر Microsoft Visual C++.Net کارکردید.

    برای فریمورک Qt هم یک IDE بسیارعالی وجود دارد که سرعت توسعهٔ نرم‌افزار با استفاده از این فریمورک را افزایش می‌دهد، پس پیشنهاد می‌کنم به جای استفاده از آن افزونه مستقیم از این IDE استفاده کنید چرا که یک IDE بسیار خوب نیز برای ++C\C می‌باشد.

    تنها پیشنهاد می‌شود که در سیستم‌عامل Microsoft Windows از کامپایلر Microsoft Visual C++.Net استفاده کنید، این کامپایلر برای سیستم‌عامل خود به خوبی عمل می‌کند. هرچند که باید حواستان به تنبلی‌های مایکروسافت باشد مواردی مثل مورد زیر اصلاً پیاده‌سازی نشده‌اند:

    void char_exception() throw(int){
        throw 'x';
    }
    
    int main(void){
        try{
            char_exception();
        }
        catch (...){
            std::cout << "Caught it." << std::endl;
        }
        return 0;
    }

    توضیح.

    در در 9 مرداد 1398 در 15:43، nabegheh95 گفته است :

    چون خیلی تازه شروع کردم به یادگیری Qt، بعضی جاها مبهم هست برام .

    فریمورک Qt یک مجموعهٔ عظیم از کتابخانه‌ها می‌باشد، که تماماً نیز در این‌سایت مستند شده‌اند. برای رفع ابهامات کافی است که مستندات را به دقّت مطالعه و نمونه‌های نوشته شده را بررسی و امتحان کنید.

    در در 9 مرداد 1398 در 15:43، nabegheh95 گفته است :

    ولی به طور کلی فهمیدم که برای اجرایی شدن برنامه نهایی در هر سیستم عامل

    اجرا شدن یک فایل، بسته به کرنل یک سیستم‌عامل و نحوهٔ پیاده‌سازی آن می‌باشد. پس مسلماً ساختاری که در کرنل Windows NT به عنوان فایل اجرایی شناخته شده است، در کرنل Linux قابل قبول نیست.  برای اطلاعات بیشتر درمورد این ساختارها می‌توانید ساختار PE و ELF را بررسی کنید.

     

    در در 9 مرداد 1398 در 15:43، nabegheh95 گفته است :

    و همیشه سعی براین داشته باشم که فقط و فقط از توابع و apiهای خود Qt استفاده کنم

    در حالت ایده‌آل، بلی باید تلاش داشته‌باشید که از APIهایی که Qt فراهم می‌کند استفاده کنید، امّا همیشه این کار شدنی نیست. شما همیشه نیازی به استفاده از Qt‌ ندارید و ممکن است قابلیّتی در یک سیستم‌عامل نیاز داشته‌باشید که مشابه آن در یک سیستم‌عامل دیگر متفاوت هست. برای مثال :

    image.png.a819715d17876c21c1821d14772098ae.png

    این سورس Telegram/ThirdParty/minizip/ioapi.c هست، ببینید به چه صورت در خط‌های ۱۳ و ۱۷ و ۲۲ بسته به سیستم‌عامل مقصد مشخص کرده‌است که چه توابعی باید کامپایل شوند. با این روش شما درحالی که از قابلیّت خاص یک سیستم‌عامل استفاده کردید ولی برنامهٔ شما Cross-Platform می‌باشد.

    پیشنهاد می‌کنم کتاب «++API Design For C» نوشتهٔ آقای «Martin Reddy» را مطالعه کنید.

    • پسندیدن 1

  7. @Alireza4 درود؛

    اینکه چه کاری انجام بدهید و به کدام راه برید، تماماً بستگی به خودتان دارد. پیشنهاد می‌کنم که قشنگ درمورد کاری که می‌خواهید انجام بدید تحقیق کنید :

    - هدفتان از برنامه‌نویسی چیست ؟

    - چقدر حوصلهٔ یادگیری مطالب را دارید ؟

    - چقد دید سیستمی به برنامه‌نویسی دارید ؟

    و ..، این مطلب را حتماً مطالعه کنید : کدام زبان برنامه‌نویسی را انتخاب کنم ؟ ، در این مقاله توضیحات لازم داده شده که بتونید خودتان تصمیم بر انتخاب زبان بگیرید. چرا که باید بدونید «درسته‌که زبان سی‌پلاس‌پلاس قدرت زیادی داره» امّا باید بدونید که هرچیز خوبی بالاخره هزینه‌ای هم داره و یادیگری کار کردن با این زبان به شش‌ماه تموم نمیشه، برای اینکه دراین‌باره هم بیشتر اطلاعات کسب کنید مقالهٔ چرا و چگونه باید ++C را یادبگیریم ؟ ، شاید اصلاً چیزی نبود که شما فکر می‌کردید.

     

    • تشکر شده 1

  8. سلام؛

    خوش‌آمدید، لطفاً ده-دقیقه وقت بگذارید و اسناد زیر را جهت فعالیت در انجمن مطالعه بکنید :

    در 5 ساعت قبل، MahdiGameMaker گفته است :

    نظرتان درمورد گنو/لینوکس چیست ؟ می‌خواهم کار با این سیستم‌عامل را شروع کنم، پیشنهادتان چیست ؟

    سیستم‌عامل گنو/لینوکس، یک سیستم‌عامل آزاد - متن‌باز می‌باشد، که می‌توانید به رایگان آن را دریافت و استفاده کنید :

    نسخه‌های متعدد و زیادی از سیستم‌عامل‌های گنو بر پایه کرنل لینوکس موجود می‌باشد که می‌توانید هرکدام را به رایگان دریافت و استفاده بکنید :

    جهت شروع آشنایی کار با این سیستم‌عامل‌ها می‌توانید از این دورهٔ آموزشی آقای‌میر‌میرانی شروع کنید :

    در 5 ساعت قبل، MahdiGameMaker گفته است :

    اگر بخوام برم سراغ گنو/لینوکس باید دوباره کل SDK و NDK و JDK برای لینوکس دانلود کنم؟

    نیازی به بارگیری SDK و NDK دوباره نیست، ولی برای JDK بسیار بهتر می‌باشد که از طریق مدیربستهٔ توزیعتان اقدام به نصب آن کنید که اختلالی پیش نیاید. مطمئن شوید که این سند را نیز مطالعه کردید :

    • پسندیدن 1

  9. در در 10 اردیبهشت 1398 در 10:04، Saman گفته است :

    من  component WebEngine رو فعال کردم و QT += webview رو هم به فایل pro. اضافه کردم 

    سلام؛

    مطمئن بشید که از نسخهٔ درست استفاده می‌کنید و اینکه این ماژول برای شما ساخته (بیلد) شده باشد؛ درغیراینصورت باید خودتان بسازید. اگر می‌خواید از دل‌متن مقداری را بیرون بکشید بهترین‌کار این است که از QRegExp استفاده کنید.


  10. سلام؛ بد نبود اگر نیَّت شما توسعهٔ‌نرم‌افزارهای-اندروید بوده،‌ از همان فناوری QtQuick استفاده می‌کردید.

    خب، برای آشنا شدن به مباحث و روش استفاده از Layoutها تنها راه این‌است که از همان پیوندی‌که آقای‌اسدزاده دادند :

    https://doc.qt.io/qt-5/layout.html

    شروع کنید و مطالعه‌کنید، خوش‌بختانه این‌بخش‌هم دارای مثال‌های خوبی هست که می‌تونید با تمرین و تست‌وخطاهایی نتایج خوبی بگیرید. کافیه‌که کاربرد هر Layout را متوجه شده و بدانید که در کجا باید استفاده کنید.

    قطعه‌ وید‌ئوهایی هم داخل youtude موجود می‌باشد که دیدنش بدنیست :).

    • پسندیدن 1

  11. سلام؛

    این سوأل شما بسیار بسیار کلّی هست ! ، تا قسمت نوشتن برنامهٔ‌خود که مرتبط به زبان‌برنامه‌نویسی سی‌پلاس‌پلاس هست. ولی قسمت کامپایل و اجرای آن برنامه به عهدهٔ سیستم‌عامل شماست؛ بهتر بود که ذکر کنید از چه سیستم‌عاملی و چه نسخه‌ای استفاده می‌کنید. حال بنده به صورت کلّی توضیحاتی می‌دهم امیدوارم مفید باشد :

     

       - درصورتی‌که از سیستم‌عامل‌های GNU/Linux استفاده می‌کنید، شما باید مستندات دسکتاپ خودتان را بررسی کنید هر دسکتاپی که استفاده می‌کنید بنا به قواعد خودش فایل‌ها/دستوراتی را در شروع دسکتاپ اجرا می‌کند. امّا اگر دسکتاپی ندارید ولی از X استفاده می‌کنید، بهتر است یک فایل .desktop درست کنید و آن را در یکی از این مسیرها قرار بدهید :

    User : ~/.config/autostart

    SystemWide : /etc/xdg/autostart

    نمونه‌های از قبل نوشته‌ شدهٔ فایل‌های .desktop را می‌توانید در این آدرس پیدا کنید و یا یکی را خودتان بنویسید :

    User : ~/.local/share/applications

    SystemWide : /usr/share/applications 

    اگر از مدیرپنجره‌هایی مثل i3wm یا awesome استفاده می‌کنید، می‌دانید که این‌ها فایل‌های پیکربندی مختص به خود دارند که در آنها نیز می‌توانید دستورات اجرایی خودتان را قرار بدید.

     

       - درصورتی‌که از سیستم‌عامل Mac OS استفاده می‌کنید، به این لینک مراجعه کنید.

     

       - درصورتی‌که از نرم‌افزار مایکروسافت‌ویندوز استفاده می‌کنید، منوی Start را باز کرده و ابزار Run را اجرا کنید - می‌توانید این‌کار را با زدن دکمه‌های WinKey + R خلاصه‌کنید - و بعد عبارت:

    shell:startup

    را وارد کنید، پنجرهٔ Windows Explorer باز می‌شود، هر فایلی که در آن دایرکتوری قرار بدهید در هنگام Login User اجرا می‌شود.

    • پسندیدن 1
    • تشکر شده 1

  12. سلام؛

    می‌توانید از QKeyEvent استفاده کنید، امّا این نیازمند gui است.

    برای محیط‌متنی می‌توانید خود یک کلاس برای شناسایی کلید زده شده بنویسید و آن را در یک QThread اجرا کنید تا زمانی که کلید مورد نظر شناسایی شد عملی که نیاز دارید انجام شود.

    - GNU Readline Library

    Detect Space Key


  13. سلام ؛

    Container :

    این اسامی‌ای که اسم بردید. تماماً Continer هستند. و وظیفه نگه‌داری داده‌هارا دارند. برای اینکه برنامه‌نویس دستش باز باشه در مدیریت داده‌ها در زبان برنامه‌نویسی سی‌پلاس‌پلاس می‌تونید از این کانتینرها در جهت نگه‌داری داده‌هاتون استفاده کنید. که استفاده از توابع و کلاس‌های موجود در هدرفایل algorithm در کنار این کانتینرها پیشنهاد میشود و می‌تواند قدرت کنترل بیشتری به برنامه‌نویسی بر روی داده‌های خود بدهد. که خود بسیار در پرفورمنس (به انگلیسی : performance) برنامه تاثیر دارد.

    Qt Container :

    از آن‌جایی که Qt یک فریمورک هست. برای اینکه برنامه‌نویسی به راحتی بتواند با کلاس‌ها و توابع این فریمورک تعامل برقرار کند ؛ Qt یک‌سری از مخازن (معادل فارسی کانتینر) را بازنویسی کرده‌است. که می‌توانید در این لینک بیشتر در این‌‌باره مطالعه کنید.

     

     

    • پسندیدن 1

  14. علیکم‌السلام ؛

    قبل از اینکه به پاسخ مستقیم سؤال بپردازیم ، بیاید درک کنیم چه شد که template ها نیاز برنامه‌نویس شد.

    این تابع را در نظر بگیر :

    int Sum (const int& first, const int& second){
        return first+second;
    }

    این تابع دو عدد از نوع int دریافت و حاصل جمع‌شون را بر می‌گردونه.

    خب ! حالا چه میشه اگه شما بخواید به جای int نوع double ارسال کنید ؟ و برنامهٔ شما با انواع مختلفی داده نیاز داشته باشه که با این تابع کار کنه. شاید بگید خب یک تابع دیگه با پارامتر و نوع بازگشتی double می‌نویسم.

    با این روش چه مشکلاتی پیش می‌آید :

    • کد تکراری.
    • بالا رفتن درصد خطای کد.
    • افزایش بی‌دلیل حجم کد.
    • سخت شدن مدیریت کد.
    • مشکل در آپدیت کردن سورس کد.
    • و ...

    زبان سی‌پلاس‌پلاس برای رفع این مشکل‌ما template ها را معرفی کرده است. template ها می‌توانند هر نوع داده‌ای را قبول کنن. تابع زیر ، تابع template بازنویسی شدهٔ تابع Sum است که در مثال بالا نوشتیم  :

    template <typename newType> newType Sum (const newType& first, const newType& second){
        return first + second;
    }

    ???خییییلی بزرگ شد ن ؟. خب می‌تونیم کوتاهش کنیم :

    template <typename newType>
    newType
    Sum (const newType& first, const newType& second){
        return first + second;
    }
    • نکته : می‌دانیم که کامپایلر فاصله‌هارا نادیده می‌گیره

    خب ! اوّل برای تبدیل تابع ، به یک تابع template باید از کلمهٔ کلیدی template استفاده کنیم. و بعد با استفاده از < > اسم نوع داده‌های جدیدمان را بنویسیم.

    • نکته : ما هیچ نوع دادهٔ جدیدی درواقع تعریف نمی‌کنیم. این تعریف فقط معرفی یک اسم به عنوان نوع داده‌ای هست که می‌تواند به هر چیزی اعم از int,double ,... تبدیل بشود.

    و داخل < > ما از کلمهٔ‌کلیدی typename برای تعریف اسم داده‌‌ استفاده کردیم. و همچنین می‌توانیم کلمهٔ‌کلیدی class نیز استفاده کنیم که هردو برابر یک دیگر هستن. امّا زمانی شما دارید templateی از template درست می‌کنید. مثلاً این نمونه :

    template < template <typename> class MyTmpClass, typename newType>

    اینجا دیگه نمی‌توانید بین کلمه‌کلیدی typename و class تفاوت قائع نشید. چرا که نیازه صراحتاً مشخص. امّا در استاندارد ۱۷ این مشکل وجود ندارد  ِ؛ ولی بهتر است که این تفاوت را اعمال کنیم.

    حال به راحتی می‌توانیم تابع را فراخوانی کنیم. به تکه کدزیر توجه کنید

    Sum (12 ,32);                               
    Sum (1'000'000'000'000,3212'333'233);
    Sum (std::string("ghasem") , std::string("ramezani"));
    Sum (12, 32.0);

    سه خط اوّل کد بدون مشکل کامپایل می‌شوند. الا خط ‌آخری. چرا که ما یک پارامتر با نوع int و یک پارامتر با نوع double‌ ارسال کردیم.

    برای حل این مشکل بیاید ببینیم که template ها به چه صورت کار می‌کنند. فرض کنید این تابع را فراخوانی کردیم :

    Sum ( int , int );

    وقتی کامپایلر به این تابع بر می‌خورد. تابع template مارا به این‌صورت برای ما بازنویسی می‌کند :

    int
    Sum (const int& first, const int& second){
        return first + second;
    }

    خب ! و وقتیما سعی می‌کنیم این تابع را فراخوانی کنیم :

    Sum ( int , double );

    برنامه کامپایل نمی‌شود و خطای زیر را ساطع میکنن. چرا که یک پارامتر Int و دیگری double هست. 

    ./main.cpp:5: candidate template ignored: deduced conflicting types for parameter 'newType' ('int' vs. 'double')

     

    آیا این شکل استفاده از توابع براتون آشنا نیست ؟ یه کم فک کنید :

    • std::vector
    • std::array
    • std::list

    تمام این کلاس‌ها ، template class هستند. و هر نوعی می‌توانند قبول کنند :

    #include <vector>
    #include <string>
    
    class myClass{
    public:
        myClass(){}
    };
    
    int main (void){
        std::vector <int> myIntger {1,2,3,4};
        std::vector <std::string> myString {"ghasem" , "ramezani"};
        std::vector <myClass>  myClassVector;
    
        return 0;
    }

     

    • نکته : این توضیح خیلی خلاصه از template ها و روش استفاده از آنها بود و به همین دو خط محدود نمی‌شوند.

     

    نقل قول

    ولی از آنجا که به نظر پیچیده می‌باشد

    و اینکه گفتید "به نظر پیچیده می‌باشد" ?. پیچیدگی در عین سادگی یکی از قابلیت‌های فوق‌العادهٔ زبان سی‌پلاس‌پلاسه?. اصلاً کد باید وحشت‌ناک باشه.?

     

     

    • ترکوندی! 1
    • تشکر شده 1

  15. با سلام.

    در نسخه‌های قدیمی Qt Creator امکان این وجود داشت ما به راحتی از کلاس‌هایی مانند QThread ارث‌بری کنیم.

    نقل قول

    که به گفتهٔ یکی از دوستان   استفاده از این روش درست نیست. چرا که ما قصد تعمیم کلاس QThread را نداریم.

    "How to use QThread in the right way (Part 1)" 1+1=10

     

    اما این قابلیت داخل نسخه جدید Qt Creator محدود به چند کلاس خاص اعم از QObject , QWidget , ... شده است. آیا روشی برای شخصی‌سازی این کلاس‌ها میباشد ؟


  16. با سلام.

    با توجه به اینکه محیط Qt Creator برای استفاده از QWidget یا Qt Quick یک محیط‌بصری هم تعبیه کرده است که کار را برای استفاده راحت‌تر کرده است. امّا واقعاً استفاده از این ابزار در پروژه‌های بزرگ درست  می‌باشد ؟ یا اینکه باید از برای کنترل بیشتر با استفاده از کدنویسی‌محض طراحی‌محیط را به عهده گرفت ؟ در این‌صورت ... وظیفهٔ اصلی این محیط طراحی چیست ؟

    - مثال‌هایی که خود Qt هم دارد ، بدون استفاده از محیط ویژوال طراحی شده است.


  17. مرسی از توضیحاتتون.

    بله اطلاع از کراس‌پلتفرم شدن MS SQL Server دارم... ولی خب مایکروسافت است دیگر ... .

    درمورد نیاز واقعی هم گفتم که برنامه حسابداری یه موسسهٔ آموزشی هست که فقط نیاز به ذخیره اطلاعات متنی هست... . این برنامه کلاینت هست و روی دسکتاپ و موبایل قرار خروجی گرفته بشه. که دیتابیس هم داخل سرور هست. و همزمان ممکنه حداکثر ده کاربر به دیتابیس دسترسی داشته‌باشن. و با توجه به توضیحات اطلاعات پردازشی سنگین نداریم.


  18. با سلام.

    معیار‌ها برای انتخاب یک دیتابیس برای یک برنامهٔ حسابداری چه چیزهایی میتواند باشد ؟ بنده درحال شروع نوشتن یک برنامهٔ حسابداری با استفاده از فریمورک Qt هستم. و وهله اوّل که درحال طراحی بخش‌های مختلف برنامه هستم نیاز به انتخاب یک دیتابیس دارم. که با وجود تنوع دیتابیس‌ها در این زمینه نیاز دانستم که نظر مابقی دوستان را در این زمینه بدانم.

    بنده برنامه‌‌ی حسابداری هلو را دیدم که از دیتابیس MS SQL Server استفاده میکند. ولی خب برنامهٔ من Cross-Platform می‌باشد و نمیتوانم از MS SQL Server استفاده کنم.

     


  19. درست متوجه منظورتون نشدم ! ولی :

    void Dialog::on_pushButton_2_clicked(){
      mThread->Stop = false;
    }

    این اسلات (slot) وقتی صدا زده میشه خب باید مقدار متغیر MyThread::Stop رو برابر false  قرار بده دیگه ! درسته ؟

    و طبق دستوراتی که داخل تابع void MyThread::run نوشته شده : درصورتی‌که این متغیر مقدارش false باشه باید حلقه شکسته بشه و دیگه چیزی emit نکنه.

    و وقتی ما این اسلات را فراخوانی میکنیم. اتفاقی نمی‌افته و باز حلقه به کار خودش ادامه میده.


  20. با سلام.

    در حال یادگیرQt و Thread ها بودم که به مشکل دسترسی به متغیر در Thread بر خوردم.

    کلاس زیر از QThread مشتق شده است :

    #ifndef MYTHREAD_H
    #define MYTHREAD_H
    
    #include <QObject>
    #include <QWidget>
    #include <QThread>
    #include <QMutex>
    
    class MyThread : public QThread
    {
        Q_OBJECT
      public:
        explicit MyThread(QObject *parent = nullptr);
        void run() override;
        bool Stop;
    
      signals:
        void NumberChanged(int);
    };
    
    #endif // MYTHREAD_H
    
    
    
    #include "mythread.h"
    
    MyThread::MyThread(QObject *parent) : QThread (parent)
    {
    
    }
    
    void MyThread::run()
    {
      for(int i=0; i<100000000 ; ++i){
          QMutex mutex;
           mutex.lock();
          if (this->Stop) break;
          mutex.unlock();
    
          emit NumberChanged(i);
          this->msleep(100);
        }
    }
    

     

    داخل فرم خودم دو QPushBotton و یک QLabel دارم. که یکی از دکمه‌ها (QPushButton) وظیفه اجرای یک QThread  را دارد و یکی دیگه باعث متوقف کردن کار QThread  ایجاد شده :

    #include "dialog.h"
    #include "ui_dialog.h"
    
    Dialog::Dialog(QWidget *parent) :
      QDialog(parent),
      ui(new Ui::Dialog){
      ui->setupUi(this);
    
      mThread = new MyThread(this);
      connect(mThread,SIGNAL(NumberChanged(int)),this,SLOT(onNumberChanged (int)));
    
    }
    
    Dialog::~Dialog(){
      delete ui;
    }
    
    void Dialog::onNumberChanged(int Number){
      ui->label->setText(QString::number(Number));
    }
    
    void Dialog::on_pushButton_clicked(){
      mThread->start();
    }
    
    void Dialog::on_pushButton_2_clicked(){
      mThread->Stop = false;
    }
    

     

    در کد بالا زمانی‌که on_pushButton_clicked فراخوانی شد. QThread را اجرا میکند. و در مقابل زمانی‌که on_pushButton_2_clicked فراخوانی شد. متغیر bool MyThread::Stop را برابر مقدار false میگذارد که باعث از بین رفتن عملیات QThread ایجاد شده میشود. اما در اصل هیچ تفاوتی ایجاد نمیکند ؟ و زمان بستن برنامه با خطای لاگ زیر برخورد میکنم :

    21:39:20: Starting /tmp/untitled/build-untitled-Desktop_Clang_7_0_0-Debug/untitled...
    QThread: Destroyed while thread is still running
    21:39:32: The program has unexpectedly finished.
    21:39:32: The process was ended forcefully.
    21:39:32: /tmp/untitled/build-untitled-Desktop_Clang_7_0_0-Debug/untitled crashed.

    کجای کار اشتباه شده است ؟ 

     


  21. با سلام.

    به چه روشی میتوان خروجی متن را در لحظه آپدیت کرد.

    برای مثال کد زیر را در نظر داشته باشید :

    #include <iostream>
    int main (void){
      
      for(unsigned int index =10 ; index <= 100 ; index+=10)
        std::cout << index << '%' << std::endl;
      
      return 0;
    }
    

     

    که خروجی زیر تولید میشه :

    [ghasem@clibcore AnotherJustForTest]$ g++ -o main main.cpp && ./main
    10%
    20%
    30%
    40%
    50%
    60%
    70%
    80%
    90%
    100%

     

    خب ! حالا اگر ما بخواهیم همان خط اول فقط  آپدیت بشود و از 10% تا 100% را در همان خط چاپ کند و دیگر به خط بعدی نرود چه باید کرد ؟

    یه مثال دیگه ... مدیربسته‌های dnf , apt , pacman که نوارپیشرفتی در خروجی کنسول خود نشان میدن. 


  22. با تشکر از توضیحات شما @فرهاد شیری  .

    در 1 ساعت قبل، فرهاد شیری گفته است :

    دقیقا همین اتفاق می افتد منتهی نه در خروجی کامپایل شما بلکه در زمان تبدیل به کد ماشین توسط خود کامپایلر و لینکر این انعقاد انجام می شود

    بنده اون لینکی که پیشنهاد داده بودید و به‌علاوه موارد دیگری هم در این زمینه خوانده بودم. و دقیقاً سعی کردم مثالی مرتبط به این موضوع بزنم. پس یه نگاه دیگه به فایل هدری که مثال زده بودم بکنید :

    class Base{
      public :
        Base(){std::cout << "BASE#c";}
        ~Base(){std::cout << "BASE#d";}
    };
    void AnotherTest (void){}
    void AndAnotherTest(void){}

    در فایل main.cpp من تنها یک بار تابع AndAnotherTest() را فراخوانی کرده بودم. که مسلماً طبق چیزی که گفتید :

    در 1 ساعت قبل، فرهاد شیری گفته است :

    خروجی باینری شما ترکیبی از کد های کامپایل شده شما خواهد بود به اضافه کلاسها و توابع استاندارد ++C که شما در برنامه خود استفاده کرده اید

    و بنده به این صورت برداشت کردم : که ابتدا تمام کد های فایل هدر من کامپایل شده و سپس در زمان لینک ، لینکر می‌بایست تنها لینکی به تابع AndAnotherTest() داشته باشد. و فقط هم این تابع در خروجی کد من باشد.

    من برای تست این موضوع از تعریف یک کلاس و دو تابع استفاده کردم. از آن‌جایی که میدونستم کلاس تنها یه نقشه از ساختمان است. پس تا زمانی که از این نقشه نمونه‌سازی نشوند ، نباید هیچ حافظه‌ای یا کامپایلی برای کد های این کلاس درنظر گرفته بشه. که تا این قسمت با توجه به خروجی اسمبلی من درست بود و حرفی از کلاس Base زده نشده بود. اما درمورد دوتا تابع بعدی که دقیقا هر دو کامپایل و درخروجی کد من بودن. در مقایسه هایی که کردم (که تماماً در طوماری که بالا ارسال کردم ، ذکر شده) متوجه شدم تنها تفاوت در فایلی که من تابع را فراخوانی و در فایلی که فراخوانی نکرده بودم تنها یک خط در خروجی اسمبلی بود ؛ اون‌هم دستور فراخوانی تابع AndAnotherTest() :

    [ghasem@clibcore output]$ cat --number JustHeader | egrep "(AnotherTest|AndAnotherTest)" > OnlyHeaderGREP
    [ghasem@clibcore output]$ cat --number UseOneFunction | egrep "(AnotherTest|AndAnotherTest)" > UseOneFunctionGREP
    [ghasem@clibcore output]$ diff JustHeader UseOneFunction
    55d54
    < 	call	_Z14AndAnotherTestv

    در مورد هدرفایل iostream هم. متغیرها و توابعی که به صورت static یا non-member function تعریف شده‌اند ، خروجی اسمبلی‌شان در فایل نهایی من هست. به غیر از tamplate-function و template-class و class ها که آن‌ها دقیقا برای کامپایل شدن نیاز به استفاده شدن را دارند.

     

    الان دلیل این اتفاق  : وجود کد اسمبلی تابع استفاده نشده در فایل هدر ، در خروجی نهایی فایل ترجمه شده به اسمبلی من چیست ؟ و آیا راهی برای جلوگیری از این موضوع هست ؟


  23. در ۱ ساعت قبل، سروش ربیعی گفته است :

    اضافه کردن فایل‌های هدر هیچ تأثیری در حجم برنامهٔ نهایی نداره

    (عذرخواهی میکنم مطالبی ارسالی این پست به دلیلی خروجی اسمبلی کدها طولانی و خارج از حوصله است. لذا متن‌های بین کدها با سبک دُرُشت و اندازه ۱۸ نوشته شده است)

    خب مگه اون هدر فایلی که اضافه میکنیم کامپایل نمیشه ؟ 

    الان یک نمونه تستی که من نوشتم :

    header.hpp

    class Base{
      public :
        Base(){std::cout << "BASE#c";}
        ~Base(){std::cout << "BASE#d";}
    };
    void AnotherTest (void){}
    void AndAnotherTest(void){}

    main.cpp

    #include <iostream>
    #include "header.hpp"
    
    int main(){
    	return 0;
    }

    خروجی اسمبلی زیر را تولید کرده :

    	.file	"main.cpp"
    	.text
    	.section	.rodata
    	.type	_ZStL19piecewise_construct, @object
    	.size	_ZStL19piecewise_construct, 1
    _ZStL19piecewise_construct:
    	.zero	1
    	.local	_ZStL8__ioinit
    	.comm	_ZStL8__ioinit,1,1
    	.text
    	.globl	_Z11AnotherTestv
    	.type	_Z11AnotherTestv, @function
    _Z11AnotherTestv:
    .LFB1524:
    	.cfi_startproc
    	pushq	%rbp
    	.cfi_def_cfa_offset 16
    	.cfi_offset 6, -16
    	movq	%rsp, %rbp
    	.cfi_def_cfa_register 6
    	nop
    	popq	%rbp
    	.cfi_def_cfa 7, 8
    	ret
    	.cfi_endproc
    .LFE1524:
    	.size	_Z11AnotherTestv, .-_Z11AnotherTestv
    	.globl	_Z14AndAnotherTestv
    	.type	_Z14AndAnotherTestv, @function
    _Z14AndAnotherTestv:
    .LFB1525:
    	.cfi_startproc
    	pushq	%rbp
    	.cfi_def_cfa_offset 16
    	.cfi_offset 6, -16
    	movq	%rsp, %rbp
    	.cfi_def_cfa_register 6
    	nop
    	popq	%rbp
    	.cfi_def_cfa 7, 8
    	ret
    	.cfi_endproc
    .LFE1525:
    	.size	_Z14AndAnotherTestv, .-_Z14AndAnotherTestv
    	.globl	main
    	.type	main, @function
    main:
    .LFB1526:
    	.cfi_startproc
    	pushq	%rbp
    	.cfi_def_cfa_offset 16
    	.cfi_offset 6, -16
    	movq	%rsp, %rbp
    	.cfi_def_cfa_register 6
    	movl	$0, %eax
    	popq	%rbp
    	.cfi_def_cfa 7, 8
    	ret
    	.cfi_endproc
    .LFE1526:
    	.size	main, .-main
    	.type	_Z41__static_initialization_and_destruction_0ii, @function
    _Z41__static_initialization_and_destruction_0ii:
    .LFB2010:
    	.cfi_startproc
    	pushq	%rbp
    	.cfi_def_cfa_offset 16
    	.cfi_offset 6, -16
    	movq	%rsp, %rbp
    	.cfi_def_cfa_register 6
    	subq	$16, %rsp
    	movl	%edi, -4(%rbp)
    	movl	%esi, -8(%rbp)
    	cmpl	$1, -4(%rbp)
    	jne	.L7
    	cmpl	$65535, -8(%rbp)
    	jne	.L7
    	movl	$_ZStL8__ioinit, %edi
    	call	_ZNSt8ios_base4InitC1Ev
    	movl	$__dso_handle, %edx
    	movl	$_ZStL8__ioinit, %esi
    	movl	$_ZNSt8ios_base4InitD1Ev, %edi
    	call	__cxa_atexit
    .L7:
    	nop
    	leave
    	.cfi_def_cfa 7, 8
    	ret
    	.cfi_endproc
    .LFE2010:
    	.size	_Z41__static_initialization_and_destruction_0ii, .-_Z41__static_initialization_and_destruction_0ii
    	.type	_GLOBAL__sub_I__Z11AnotherTestv, @function
    _GLOBAL__sub_I__Z11AnotherTestv:
    .LFB2011:
    	.cfi_startproc
    	pushq	%rbp
    	.cfi_def_cfa_offset 16
    	.cfi_offset 6, -16
    	movq	%rsp, %rbp
    	.cfi_def_cfa_register 6
    	movl	$65535, %esi
    	movl	$1, %edi
    	call	_Z41__static_initialization_and_destruction_0ii
    	popq	%rbp
    	.cfi_def_cfa 7, 8
    	ret
    	.cfi_endproc
    .LFE2011:
    	.size	_GLOBAL__sub_I__Z11AnotherTestv, .-_GLOBAL__sub_I__Z11AnotherTestv
    	.section	.init_array,"aw"
    	.align 8
    	.quad	_GLOBAL__sub_I__Z11AnotherTestv
    	.hidden	__dso_handle
    	.ident	"GCC: (GNU) 8.2.1 20181105 (Red Hat 8.2.1-5)"
    	.section	.note.GNU-stack,"",@progbits

    و کد زیر :

    #include <iostream>
    #include "header.hpp"
    
    int main(){
    	AndAnotherTest();
    	return 0;
    }

    خروجی اسمبلی زیر را تولید کرده :

    	.file	"main.cpp"
    	.text
    	.section	.rodata
    	.type	_ZStL19piecewise_construct, @object
    	.size	_ZStL19piecewise_construct, 1
    _ZStL19piecewise_construct:
    	.zero	1
    	.local	_ZStL8__ioinit
    	.comm	_ZStL8__ioinit,1,1
    	.text
    	.globl	_Z11AnotherTestv
    	.type	_Z11AnotherTestv, @function
    _Z11AnotherTestv:
    .LFB1524:
    	.cfi_startproc
    	pushq	%rbp
    	.cfi_def_cfa_offset 16
    	.cfi_offset 6, -16
    	movq	%rsp, %rbp
    	.cfi_def_cfa_register 6
    	nop
    	popq	%rbp
    	.cfi_def_cfa 7, 8
    	ret
    	.cfi_endproc
    .LFE1524:
    	.size	_Z11AnotherTestv, .-_Z11AnotherTestv
    	.globl	_Z14AndAnotherTestv
    	.type	_Z14AndAnotherTestv, @function
    _Z14AndAnotherTestv:
    .LFB1525:
    	.cfi_startproc
    	pushq	%rbp
    	.cfi_def_cfa_offset 16
    	.cfi_offset 6, -16
    	movq	%rsp, %rbp
    	.cfi_def_cfa_register 6
    	nop
    	popq	%rbp
    	.cfi_def_cfa 7, 8
    	ret
    	.cfi_endproc
    .LFE1525:
    	.size	_Z14AndAnotherTestv, .-_Z14AndAnotherTestv
    	.globl	main
    	.type	main, @function
    main:
    .LFB1526:
    	.cfi_startproc
    	pushq	%rbp
    	.cfi_def_cfa_offset 16
    	.cfi_offset 6, -16
    	movq	%rsp, %rbp
    	.cfi_def_cfa_register 6
    	call	_Z14AndAnotherTestv
    	movl	$0, %eax
    	popq	%rbp
    	.cfi_def_cfa 7, 8
    	ret
    	.cfi_endproc
    .LFE1526:
    	.size	main, .-main
    	.type	_Z41__static_initialization_and_destruction_0ii, @function
    _Z41__static_initialization_and_destruction_0ii:
    .LFB2010:
    	.cfi_startproc
    	pushq	%rbp
    	.cfi_def_cfa_offset 16
    	.cfi_offset 6, -16
    	movq	%rsp, %rbp
    	.cfi_def_cfa_register 6
    	subq	$16, %rsp
    	movl	%edi, -4(%rbp)
    	movl	%esi, -8(%rbp)
    	cmpl	$1, -4(%rbp)
    	jne	.L7
    	cmpl	$65535, -8(%rbp)
    	jne	.L7
    	movl	$_ZStL8__ioinit, %edi
    	call	_ZNSt8ios_base4InitC1Ev
    	movl	$__dso_handle, %edx
    	movl	$_ZStL8__ioinit, %esi
    	movl	$_ZNSt8ios_base4InitD1Ev, %edi
    	call	__cxa_atexit
    .L7:
    	nop
    	leave
    	.cfi_def_cfa 7, 8
    	ret
    	.cfi_endproc
    .LFE2010:
    	.size	_Z41__static_initialization_and_destruction_0ii, .-_Z41__static_initialization_and_destruction_0ii
    	.type	_GLOBAL__sub_I__Z11AnotherTestv, @function
    _GLOBAL__sub_I__Z11AnotherTestv:
    .LFB2011:
    	.cfi_startproc
    	pushq	%rbp
    	.cfi_def_cfa_offset 16
    	.cfi_offset 6, -16
    	movq	%rsp, %rbp
    	.cfi_def_cfa_register 6
    	movl	$65535, %esi
    	movl	$1, %edi
    	call	_Z41__static_initialization_and_destruction_0ii
    	popq	%rbp
    	.cfi_def_cfa 7, 8
    	ret
    	.cfi_endproc
    .LFE2011:
    	.size	_GLOBAL__sub_I__Z11AnotherTestv, .-_GLOBAL__sub_I__Z11AnotherTestv
    	.section	.init_array,"aw"
    	.align 8
    	.quad	_GLOBAL__sub_I__Z11AnotherTestv
    	.hidden	__dso_handle
    	.ident	"GCC: (GNU) 8.2.1 20181105 (Red Hat 8.2.1-5)"
    	.section	.note.GNU-stack,"",@progbits

    و در کد اسمبلئ که هیچ یک از توابع فایلheader.hpp استفاده نشده است. خروجی اسمبلی توابع فایل header.hpp موجود هست :

    [ghasem@clibcore tmp]$ cat --number OnlyHeader | egrep "(AnotherTest|AndAnotherTest)" 
        11		.globl	_Z11AnotherTestv
        12		.type	_Z11AnotherTestv, @function
        13	_Z11AnotherTestv:
        27		.size	_Z11AnotherTestv, .-_Z11AnotherTestv
        28		.globl	_Z14AndAnotherTestv
        29		.type	_Z14AndAnotherTestv, @function
        30	_Z14AndAnotherTestv:
        44		.size	_Z14AndAnotherTestv, .-_Z14AndAnotherTestv
        92		.type	_GLOBAL__sub_I__Z11AnotherTestv, @function
        93	_GLOBAL__sub_I__Z11AnotherTestv:
       109		.size	_GLOBAL__sub_I__Z11AnotherTestv, .-_GLOBAL__sub_I__Z11AnotherTestv
       112		.quad	_GLOBAL__sub_I__Z11AnotherTestv
    

    و در کدی که فقط تابع AndAnotherTest() استفاده شده است :

    [ghasem@clibcore tmp]$ cat --number UseOneFunction | egrep "(AnotherTest|AndAnotherTest)"
        11		.globl	_Z11AnotherTestv
        12		.type	_Z11AnotherTestv, @function
        13	_Z11AnotherTestv:
        27		.size	_Z11AnotherTestv, .-_Z11AnotherTestv
        28		.globl	_Z14AndAnotherTestv
        29		.type	_Z14AndAnotherTestv, @function
        30	_Z14AndAnotherTestv:
        44		.size	_Z14AndAnotherTestv, .-_Z14AndAnotherTestv
        55		call	_Z14AndAnotherTestv
        93		.type	_GLOBAL__sub_I__Z11AnotherTestv, @function
        94	_GLOBAL__sub_I__Z11AnotherTestv:
       110		.size	_GLOBAL__sub_I__Z11AnotherTestv, .-_GLOBAL__sub_I__Z11AnotherTestv
       113		.quad	_GLOBAL__sub_I__Z11AnotherTestv

     و تنها تفاوت این دو در فراخوانی تابع AndAnotherTest() هست :

    [ghasem@clibcore output]$ cat --number JustHeader | egrep "(AnotherTest|AndAnotherTest)" > OnlyHeaderGREP
    [ghasem@clibcore output]$ cat --number UseOneFunction | egrep "(AnotherTest|AndAnotherTest)" > UseOneFunctionGREP
    [ghasem@clibcore output]$ diff JustHeader UseOneFunction
    55d54
    < 	call	_Z14AndAnotherTestv

    در حالی که من از پاسخ شما @سروش ربیعی فهمیدم که گفتید هدرفایل‌ها تاثیری در حجم برنامه‌ٔ‌نهایی نداره. اما مثال بالا که زدم با وجود اینکه هیچ فراخوانی از توابع نشده بود بازم هم کد های هدرفایل کامپایل شد.

    و اما بخشی که منو گیج کرده ! 

    ما در این فایل هم هدرفایل iostream و هم header.hpp را وارد برنامه کرده ایم. توابعی که در header.hpp بود تماما کامپایل شده و در خروجی اسمبلی هست. اما خبری از توابع و دستورات iostream نیست. این خروجی اسمبلی بدون هدرفایل iostream هست :

    	.file	"main.cpp"
    	.text
    	.globl	_Z11AnotherTestv
    	.type	_Z11AnotherTestv, @function
    _Z11AnotherTestv:
    .LFB0:
    	.cfi_startproc
    	pushq	%rbp
    	.cfi_def_cfa_offset 16
    	.cfi_offset 6, -16
    	movq	%rsp, %rbp
    	.cfi_def_cfa_register 6
    	nop
    	popq	%rbp
    	.cfi_def_cfa 7, 8
    	ret
    	.cfi_endproc
    .LFE0:
    	.size	_Z11AnotherTestv, .-_Z11AnotherTestv
    	.globl	_Z14AndAnotherTestv
    	.type	_Z14AndAnotherTestv, @function
    _Z14AndAnotherTestv:
    .LFB1:
    	.cfi_startproc
    	pushq	%rbp
    	.cfi_def_cfa_offset 16
    	.cfi_offset 6, -16
    	movq	%rsp, %rbp
    	.cfi_def_cfa_register 6
    	nop
    	popq	%rbp
    	.cfi_def_cfa 7, 8
    	ret
    	.cfi_endproc
    .LFE1:
    	.size	_Z14AndAnotherTestv, .-_Z14AndAnotherTestv
    	.globl	main
    	.type	main, @function
    main:
    .LFB2:
    	.cfi_startproc
    	pushq	%rbp
    	.cfi_def_cfa_offset 16
    	.cfi_offset 6, -16
    	movq	%rsp, %rbp
    	.cfi_def_cfa_register 6
    	movl	$0, %eax
    	popq	%rbp
    	.cfi_def_cfa 7, 8
    	ret
    	.cfi_endproc
    .LFE2:
    	.size	main, .-main
    	.ident	"GCC: (GNU) 8.2.1 20181105 (Red Hat 8.2.1-5)"
    	.section	.note.GNU-stack,"",@progbits

    و تفاوت آن با خروجی اسمبلی‌ای که هدرفایل iostream وجود داشته است  :

    [ghasem@clibcore output]$ diff WithIostream WithoutIostrea 
    3,10d2
    < 	.section	.rodata
    < 	.type	_ZStL19piecewise_construct, @object
    < 	.size	_ZStL19piecewise_construct, 1
    < _ZStL19piecewise_construct:
    < 	.zero	1
    < 	.local	_ZStL8__ioinit
    < 	.comm	_ZStL8__ioinit,1,1
    < 	.text
    14c6
    < .LFB1518:
    ---
    > .LFB0:
    26c18
    < .LFE1518:
    ---
    > .LFE0:
    31c23
    < .LFB1519:
    ---
    > .LFB1:
    43c35
    < .LFE1519:
    ---
    > .LFE1:
    48c40
    < .LFB1520:
    ---
    > .LFB2:
    60c52
    < .LFE1520:
    ---
    > .LFE2:
    62,113d53
    < 	.type	_Z41__static_initialization_and_destruction_0ii, @function
    < _Z41__static_initialization_and_destruction_0ii:
    < .LFB2001:
    < 	.cfi_startproc
    < 	pushq	%rbp
    < 	.cfi_def_cfa_offset 16
    < 	.cfi_offset 6, -16
    < 	movq	%rsp, %rbp
    < 	.cfi_def_cfa_register 6
    < 	subq	$16, %rsp
    < 	movl	%edi, -4(%rbp)
    < 	movl	%esi, -8(%rbp)
    < 	cmpl	$1, -4(%rbp)
    < 	jne	.L7
    < 	cmpl	$65535, -8(%rbp)
    < 	jne	.L7
    < 	movl	$_ZStL8__ioinit, %edi
    < 	call	_ZNSt8ios_base4InitC1Ev
    < 	movl	$__dso_handle, %edx
    < 	movl	$_ZStL8__ioinit, %esi
    < 	movl	$_ZNSt8ios_base4InitD1Ev, %edi
    < 	call	__cxa_atexit
    < .L7:
    < 	nop
    < 	leave
    < 	.cfi_def_cfa 7, 8
    < 	ret
    < 	.cfi_endproc
    < .LFE2001:
    < 	.size	_Z41__static_initialization_and_destruction_0ii, .-_Z41__static_initialization_and_destruction_0ii
    < 	.type	_GLOBAL__sub_I__Z11AnotherTestv, @function
    < _GLOBAL__sub_I__Z11AnotherTestv:
    < .LFB2002:
    < 	.cfi_startproc
    < 	pushq	%rbp
    < 	.cfi_def_cfa_offset 16
    < 	.cfi_offset 6, -16
    < 	movq	%rsp, %rbp
    < 	.cfi_def_cfa_register 6
    < 	movl	$65535, %esi
    < 	movl	$1, %edi
    < 	call	_Z41__static_initialization_and_destruction_0ii
    < 	popq	%rbp
    < 	.cfi_def_cfa 7, 8
    < 	ret
    < 	.cfi_endproc
    < .LFE2002:
    < 	.size	_GLOBAL__sub_I__Z11AnotherTestv, .-_GLOBAL__sub_I__Z11AnotherTestv
    < 	.section	.init_array,"aw"
    < 	.align 8
    < 	.quad	_GLOBAL__sub_I__Z11AnotherTestv
    < 	.hidden	__dso_handle
    

    با یه نگاه کردن به  فایل iostream :

    #ifndef _GLIBCXX_IOSTREAM
    #define _GLIBCXX_IOSTREAM 1
    
    #pragma GCC system_header
    
    #include <bits/c++config.h>
    #include <ostream>
    #include <istream>
    
    namespace std _GLIBCXX_VISIBILITY(default)
    {
    _GLIBCXX_BEGIN_NAMESPACE_VERSION
      extern istream cin;		
      extern ostream cout;		
      extern ostream cerr;		
      extern ostream clog;		
    
    #ifdef _GLIBCXX_USE_WCHAR_T
      extern wistream wcin;		
      extern wostream wcout;	
      extern wostream wcerr;	
      extern wostream wclog;	
    #endif
      static ios_base::Init __ioinit;
    
    _GLIBCXX_END_NAMESPACE_VERSION
    } 
    #endif 

    ظاهرا دلیل اون تفاوت هم مشخص هست. اما تکلیف مابقی هدرفایل هایی که داخل iostream وارد شده اند چیست ؟ مگه توابع و متغیر های آنها نیز کامپایل نمیشود ؟ پس چرا مثل خروجی کد اسمبلی‌ توابع موجود در header.hpp در سورس اسمبلی نهایی نیست ؟ (و باز عذرخواهی میکنم بابت طولانی بودن پست )


  24. با سلام.

    درحال بررسی کدهای کتابخانه‌های استاندارد سی‌پلاس‌پلاس بودم ، که متوجه موردی شدم ؛ تقریبا بیشتر توابع و کلاس‌هایی که از کتابخانه‌های استاندارد استفاده میکنیم دارای مقدار زیادی وابستگی به توابع و فایل‌های دیگر دارند. برای مثال تابع std::swap که برای جابه‌جایی دو نوع استفاده میشود به این‌صورت میباشد :

    template<typename _Tp, size_t _Nm>
      inline
      typename std::enable_if<__is_swappable<_Tp>::value>::type
      swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm])
      noexcept(std::__is_nothrow_swappable<_Tp>::value)
      {
        for (size_t __n = 0; __n < _Nm; ++__n)
          swap(__a[__n], __b[__n]);
      }

    که برای کامپایل نیاز به این موارد در دو فایل move.h و type_traits دارند :

    template<typename _Tp, _Tp __v>
      struct integral_constant
      {
        static constexpr _Tp                  value = __v;
        typedef _Tp                           value_type;
        typedef integral_constant<_Tp, __v>   type;
        constexpr operator value_type() const noexcept { return value; }
    #if __cplusplus > 201103L
    
    #define __cpp_lib_integral_constant_callable 201304
    
        constexpr value_type operator()() const noexcept { return value; }
    #endif
      };
    
      template<bool __v>
        using __bool_constant = integral_constant<bool, __v>;
    
    typedef integral_constant<bool, true>     true_type;
      typedef integral_constant<bool, false>    false_type;
    
    template<bool, typename _Tp = void>
      struct enable_if
      { };
    
      namespace __swappable_details {
        using std::swap;
    
        struct __do_is_swappable_impl
        {
          template<typename _Tp, typename
                   = decltype(swap(std::declval<_Tp&>(), std::declval<_Tp&>()))>
            static true_type __test(int);
    
          template<typename>
            static false_type __test(...);
        };
    
        struct __do_is_nothrow_swappable_impl
        {
          template<typename _Tp>
            static __bool_constant<
              noexcept(swap(std::declval<_Tp&>(), std::declval<_Tp&>()))
            > __test(int);
    
          template<typename>
            static false_type __test(...);
        };
    
      }
    
      template<typename _Tp>
        struct __is_swappable_impl
        : public __swappable_details::__do_is_swappable_impl
        {
          typedef decltype(__test<_Tp>(0)) type;
        };
    
      template<typename _Tp>
        struct __is_swappable
        : public __is_swappable_impl<_Tp>::type
        { };
    
        template<typename _Tp>
          struct __is_nothrow_swappable_impl
          : public __swappable_details::__do_is_nothrow_swappable_impl
          {
            typedef decltype(__test<_Tp>(0)) type;
          };
    
      template<typename _Tp>
        struct __is_nothrow_swappable
        : public __is_nothrow_swappable_impl<_Tp>::type
        { };

    خب ! سوال اول بنده اینجاس که در چنین مواردی ، بهتر نیست که تابعstd::swap را با توجه به نیازی که داریم خودمان پیاده‌سازی کنیم ؟ و اینکه آیا این حجم از کد و استفاده از template ها هزینه پِرفُورْمَنْس زیادی ندارد ؟

    و سوال دوم :

    تمام این کدها در دو فایل move.h و type_traits قرار دارد (که مسلماً این فایل ها هم وابستگی‌های دیگری به دیگر فایل‌ها دارند). آیا ما نمی‌توانیم مثلا فقط تابع std::swap را در برنامهٔ خود فراخوانی کنیم که این حجم از کد احتیاج به کامپایل نداشته باشد ؟

    برای نمونه در زبان برنامه‌نویسی پایتون ، با استفاده از دستور import ما یک ماژول را وارد برنامه میکنیم :

    import time

    در این روش تمام ماژول time به فایل‌ما اضافه خواهند شد. درصورتی که ما فقط از ماژول time نیاز به تابع sleep داشته باشیم کافی است که از قابلت from ... import ... استفاده کنیم :

    from time import sleep

    آیا این حرکت در C++ نیز امکان‌پذیر هست ؟

×
×
  • جدید...