Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Bildschirmausgabe

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: [ 1 ] > 2 < [ 3 ]
010
29.07.2003, 14:53 Uhr
virtual
Sexiest Bit alive
(Operator)


Zu diesem Thema mal ein paar Anregungen, vielleicht mach ich da mal was richtiges raus:

C++:
#include <iostream>
#include <unistd.h> // Nur wegen sleep. Unter Windows muß das sleep Großgeschrieben werden. Hat aber nichts mit den Escape Dingern zu tun.

static const char ESC = 27;

//  --- Bildschirm löschen ---------------------------------------------------

std::ostream& clear(std::ostream& out)
{
    out<<ESC<<"[2J";
    return out;
}

//  --- Cursor absolut setzen ------------------------------------------------

struct locate
{
    int x;
    int y;

    locate(int x_, int y_) :x(x_), y(y_) {};
};

std::ostream& operator<<(std::ostream& out, const locate& loc)
{
    out<<ESC<<'['<<loc.x<<';'<<loc.y<<'H';
    return out;
}

//  --- Cursor relativ veschieben --------------------------------------------

struct move
{
    enum DIRECTION
    {
        UP,
        DOWN,
        RIGHT,
        LEFT
    };

    DIRECTION d;
    int n;

    move(DIRECTION d_, int n_ = 1) :d(d_), n(n_) {};
};

std::ostream& operator<<(std::ostream& out, const move& mov)
{
    out<<ESC<<'['<<mov.n;
    switch (mov.d)
    {
    case move::UP: out<<'A'; break;
    case move::DOWN: out<<'B'; break;
    case move::RIGHT: out<<'C'; break;
    case move::LEFT: out<<'D'; break;
    }
    return out;
}

//  --- Kleines Demo ---------------------------------------------------------

int main()
{
    const char* text = "Hallo, Welt!";
    int len = strlen(text);
    std::cout<<clear<<locate(10,10)<<std::flush;

    for(int i=0; i<len; ++i)
    {
        sleep(1);
        std::cout<<text[i]<<std::flush<<move(move::DOWN)<<move(move::LEFT)
                 <<'-'<<move(move::UP)<<std::flush;
    }
    std::cout<<locate(0,0)<<std::flush;
}


--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)

Dieser Post wurde am 29.07.2003 um 14:54 Uhr von virtual editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
011
29.07.2003, 18:14 Uhr
Pablo
Supertux
(Operator)


hey, schönes Beispiel!
--
A! Elbereth Gilthoniel!
silivren penna míriel
o menel aglar elenath,
Gilthoniel, A! Elbereth!
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
012
30.07.2003, 13:13 Uhr
typecast
aka loddab
(Operator)


Das Beispiel gefällt mir auch
Aber eine Frage hab ich noch: Du schreibst z.B.

C++:
move(DIRECTION d_, int n_ = 1) :d(d_), n(n_) {};



Was bedueten die Unterstriche hinter dem d und dem n?
--
All parts should go together without forcing. ... By all means, do not use a hammer. (IBM maintenance manual, 1925)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
013
30.07.2003, 13:30 Uhr
virtual
Sexiest Bit alive
(Operator)


Gehören zum Variablennamen. Hier habe ich die Parameter eben mit einem trailing Underscore versehen. Ich mach auch oft ein "p_" vor den Parameternamen, um kenntlich zu machen, daß es ein parameter ist. Funktionalgesehen keinerlei bedeutung
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
014
30.07.2003, 13:33 Uhr
typecast
aka loddab
(Operator)


dann ist alles klar!
--
All parts should go together without forcing. ... By all means, do not use a hammer. (IBM maintenance manual, 1925)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
015
30.07.2003, 23:24 Uhr
Pablo
Supertux
(Operator)


Was mich gewundert hat ist:


Code:
move(DIRECTION d_, int n_ = 1) :d(d_), n(n_) {};



Wieso ist diese Funktion leer? ich meine natürlich, dass der Rumpf der Funktion leer ist und trotzdem funktioniert. Was bedeutet ganz genau das Zeichen : nach geschloßenem Klammer?
--
A! Elbereth Gilthoniel!
silivren penna míriel
o menel aglar elenath,
Gilthoniel, A! Elbereth!
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
016
31.07.2003, 01:41 Uhr
virtual
Sexiest Bit alive
(Operator)


@Pablo:
Es ist ein Constructor. Die Initialisierer machen alles, was notwendig ist, eben d und n initialisieren. Da bracuht dann auch nichts mehr in den Body rein. : Leitet die Initialisiererliste ein
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)

Dieser Post wurde am 31.07.2003 um 01:41 Uhr von virtual editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
017
31.07.2003, 02:00 Uhr
Pablo
Supertux
(Operator)


Konstructor? Heißt das, dass :d(d_) sagt, dass die Variable d den wert von d_ speichern muss? Aber wieso in Klammern? Ist das eine andere Form einen Konstruktor zu deklarieren?
--
A! Elbereth Gilthoniel!
silivren penna míriel
o menel aglar elenath,
Gilthoniel, A! Elbereth!
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
018
31.07.2003, 08:53 Uhr
virtual
Sexiest Bit alive
(Operator)


Zunächstmal was zu den Begrifflichkeiten:

C++:
void f();


Ist eine Deklaration.

C++:
void f()
{
....
}


Ist eine Definition; wenn vorher im Quelltext keine Deklaration gefunden wurde, ist es auch die Deklaration.

Bei unserem ctor handelt es sich also um einen Deklaration und eine Definition, weil da das Semikolon nach dem schliessenden Klammer der parameterliste fehlt und "irgendwas" anderes kommt. Obigen ctor hätte man auch so schreiben können:

C++:
move(DIRECTION d_, int n_ = 1)
{
   d = d_;
   n = n_;
}


Nun gibt es speziell beim Ctor ja die Situation, daß man bestimmte Sachen initialisieren muß, bevor man in den Body vom ctor ("{...}") eintritt. zB bei einer abgeleiteten Klasse die Basisklasse:

C++:
class Base
{
public:
     Base(int x);

};

class Derived: public Base
{
public:
      Derived(int x) :Base(x) { /*Hier muß der Base anteil bereits initialisiert sein */ }
};


Anders als in Java (da gibt es mit "super" die Möglichkeit, den Anteil von Base an beliebiger Stelle im ctor von Derived zu initialisieren) muß in C++ der Anteil von Base initialisiert sein, bevor in den Body vom Ctor gesprungen wird.Das wird von dem Initialisierer erledigt, also dem ":Base(x)".
Es gibt folgende Situationen, wo man mit Initialisieren arbeiten muß:
1. Bei Ableitungen (siehe oben) zum initialisieren der Basisklasse
2. Wenn die Klasse Referenzen enthält, müssen die Referenzen ebenfalls vor Eintritt in den Body vom ctor initialisiert werden.
3. Wenn die Klasse eine Aggregation von anderen Klassen ist, die keinen Defaultconstructor bereitstellen (Fall 2 ist so gesehen ein Spezialfall von diesem).

Man kann generell sagen, daß man alle Attribute eine ctor mit Initialisierern initialisieren kann und (wie im move Beispiel) einen leeren Body hat. Das macht vor allem dann sinn, wenn man andere, kompliziert zu konstruierende Objekte als Membervariablen hat. Beispiel:

C++:
class Bad
{
     std::string x;
public:
     Bad(const std::string& x_)
     {
        x = x_;
     }
};

class Good
{
     std::string x;
public:
     Good(const std::string& x_) :x(x_) { }
};


Sowohl die Klasse Goood alsauch die Klasse Bad sind rein C++ technisch okay (es sei denn, ich habe mich vertippt), allerdings tun sie zwei recht unterschiedliche Dinge im Ctor:
Bad Unternimmt im ctor folgende Schritte:
1. Es ruft den Default-ctor für Bad::x (ein std::string) auf
2. Es ruft den Zuweisungsoperator von std::string auf, weil ja im Body eine Zuweisung stattfindet.
3. Der Zuweisungoperator wird - wenn er Exceptionsicher geschrieben sein will, in der Regel die Contruction eines weiteres temp. string objektes nach sich ziehen
Good hingegen macht genau einen Schritt:
1. Es ruft den Copy-Constructor für Good::x auf.

Generell kann man also sagen, daß die Verwendung von Initialisieren die Performance begünstigen, in einigen Situation sogar zwingend erforderlich sind.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
019
31.07.2003, 11:48 Uhr
ao

(Operator)



Zitat:
virtual postete
Es gibt folgende Situationen, wo man mit Initialisieren arbeiten muß:
1. Bei Ableitungen ...
2. Wenn die Klasse Referenzen enthält ...
3. Wenn die Klasse eine Aggregation ...


Eine hast du vergessen:
4. Wenn die Klasse const-Member enthält, müssen diese ebenfalls in der Initialisierer-Liste initialisiert werden (eine Zuweisung im c'tor-Body erfüllt den Zweck nicht).

Ich möchte noch hinzufügen, dass die Objekte nicht (wie man spontan vermuten könnte) in der Reihenfolge initialisiert werden, wie sie in der Initialisierer-Liste aufgelistet sind (denn die ist beliebig), sondern in der, in der sie in der Klassendeklaration (also class X { ... } deklariert sind.
Nur für den Fall, dass die Reihenfolge der Initialisierung mal eine Rolle spielt.

ao
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: [ 1 ] > 2 < [ 3 ]     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: