وظيفة تطبع شيئا إلى STD :: Ostream وإرجاع STD :: Ostream؟

StackOverflow https://stackoverflow.com/questions/1087927

  •  23-08-2019
  •  | 
  •  

سؤال

أريد أن أكتب وظيفة تخرج شيئا إلى ostream هذا مرت، وإرجاع الدفق، مثل هذا:

std::ostream& MyPrint(int val, std::ostream* out) {
  *out << val;
  return *out;
}

int main(int argc, char** argv){
    std::cout << "Value: " << MyPrint(12, &std::cout) << std::endl;
    return 0;
}

سيكون من المناسب طباعة القيمة مثل هذا وتضمين استدعاء الدالة في سلسلة مشغل الناتج، كما فعلت في main().

لا يعمل، ومع ذلك، وطبع هذا:

$ ./a.out
12Value: 0x6013a8

الإخراج المطلوب سيكون هذا:

Value: 12

كيف يمكنني اصلاح هذا؟ هل يجب علي تحديد operator<< في حين أن؟

تحديث: أوضح ما سيكون الإخراج المطلوب.

تحديث 2: بعض الناس لم يفهموا لماذا أطبع عدد من ذلك، باستخدام وظيفة بدلا من طباعةها مباشرة. هذا مثال مبسط، وفي الواقع، تقوم الوظيفة بطباعة كائن معقد بدلا من int.

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

المحلول

لا يمكنك إصلاح الوظيفة. لا يوجد شيء في المواصفات يتطلب مترجما لتقييم مكالمة دالة في تعبير في أي طلب معين فيما يتعلق ببعض المشغل غير المرتبط به في نفس التعبير. لذلك دون تغيير رمز الاتصال، لا يمكنك القيام به MyPrint() تقييم بعد ذلك std::cout << "Value: "

يتم تكليف الترتيب من اليسار اليميني للتعبيرات التي تتكون من العديد من المشغلين << مشغلي، بحيث تعمل. نقطة المشغل << إرجاع الدفق هو أنه عندما يتم دمج المشغلين، يتم توفير LHS من كل واحد من خلال تقييم المشغل إلى يساره.

لا يمكنك تحقيق نفس الشيء مع مكالمات الدالة المجانية لأنها لا تملك LHS. MyPrint() إرجاع كائن يساوي std::cout, وهكذا يفعل std::cout << "Value: ", ، لذلك أنت تفعل بفعالية std::cout << std::cout, ، الذي يطبع قيمة عرافة.

منذ الناتج المطلوب هو:

Value: 12

الشيء "الصحيح" الذي يجب القيام به هو في الواقع لتجاوز المشغل <<. هذا يعني كثيرا أنك تحتاج إلى جعله صديقا، أو القيام بذلك:

class WhateverItIsYouReallyWantToPrint {
    public:
    void print(ostream &out) const {
        // do whatever
    }
};

ostream &operator<<(ostream &out, const WhateverItIsYouReallyWantToPrint &obj) {
    obj.print(out);
}

إذا تجاوزت operator<< بالنسبة لفصولتك ليست مناسبة، على سبيل المثال نظرا لأن هناك تنسيقات متعددة قد ترغب في طباعتها، وتريد كتابة وظيفة مختلفة لكل منها، فعليك إما أن تستسلم عن فكرة المدعوم والمشاركة فقط وظيفة، أو كتابة فئات متعددة تأخذ كائنك كمعلمة منشئية، كل منها مع تحميل مشغل مختلف.

نصائح أخرى

تريد إنشاء فئة فئة مع أحد المشغل <<:

class MyPrint
{
public:
    MyPrint(int val) : val_(val) {}
    friend std::ostream& operator<<(std::ostream& os, const MyPrint& mp) 
    {
        os << mp.val_;
        return os;
    }
private:
    int val_;
};

int main(int argc, char** argv)
{
    std::cout << "Value: " << MyPrint(12) << std::endl;
    return 0;
}

تتطلب هذه الطريقة أن تقوم بإدراج كائن Myprint في دفق اختيارك. إذا كنت بحاجة فعلا إلى القدرة على تغيير الدفق النشط، فيمكنك القيام بذلك:

class MyPrint
{
public:
    MyPrint(int val, std::ostream& os) : val_(val), os_(os) {}
    friend std::ostream& operator<<(std::ostream& dummy, const MyPrint& mp) 
    {
        mp.os_ << mp.val_;
        return os_;
    }
private:
    int val_;
    std::ostream& os_
};

int main(int argc, char** argv)
{
    std::cout << "Value: " << MyPrint(12, std::cout) << std::endl;
    return 0;
}

لديك خياران. الأول، باستخدام ما لديك بالفعل هو:

std::cout << "Value: ";
MyPrint(12, &std::cout);
std::cout << std::endl;

الآخر، وهو أكثر C ++ - مثل، هو استبدال MyPrint() مع المناسب std::ostream& operator<<. وبعد هناك بالفعل واحد ل int, ، لذلك سوف أفعل واحدة فقط صبي أكثر تعقيدا:

#include <iostream>

struct X {
    int y;
};

// I'm not bothering passing X as a reference, because it's a
// small object
std::ostream& operator<<(std::ostream& os, const X x)
{
    return os << x.y;
}

int main()
{
    X x;
    x.y = 5;
    std::cout << x << std::endl;
}

لا توجد طريقة للقيام بما تتوقعه هناك بسبب الطلب يتم تقييم الوظائف.

هل هناك أي سبب محدد تحتاج إلى الكتابة مباشرة إلى النيتريم من هذا القبيل؟ إذا لم يكن الأمر كذلك، فما عليك سوى إرجاع SPAINT سلسلة. إذا كنت ترغب في استخدام دفق داخل برينتر لإنشاء الإخراج، فما عليك سوى استخدام Strstream وإرجاع النتيجة.

أولا، لا يوجد سبب لعدم المرور في ostream بالرجوع إلى مؤشر:

std::ostream& MyPrint(int val, std::ostream& out) {
  out << val;
  return out;
}

إذا كنت حقا لا ترغب في استخدام std::ostream& operator<<(std::ostream& os, TYPE), ، يمكنك ان تفعلها:

int main(int argc, char** argv){
    std::cout << "Value: ";
    MyPrint(12, std::cout) << std::endl;
    return 0;
}

بعد تغيير المؤشر إلى مرجع، يمكنك القيام بذلك:

#include <iostream>

std::ostream& MyPrint(int val, std::ostream& out) {
    out << val;
    return out;
}

int main(int, char**) {
    MyPrint(11, std::cout << "Value: ") << std::endl; 

    return 0;
}

بناء الجملة ل MyPrint هو أساسا أن من غير المنسد operator<< ولكن مع حجة إضافية.

في حالتك، من الواضح أن الإجابة:

 std::cout << "Value: " << 12 << std::endl;

إذا لم يكن ذلك جيدا بما فيه الكفاية، فيرجى توضيح ما هو الإخراج الذي تريد رؤيته.

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