سؤال

النظر في المسائل التالية الحد الأدنى على سبيل المثال:

#include <iostream>

using namespace std;

class myostream : public ostream {
    public:
        myostream(ostream const &other) :
            ostream(other.rdbuf())
        { }
};

int main() {
    cout << "hello world" << endl;

    myostream s(cout);
    s << "hello world" << endl;

    myostream(cout) << "hello world" << endl;
}

الإخراج ، سواء على g++ و Visual C++ ،

hello world
hello world
0x4012a4

النسخة التي يكتب مؤقتة كائن ، myostream(cout), يبدو أن تفضل الأعضاء المشغل ostream::operator<<(void *), بدلا من مشغل حر operator<<(ostream &, char *).يبدو أن تحدث فرقا ما إذا كان أو لم يكن كائن لديه اسم.

لماذا يحدث هذا ؟ و كيف يمكن منع هذا السلوك ؟

تحرير:لماذا يحدث هو واضح الآن من إجابات مختلفة.كيفية منع هذا ، التالية تبدو جذابة:

class myostream : public ostream {
    public:
        // ...
        myostream &operator<<(char const *str) {
            std::operator<<(*this, str);
            return *this;
        }
};

ومع ذلك ، فإن هذه النتائج في جميع أنواع الغموض.

هل كانت مفيدة؟

المحلول

rvalues لا يمكن أن يكون منضما إلى مرجع غير const.لذلك في المثال الخاص بك مؤقتة من نوع ostream لا يمكن أن تكون الوسيطة الأولى مجانا المشغل<<(std::ostream&, const char*) و ما يستخدم هو عضو في المشغل<<(الفراغ*).

إذا كنت بحاجة إلى ذلك, يمكنك إضافة مكالمة مثل

myostream(cout).flush() << "foo";

التي ستحول rvalue إلى إشارة.

علما أنه في C++0X ، وإدخال rvalue مرجعية تسمح لتوفير الزائد من المشغل<< أخذ rvalue المراجع كما المعلمة حل الجذري لهذه القضية.

نصائح أخرى

إذا كان كائن لا اسم له (أيهو مؤقت) ، فإنه لا يمكن أن يكون منضما إلى مرجع غير const.على وجه التحديد لا يمكن أن يكون لا بد أن المعلمة الأولى من:

operator<<(ostream &, char *)

أنا فقط أدركت جزء من الجواب.مؤقت ليس lvalue ، لذلك فإنه لا يمكن أن تستخدم حجة من نوع ostream &.

السؤال "كيف يمكنني جعل هذا العمل" لا يزال...

لأن أيا من الإجابات حتى الآن تبدو نظيفة الحل, سأقبل القذرة الحل:

myostream operator<<(myostream stream, char const *str) {
    std::operator<<(stream, str);
    return stream;
}

هذا ممكن فقط لأن myostream لديه نسخة منشئ.(داخليا, و هو مدعوم ref-تحسب std::stringbuf.)

في حين C++11 هل من حل هذه المسألة لأن هناك rvalue المراجع ، وأعتقد أن هذا قد يكون حلا قبل C++11.

الحل هو أن يكون وظيفة عضو << المشغل حيث أننا يمكن أن يلقي إلى غير const الإشارة إلى الفئة الأساسية:

class myostream : public ostream {
    public:
        // ...
        template<typename T>
        ostream &operator<<(const T &t) {
            //now the first operand is no longer a temporary,
            //so the non-member operators will overload correctly
            return static_cast<ostream &>(*this) << t;
        }
};

حسنا, أنا لا أعرف C++ المواصفات التي تسبب هذا, ولكن من السهل أن تكتشفه لماذا يحدث ذلك.

مؤقت يعيش على المكدس ، وعادة ما يتم تمريرها إلى وظيفة أخرى أو أن يكون عملية واحدة تسمى على ذلك.لذا ، إذا كنت اتصل مجانا المشغل على ذلك:

المشغل<<(myostream(cout))

يتم تدميره في نهاية هذه العملية الثانية "<<"المشغل إلى إلحاق endl مرجع كائن غير صالح.قيمة الإرجاع من الحر "<<"المشغل إشارة إلى تدمير كائن مؤقت.C++ المواصفات ربما يحدد قواعد مجانا مشغلي لمنع هذا السيناريو من محبطة ومربكة C++ المبرمجين.

الآن في حالة "<<(الفراغ*)" عضو المشغل على مؤقت قيمة الإرجاع هو الكائن نفسه الذي لا يزال على المكدس وليس تدميرها ، وبالتالي فإن المترجم لا يعرف التدمير ذلك ولكن تمر بجوار الأعضاء المشغل ، أن يأخذ endl.مشغل تسلسل على المؤقتات هي ميزة مفيدة بالنسبة مقتضبة رمز C++, لذا أنا متأكد C++ المواصفات المصممين اعتبر وتنفيذ برنامج التحويل البرمجي دعم ذلك عمدا.

تحرير

وقد قال البعض أن هذا هو أن تفعل مع مرجع غير const.هذه البرمجية برمجيا:

#include <iostream>
using namespace std;
class myostream : public ostream { 
    public: 
        myostream(ostream const &other) : 
            ostream(other.rdbuf()) 
        { } 
            ~myostream() { cout << " destructing "; }
    }; 
int _tmain(int argc, _TCHAR* argv[])
{
    basic_ostream<char>& result = std::operator << (myostream(cout), "This works");
    std::operator << (result, "illegal");
         return 0;
}

و يعود

  This works destructing illegal
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top