Frage

Ich möchte eine Funktion schreiben, die etwas zu einem ostream ausgibt, die in übergeben wird, und gibt den Strom, wie folgt aus:

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;
}

Es wäre zweckmäßig, den Wert wie folgt und bettet den Funktionsaufruf in der Ausgabeoperator Kette zu drucken, wie ich in main() tat.

Es funktioniert nicht, aber, und druckt diese:

$ ./a.out
12Value: 0x6013a8

Die gewünschte Ausgabe wäre dies:

Value: 12

Wie kann ich dieses Problem beheben? Muss ich einen operator<< statt definieren?

UPDATE:. Geklärte, was die gewünschte Ausgabe wäre

UPDATE2: Manche Leute verstehen nicht, warum ich eine Nummer wie das gedruckt werden soll, eine Funktion anstelle des Druckens direkt verwenden. Dies ist ein vereinfachtes Beispiel, und in Wirklichkeit druckt die Funktion ein komplexes Objekt eher als ein int.

War es hilfreich?

Lösung

Sie können nicht die Funktion beheben. Nichts in der Spezifikation erfordert einen Compiler einen Funktionsaufruf in einem Ausdruck in einer bestimmten Reihenfolge in Bezug auf einige unabhängige Betreiber in der gleichen Ausdruck auszuwerten. Also ohne den aufrufenden Code zu ändern, können Sie nicht MyPrint() bewerten nach std::cout << "Value: " machen

Von links nach rechts, um für Ausdrücke beauftragt, bestehend aus mehreren aufeinanderfolgenden << Operatoren, dass so funktionieren wird. Der Punkt, der Operator <<, um den Strom zurückkehrt, ist, dass, wenn Betreiber verkettet sind, die LHS eines jeden durch die Auswertung des Betreibers zu seiner linken zugeführt wird.

Sie können nicht das Gleiche mit Freisprechfunktion telefonieren erreichen, weil sie keine LHS haben. MyPrint() gibt ein Objekt gleich std::cout, und so auch std::cout << "Value: ", so dass Sie effektiv tun std::cout << std::cout sind, die diese Hex-Wert gedruckt wird.

Da die gewünschte Ausgabe lautet:

Value: 12

das „Recht“, was zu tun ist in der Tat Betreiber außer Kraft zu setzen <<. Diese häufig bedeutet, dass Sie müssen entweder einen Freund machen, oder dies tun:

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

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

Wenn überwiegendes operator<< für Ihre Klasse nicht geeignet ist, beispielsweise, weil es mehrere Formate, die Sie drucken möchten, und Sie wollen eine andere Funktion für jeden schreiben, dann sollten Sie entweder aufgeben auf der Idee, Betreiber Verkettung und rufen Sie die Funktion, oder auch mehrere Klassen schreiben, die Ihr Objekt als Konstruktor Parameter übernehmen, die jeweils mit unterschiedlichen Betreibern Überlastung.

Andere Tipps

Sie wollen MyPrint eine Klasse mit Freund Operator machen <<:

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;
}

Diese Methode erfordert, dass Sie das MyPrint Objekt in den Strom Ihrer Wahl einzufügen. Wenn man wirklich die Fähigkeit, ändern müssen, welcher Strom aktiv ist, können Sie dies tun:

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;
}

Sie haben zwei Möglichkeiten. Der erste, mit was Sie bereits haben, ist:

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

Die andere, die mehr C ++ ist - wie, ist MyPrint() mit dem entsprechenden std::ostream& operator<< zu ersetzen. Es gibt bereits eine für int, also werde ich ein tun nur ein bisschen komplizierter:

#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;
}

Es gibt keine Möglichkeit zu tun, was Sie erwarten, da aufgrund der Reihenfolge der Funktionen in ausgewertet werden.

Gibt es einen besonderen Grund, warum Sie direkt an den Ostream so schreiben müssen? Wenn nicht, nur haben MyPrint einen String zurück. Wenn Sie einen Stream innerhalb MyPrint verwenden möchten, um die Ausgabe zu erzeugen, um nur Strstream verwenden und das Ergebnis zurück.

Erstens gibt es keinen Grund, nicht in den ostream durch Verweis übergeben, anstatt durch einen Zeiger:

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

Wenn Sie wirklich nicht wollen, std::ostream& operator<<(std::ostream& os, TYPE) verwenden, können Sie dies tun:

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

Nach dem Zeiger auf eine Referenz zu ändern, können Sie dies tun:

#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;
}

Die Syntax für MyPrint ist im Wesentlichen die eines abgerollt operator<< aber mit einem zusätzlichen Argument.

In Ihrem Fall ist die Antwort offensichtlich:

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

Wenn das nicht gut genug ist, bitte erklären, was Ausgabe, die Sie sehen wollen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top