Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Das Gurke

Community-Fossil

  • »Das Gurke« ist der Autor dieses Themas

Beiträge: 1 996

Wohnort: Pinneberg

Beruf: Schüler

  • Private Nachricht senden

1

04.01.2008, 22:35

Operator << überladen

Ich krieg das irgendwie total nicht hin ... Der Grundgedanke ist folgender:

Bei meinem aktuellen Projekt möchte ich Konsolenausgaben auf dem Bildschirm ausgeben und in ein Logfile schreiben. Um mir das möglich einfach zu machen, wollte ich mir eine Klasse schreiben, welche Ausgaben per << Operator an beiden Orten ausgibt.

Die Klasse dafür sieht so aus:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
std::ostringstream& Output::operator << ( const char* s)
{
    std::cout << s;
    mLog << s;

    std::ostringstream  str;
    str << s;
    return (str);
}
Der gcc warnt sogar, dass dieses konstrukt knallen wird. Tut es natürlich auch. Ich sollte keine Referenz zurückgeben, sondern das tatsächliche Objekt. Aber wenn ich das ganze als Objekt zurückgebe, bekomme ich folgenden Fehler:

C-/C++-Quelltext

1
Fehler  1   error C2248: "std::basic_ios<_Elem,_Traits>::basic_ios": Kein Zugriff auf private Member, dessen Deklaration in der std::basic_ios<_Elem,_Traits>-Klasse erfolgte.  c:\programme\microsoft visual studio 8\vc\include\sstream   448
Ist mir prinzipiell auch klar, jetzt weiss ich aber dummerweise garnicht mehr weiter. Ich vermute der Ansatz selber ist einfach schwachsinnig. Wie würdet ihr da rangehen?

drakon

Supermoderator

Beiträge: 6 513

Wohnort: Schweiz

Beruf: Entrepreneur

  • Private Nachricht senden

2

05.01.2008, 10:18

Moment...da habe ich letztlich erst gerade für mein Font gemacht...


Ich gebe dir mal den ganzen Code, weiss nicht, ob es dir was bringt, aber ich habe hald bei mir einfach ne andere Klasse

C-/C++-Quelltext

1
    template<class T>CFont& operator <<     (T t) {Write(t); return *this;}


*this ist auche eine CFont - Klasse..

Also ich persönlich würde bei dir einfach anstatt nen const char zeiger einen std::string übergeben... Den könntest du ja auch einfacher zurückgeben.

rklaffehn

Treue Seele

Beiträge: 267

Wohnort: Braunschweig

  • Private Nachricht senden

3

05.01.2008, 10:35

Wieso willst du einen ostringstream als Ergebnis liefern, wenn du einen Stream-Operator für deine Output Klasse definierst?

Vermutlich meinst du:

C-/C++-Quelltext

1
2
3
4
5
6
Output& Output::operator << (const char* s)
{
  std::cout << s; 
  mLog << s; 
  return *this;
}


Das folgt auch der Implementation der std::stream Operatoren, weil man damit diese schönen "Umleitketten" bauen kann. So funktioniert nämlich auch:

C-/C++-Quelltext

1
2
Output log;
log << "foo" << "bar";


Mit deiner Implementation -- wenn sie denn compilieren oder funktionieren würde :) -- würde das "bar" in einem stringstream landen und gar nicht ausgegben werden.
God is real... unless declared integer.
http://www.boincstats.com/signature/user_967277_banner.gif

drakon

Supermoderator

Beiträge: 6 513

Wohnort: Schweiz

Beruf: Entrepreneur

  • Private Nachricht senden

4

05.01.2008, 11:09

Das ist ja ziemlich genau das, was ich gemacht habe.. :D
Habe einfach noch Templates drinn, damit ich mir keine Gedanken um den Typ machen muss bei der Ausgabe.. Auch ganz Nützlich ;-)

Wenn ich mal das Vorgehen demonstrieren darf, wie ich es mir vorstelle:

Output log;
log << "foo" << "bar"; Wird nachdem "foo" ausgewertet und die Referenz zurückgegeben wurde zu:
(Zurückgegebene Referenz zu log) << "bar";

Das Gurke

Community-Fossil

  • »Das Gurke« ist der Autor dieses Themas

Beiträge: 1 996

Wohnort: Pinneberg

Beruf: Schüler

  • Private Nachricht senden

5

05.01.2008, 15:51

Danke, nun hab ichs auch Begriffen ^^ Komisch, dass ich solange mit dem Operator << gearbeitet habe ohne ihn je richtig zu verstehen *g*

Trotzdem hab ich noch ein Problem über, und zwar frage ich mich von welchem Typ "std::endl" ist? Habe hier grad wie ein wilder über die "Gehe zu Definition" vom Visual Studio rumgesucht, aber keine überzeugende Lösung gefunden. Ausserdem lässt es sich, durch die Templates, mehrdeutig auflösen... Da kommt man sich ja vor wie ein Anfänger *g*

drakon

Supermoderator

Beiträge: 6 513

Wohnort: Schweiz

Beruf: Entrepreneur

  • Private Nachricht senden

6

05.01.2008, 16:44

Also ich würde std::endl ganz einfach als

C-/C++-Quelltext

1
 const char endl = '\c';

definieren. :D

Weiss aber nicht, wie das geregelt ist.

Also mit dem Templates ist es ganz einfach. Da kannst du eine Templatefunktion schreiben, wie meine und dann einfach die überladene Funktion aufrufen mit dem Typ, der gerade gefragt ist.

7

05.01.2008, 17:07

C-/C++-Quelltext

1
2
3
4
5
Also ich würde std::endl ganz einfach als
Code (C++):
 const char endl = '\c';

definieren. Very Happy 
? Ähm...

std::endl packt ein Newline-Zeichen in den Stream und ruft dann std::flush auf.
Devil Entertainment :: Your education is our inspiration
Der Spieleprogrammierer :: Community Magazin
Merlin - A Legend awakes :: You are a dedicated C++ (DirectX) programmer and you have ability to work in a team? Contact us!
Siedler II.5 RttR :: The old settlers-style is comming back!

Also known as (D)Evil

drakon

Supermoderator

Beiträge: 6 513

Wohnort: Schweiz

Beruf: Entrepreneur

  • Private Nachricht senden

8

05.01.2008, 17:10

Ich habe ja geschrieben, dass ICH es so machen und auch funktionieren würde...

Das Gurke

Community-Fossil

  • »Das Gurke« ist der Autor dieses Themas

Beiträge: 1 996

Wohnort: Pinneberg

Beruf: Schüler

  • Private Nachricht senden

9

05.01.2008, 17:14

Nene, mir geht es schon um das "originale" endl mit flush ... Wenn ich mir std::endl jedoch so anschaue krieg ich ein wenig das kalte grausen. Wie genau bekomm ich denn eine Überladung für dieses ... Ding?

C-/C++-Quelltext

1
2
3
4
5
6
7
_CRTIMP2_PURE inline basic_ostream<char, char_traits<char> >&
    __CLRCALL_OR_CDECL endl(basic_ostream<char, char_traits<char> >& _Ostr)
    {   // insert newline and flush byte stream

    _Ostr.put('\n');
    _Ostr.flush();
    return (_Ostr);
    }

Der brachiale Ansatz funktioniert nicht:

C-/C++-Quelltext

1
2
3
4
5
6
7
    Output& Output::operator << (const std::endl& s)
    {
        std::cout << s;
        mLog << s;

        return (*this); 
    }

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Fehler  1   error C4430: Fehlender Typspezifizierer - int wird angenommen. Hinweis: "default-int" wird von C++ nicht unterstützt.  f:\projekte\word\word - server\src\Output.h 23
Fehler  5   error C4430: Fehlender Typspezifizierer - int wird angenommen. Hinweis: "default-int" wird von C++ nicht unterstützt.  f:\projekte\word\word - server\src\Output.h 23
Fehler  9   error C4430: Fehlender Typspezifizierer - int wird angenommen. Hinweis: "default-int" wird von C++ nicht unterstützt.  f:\Projekte\WoRD\WoRD - Server\src\Output.cpp   39
Fehler  13  error C4430: Fehlender Typspezifizierer - int wird angenommen. Hinweis: "default-int" wird von C++ nicht unterstützt.  f:\projekte\word\word - server\src\Output.h 23
Fehler  2   error C2751: 'std::endl': Der Name eines Funktionsparameters kann nicht qualifiziert sein   f:\projekte\word\word - server\src\Output.h 23
Fehler  6   error C2751: 'std::endl': Der Name eines Funktionsparameters kann nicht qualifiziert sein   f:\projekte\word\word - server\src\Output.h 23
Fehler  10  error C2751: 'std::endl': Der Name eines Funktionsparameters kann nicht qualifiziert sein   f:\Projekte\WoRD\WoRD - Server\src\Output.cpp   39
Fehler  14  error C2751: 'std::endl': Der Name eines Funktionsparameters kann nicht qualifiziert sein   f:\projekte\word\word - server\src\Output.h 23
Fehler  4   error C2535: 'WoRD::Output &WoRD::Output::operator <<(int)': Memberfunktion bereits definiert oder deklariert   f:\projekte\word\word - server\src\Output.h 23
Fehler  8   error C2535: 'WoRD::Output &WoRD::Output::operator <<(int)': Memberfunktion bereits definiert oder deklariert   f:\projekte\word\word - server\src\Output.h 23
Fehler  16  error C2535: 'WoRD::Output &WoRD::Output::operator <<(int)': Memberfunktion bereits definiert oder deklariert   f:\projekte\word\word - server\src\Output.h 23
Fehler  3   error C2143: Syntaxfehler: Es fehlt ',' vor '&' f:\projekte\word\word - server\src\Output.h 23
Fehler  7   error C2143: Syntaxfehler: Es fehlt ',' vor '&' f:\projekte\word\word - server\src\Output.h 23
Fehler  11  error C2143: Syntaxfehler: Es fehlt ',' vor '&' f:\Projekte\WoRD\WoRD - Server\src\Output.cpp   39
Fehler  15  error C2143: Syntaxfehler: Es fehlt ',' vor '&' f:\projekte\word\word - server\src\Output.h 23
Fehler  12  error C2084: Funktion 'WoRD::Output &WoRD::Output::operator <<(int)' hat bereits einen Funktionsrumpf   f:\Projekte\WoRD\WoRD - Server\src\Output.cpp   40

drakon

Supermoderator

Beiträge: 6 513

Wohnort: Schweiz

Beruf: Entrepreneur

  • Private Nachricht senden

10

05.01.2008, 18:29

C-/C++-Quelltext

1
Output& Output::operator << (const std::endl& s) 


Warum hast du da std::endl drinn?
Ich versteh jetzt nicht alles, was dort bei der Definition steht, aber es scheint ja kein Typ zu sein.. :?

Werbeanzeige