Schon eine Klasse?



  • Hallo,

    ich trau mich immer nie so recht zu fragen, egal wo, aber ich habe immer noch Schwierigkeiten mit Klassen. Deshalb habe ich mir eine erstellt (aus einer vorherigen struct, vielleicht sieht man das gar noch?), die das Konsolenfenster verschiebt und dessen Werte ermittelt.

    Hat diese schon Ähnlichkeiten mit einer Klasse in C++?
    (Die Auskommentierungen erstmal nicht beachten)

    #include "display.h"
    //#include <vector>
    
    class Console
    {
    public:
    
        HANDLE hndl = GetStdHandle( STD_OUTPUT_HANDLE );
        HWND consl = GetConsoleWindow();
        CONSOLE_SCREEN_BUFFER_INFO csbi = {};
        Display display;                          //Monitorauflösung holen
    
        int getWindow_size() const { return window_size; };
        int getWindow_xpos() const { return pos_x; };
        int getWindow_ypos() const { return pos_y; };
        double getAspect_x() const { return aspect_x; };
        double getAspect_y() const { return aspect_y; };
        double getAspect_ratio() const { return aspect_ratio; };
        int getColumns() const { return columns; };
        int getRows() const { return rows; };
    
        Console( int cwindow_size,                 //Konstruktor
                 int cpos_x, int cpos_y )
        {
            window_size = cwindow_size;
            pos_x = cpos_x;
            pos_y = cpos_y;
            moveWindow( consl, hndl, csbi, display, window_size, pos_x, pos_y );
        }
    
        void getCsbi( HANDLE hndl,
                      CONSOLE_SCREEN_BUFFER_INFO csbi )
        {
            GetConsoleScreenBufferInfo( hndl, &csbi );
            columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
            rows = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
        };
    
        void moveWindow( HWND consl,                 //Konsolenfenster verschieben
                         HANDLE hndl,
                         CONSOLE_SCREEN_BUFFER_INFO csbi,
                         Display display,
                         int& window_size,
                         int& pos_x, int& pos_y )
        {
            if ( window_size < static_cast<int> ( (display.height - 22) * aspect_ratio ) ) //wenn window_size einen bestimmten Wert...
            {
                int window_left = static_cast<int> ( (display.width/2 - window_size/2) ) + pos_x;
                int window_top = static_cast<int> ( (display.height/2 - (window_size/aspect_ratio)/2) ) + pos_y;
                int window_right = window_size;
                int window_bottom = static_cast<int> ( window_size/aspect_ratio );
                MoveWindow( consl, window_left, window_top, window_right, window_bottom, TRUE );
                getCsbi( hndl, csbi );
            }
            else //...Konsole wird maximiert
            {
                window_size = display.width;
                pos_x = 0;
                pos_y = 0;
                aspect_x = display.aspect_x;
                aspect_y = display.aspect_y;
                aspect_ratio = aspect_x / aspect_y;
                ShowWindow( consl, SW_MAXIMIZE );
                getCsbi( hndl, csbi );
            }
        };
    
    private:
    
        int window_size = 0;
        double aspect_x = 4.0, aspect_y = 3.0;
        double aspect_ratio = aspect_x / aspect_y;
        int pos_x = 0, pos_y = 0;
        int columns = 0, rows = 0;
        //std::vector <CHAR_INFO> outbuffer;
    
    };
    
    #include "console.h"
    #include <iostream>
    
    void showValues( Console console )
    {
        //std::cout << "Monitor Width: " << display.width << "  Monitor Height: " << display.height;
        //std::cout << "  Aspect Ratio: " << display.aspect_x << "/" << display.aspect_y << '\n';
        std::cout << "Console Width: " << console.getWindow_size()
                  << "  Console Height: " << static_cast<int> ( console.getWindow_size() / console.getAspect_ratio() );
        std::cout << "  Aspect Ratio: " << console.getAspect_x() << "/" << console.getAspect_y() << '\n';
        std::cout << "Columns: " << console.getColumns() << "  Rows: " << console.getRows() << '\n';
        //std::cout << "Coord X: " << drawing.coord_width << "  Coord Y: " << drawing.coord_height;
        //std::cout << "  Center X: " << drawing.center.cx << "  Center Y: " << drawing.center.cy << '\n';
        //std::cout << "outbuffer_size: " << console.outbuffer.size();
        //std::cout << "  drawing.chars_size: " << drawing.chars.size() << '\n';
    }
    
    int main()
    {
    
        Console console( 1200, 0, 0 );
        showValues( console );
    
    }
    


  • lemon03 schrieb:

    Hat diese schon Ähnlichkeiten mit einer Klasse in C++?

    du verwendest doch das schlüsselwort "class" und legst sogar ein objekt von "Console" an.
    also hast du selbstverständlich eine klasse gebastelt. 🙂

    oder was meinst du, was das ist?



  • Naja, ich hatte gehofft, das ich schon richtig denke, das ich eine Klasse erstellt habe 😉

    Aber aus Deiner Antwort entnehme ich, das ich diese erstmal weiterverwenden kann, ohne sie später großartig wegen "aliencode" oder so, ändern muss? Oder ohne das der Code der Klasse irgendwie "anstößig" ist?



  • eine Klasse in C++ ist wie eine Struct. nur dass in einer Struct alles per Default public ist. Das ist IMHO der einzige Unterschied. Du kannst sogar Funktionen in die Struct packen. Genau wie bei Klassen.


  • Mod

    Fricky667, bitte sei einfach still zu Themen, von denen du keine Ahnung hast. Was mindestens alle sind, die den Buchstaben 'C' im Namen haben. Überall muss man ständig nur deinen Müll korrigieren, anstatt anderen helfen zu können. Er möchte wissen, ob das gutes Klassendesign ist, nicht deine Möchtegernklugscheißerkommentare, dass es technisch gesehen eine Klasse ist, weil 'class' dran steht.

    Ich hätte das hier erläutern könne, aber ich sehe, du warst heute schon wieder im C-Forum unterwegs, wo ich wieder hinter dir sauber machen muss. Da muss ich hoffen, dass hier jemand vorbei kommt, der es stattdessen erklärt 🙄



  • Richtig, ja danke 🙂



  • Sieht auf den ersten Blick gut aus.

    Ich persönlich schreibe in die Klassendeklaration nur die Köpfe der Methoden und Definiere sie dann Auserhalb. Das bringt mehr Übersichtlichkeit über die Klasse.



  • Aber immer noch innerhalb des header? Und ist das richtig, das dies dann mit inline geschehen muss?



  • Was ist denn die Aufgabe der Klasse? Nur verschieben und Werte ermitteln? Wären das vielleicht eher zwei einfach Funktionen?

    Du benutzt den Konstuktor mit seinen Parametern, um direkt das Fenster zu manipulieren. Ich würde da eher einen Konstruktor ohne Parameter erwarten. Und dann zwei Funktionen move und resize, die aber nicht das ganze Handel gedöns übergeben bekommen. Das kennt das instanziierte Consoleobjekt ja schon. Stattdessen erhalten sie nur einen Point bzw. eine Size.

    hndl + consl ist public. Warum?

    Macht es Sinn, dass die Klasse kopierbar ist? Du kopierst sie jedenfalls in showValues.



  • lemon03 schrieb:

    Aber immer noch innerhalb des header? Und ist das richtig, das dies dann mit inline geschehen muss?

    Das machst du wie du willst, Header-only ist handlicher, andersrum eher übersichtlicher.

    Oder du schreibst Deklarationen in einen Header und Definitionen in einen anderen, denn du am Ende deiner Deklarationen einfach inkludierst.



  • Aha, danke.

    @ manni66

    Aihahai, da muss ich erstmal überlegen, um alle Fragen beantworten zu können.

    Angefangen habe ich damit, das ich alles in eine struct gepackt habe, damit mir die Funktionsaufrufe mit den Werten darin einfacher gehen. Aber das diese Klasse wirklich eigentlich nur den Zweck einer übergroßen Funktion hat, wurmt mich auch ein wenig.

    Ich muss mal ein wenig schauen, zu Deinen Ratschlägen. Nur was mit 'Klasse kopieren' gemeint ist, würde ich gerne noch wissen.



  • Klasse kopieren ist natürlich auch falsch formuliert. Ich meinte: sollen Objekte der Klasse kopierbar sein? Wenn du showValues aufrufst, erzeugst du erstmal eine Kopie, weil der Parameter keine Referenz ist. Das sollte vielleicht ganz verhindert werden, da es nicht sinnvoll ist.



  • Aha, würde das reichen, wenn ich die Klasse const übergebe, oder direkt als Referenz?

    Und wegen der Klasse selber, ich habe sie jetzt so geändert. War das in etwa so gemeint:?

    class Console
    {
    
    public:
    
        Display display;       //Monitorauflösung holen
    
        int getWindow_size() const { return window_size; };
        int getWindow_xpos() const { return pos_x; };
        int getWindow_ypos() const { return pos_y; };
        double getAspect_x() const { return aspect_x; };
        double getAspect_y() const { return aspect_y; };
        double getAspect_ratio() const { return aspect_ratio; };
        int getColumns() const { return columns; };
        int getRows() const { return rows; };
        std::vector <CHAR_INFO> outbuffer;
    
       //neue Methoden nur zur Änderung der Konsole
    
        void move_( int cpos_x, int cpos_y )
        {
            pos_x = cpos_x;
            pos_y = cpos_y;
            moveWindow();
        }
    
        void resize_( unsigned int cwindow_size )
        {
            window_size = cwindow_size;
            moveWindow();
        }
    
        /////////////////////////////////////////////
    
        void getCsbi()
        {
            GetConsoleScreenBufferInfo( hndl, &csbi );
            columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
            rows = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
        };
    
        void moveWindow()
        {
            if ( window_size < static_cast<unsigned int> ( (display.height - 22) * aspect_ratio ) ) //wenn window_size einen bestimmten Wert...
            {
                int window_left = static_cast<int> ( (display.width/2 - window_size/2) ) + pos_x;
                int window_top = static_cast<int> ( (display.height/2 - (window_size/aspect_ratio)/2) ) + pos_y;
                int window_right = window_size;
                int window_bottom = static_cast<int> ( window_size/aspect_ratio );
                MoveWindow( consl, window_left, window_top, window_right, window_bottom, TRUE );
                getCsbi();
            }
            else //...Konsole wird maximiert
            {
                window_size = display.width;
                pos_x = 0;
                pos_y = 0;
                aspect_x = display.aspect_x;
                aspect_y = display.aspect_y;
                aspect_ratio = aspect_x / aspect_y;
                ShowWindow( consl, SW_MAXIMIZE );
                getCsbi();
            }
        };
    
    private:
    
        HANDLE hndl = GetStdHandle( STD_OUTPUT_HANDLE );
        HWND consl = GetConsoleWindow();
        CONSOLE_SCREEN_BUFFER_INFO csbi = {};
    
        unsigned int window_size = 0;
        double aspect_x = 4.0, aspect_y = 3.0;
        double aspect_ratio = aspect_x / aspect_y;
        int pos_x = 0, pos_y = 0;
        int columns = 0, rows = 0;
    
    };
    

    EDIT: An die Membermethoden (der richtige Begriff?) muss ich ja gar nichts übergeben, weil ja alles bekannt...



  • Ich habe jetzt noch einen Konstruktor hinzugefügt, damit es kein großes Wundern gibt, wenn man Console ohne resize_() oder move_() aufruft.

    Console()
      {
          resize_( 800 );
      }
    


  • Die Richtung stimmt (wenn man tatsächlich eine Klasse dafür benutzen möchte). Warum move_? move!

    Da ist noch zu viel public. Was wird wirklich von Außen aufgerufen bzw. benutzt? Alles andere ist private.



  • lemon03 schrieb:

    Aha, würde das reichen, wenn ich die Klasse const übergebe, oder direkt als Referenz?

    Sowohl als auch! Als const-Referenz, du willst das Objekt ja weder kopieren noch irgendwas ändern.
    Also: void showValues(const Console &console) { ... }

    Für den Fall, dass es keinen Sinn ergibt, dass man Objekte deiner Klasse kopiert, kannst du einfach den Copy-Constructor und den Zuweisungsoperator löschen:

    class Console {
       ...
       Console(const Console&) = delete;
       Console& operator=(const Console&) = delete;
       ...
    };
    

    Ein Kommentar noch: ich mag ja camelCase sehr gern und nutze das für all meine eigenen Klassen, während der Standard ja lieber_underscores_mag. Aber eine Kombination von beiden wie in getAspect_ratio() finde ich doch etwas merkwürdig.



  • Ok, werde ich das mal verbessern.

    move_ und so, weil move doch schon ein Schlüsselwort ist, aber da habe ich wohl etwas quer gedacht.

    Bedankt schon mal für die bisherigen Hilfen 🙂

    PS: Variablen in underscores und Funktionen in camelCase ist aber schon ok?


Anmelden zum Antworten