Basisklasse erstellen?



  • Hallo,

    meine Klassen sind soweit fertig, jetzt überlege ich sie unter eine Basisklasse zu stellen. Wenn ich das richtig verstanden habe, kann ich dann bei Bedarf Methoden für beide gleichzeitig aufrufen, das fände ich ganz hilfreich. Im Detail habe ich mich noch nicht damit beschäftigt, will erst erfahren, ob das hier sinnvoll ist.
    Hoffe die Codes sind nicht zu groß fürn Forum. Sonst sollte ich sie auf einer anderen Seite zeigen?

    #pragma once
    
    #include "console.h"
    #include <map>
    
    class Draw
    {
    
    public:
    
        Console& console;
        std::map <std::string, std::vector <CHAR_INFO>> chars;
    
        Draw( Console& console ) : console( console )
        {
            getDefaultChars();
            get_Dims();
            resetCoords();
        }
    
         void getDims()
        {
            get_Dims();
        }
    
        unsigned int getXWidth() const { return used.width; }
        unsigned int getYHeight() const { return used.height; }
        int getCenterX() const { return used.center_x; }
        int getCenterY() const { return used.center_y; }
    
        unsigned int getCoordXWidth() const { return scaled.width; }
        unsigned int getCoordYHeight() const { return scaled.height; }
        int getCoordCenterX() const { return scaled.center_x; }
        int getCoordCenterY() const { return scaled.center_y; }
    
        unsigned int getOrigCoordXWidth() const { return coord.width; }
        unsigned int getOrigCoordYHeight() const { return coord.height; }
        int getOrigCoordCenterX() const { return coord.center_x; }
        int getOrigCoordCenterY() const { return coord.center_y; }
    
        void addChars( std::string,
                       const std::vector <WCHAR>&,
                       const std::vector <WORD>& );
        void resizeCoords( unsigned int,
                           unsigned int );
        void useCoords( const bool& );
        void resetCoords();
    
    private:
    
         struct Coord
        {
            unsigned int width = 0;
            unsigned int height = 0;
            int center_x = 0;
            int center_y = 0;
            bool b = false;
        };
    
        Coord dim, coord, scaled, used;
    
        std::string default_name = "default";
        std::vector <WCHAR> unicodes = { '*', '@', 219 };
        std::vector <WORD> attributes = { 0, 15, 7, 8, 4, 12, 6, 14, 10, 11, 3, 9, 1, 13, 5 };
    ////Funktionen, in denen Werte von Draw und Paint verschieden sind
        void get_Dims()
        {
            dim.width = console.getColumns();
            dim.height = console.getRows() * 2;
            dim.center_x = toInt( dim.width / 2.0 );
            dim.center_y = toInt( dim.height / 2.0 );
            dim.b = false;
            used = dim;
        };
    
        void getDefaultChars()
        {
            addChars( default_name, unicodes, attributes );
        };
    ////////////////////////////////////////////////////////////
        unsigned int toUInt( double );
        int toInt( double );
    };
    
    inline void Draw::addChars( std::string name,
                                const std::vector <WCHAR>& unicodes,
                                const std::vector <WORD>& attributes )
    {
        CHAR_INFO ch;
        std::vector <CHAR_INFO> tmp_vec;
        for ( auto i : unicodes )
        {
            for ( auto j : attributes )
            {
                ch.Char.UnicodeChar = i;
                ch.Attributes = j;
                tmp_vec.push_back( ch );
            }
        }
        chars.insert( std::make_pair( name, tmp_vec ));
    }
    ////Funktionen, in denen Werte von Draw und Paint verschieden sind
    inline void Draw::resizeCoords( unsigned int co_width,
                                    unsigned int co_height )
    {
        coord.width = co_width;
        coord.height = co_height;
        coord.center_x = toInt( coord.width / 2.0 );
        coord.center_y = toInt( coord.height / 2.0 );
        scaled = coord;
        scaled.width = toUInt( co_width * console.getAspectRatio() );
        scaled.center_x = toInt( scaled.width / 2.0 );
        useCoords( used.b );
    }
    ///////////////////////////////////////////////////////////////
    inline void Draw::useCoords( const bool& use = true )
    {
        if ( use )
        {
            used = scaled;
            used.b = true;
        }
        else
        {
            used = dim;
            used.b = false;
        }
    }
    
    inline void Draw::resetCoords()
    {
        coord.width = 1;
        coord.height = 1;
        coord.center_x = 1;
        coord.center_y = 1;
        coord.b = false;
        scaled = coord;
        used = dim;
    }
    
    inline unsigned int Draw::toUInt( double val )
    {
        return static_cast<unsigned int> ( std::round( val ) );
    }
    
    inline int Draw::toInt( double val )
    {
        return static_cast<int> ( std::round( val ) );
    }
    
    #pragma once
    
    #include "console.h"
    #include <map>
    
    class Paint
    {
    
    public:
    
        Console& console;
        std::map <std::string, std::vector <CHAR_INFO>> chars;
    
        Paint( Console& console ) : console( console )
        {
            getDefaultChars();
            get_Dims();
            resetCoords();
        }
    
         void getDims()
        {
            get_Dims();
        }
    
        unsigned int getXWidth() const { return used.width; }
        unsigned int getYHeight() const { return used.height; }
        int getCenterX() const { return used.center_x; }
        int getCenterY() const { return used.center_y; }
    
        unsigned int getCoordXWidth() const { return scaled.width; }
        unsigned int getCoordYHeight() const { return scaled.height; }
        int getCoordCenterX() const { return scaled.center_x; }
        int getCoordCenterY() const { return scaled.center_y; }
    
        unsigned int getOrigCoordXWidth() const { return coord.width; }
        unsigned int getOrigCoordYHeight() const { return coord.height; }
        int getOrigCoordCenterX() const { return coord.center_x; }
        int getOrigCoordCenterY() const { return coord.center_y; }
    
        void addChars( std::string,
                       const std::vector <WCHAR>&,
                       const std::vector <WORD>& );
        void resizeCoords( unsigned int,
                           unsigned int );
        void useCoords( const bool& );
        void resetCoords();
    
    private:
    
         struct Coord
        {
            unsigned int width = 0;
            unsigned int height = 0;
            int center_x = 0;
            int center_y = 0;
            bool b = false;
        };
    
        Coord dim, coord, scaled, used;
    
        std::string default_name = "default";
        std::vector <WCHAR> unicodes = { 177, 219 };
        std::vector <WORD> attributes = { 0, 15, 7, 8, 4, 12, 6, 14, 10, 11, 3, 9, 1, 13, 5 };
    ////Funktionen, in denen Werte von Draw und Paint verschieden sind
        void get_Dims()
        {
            dim.width = toUInt( console.getColumns() / 2.0 );
            dim.height = console.getRows();
            dim.center_x = toInt( dim.width / 2.0 );
            dim.center_y = toInt( dim.height / 2.0 );
            dim.b = false;
            used = dim;
        };
    
        void getDefaultChars()
        {
           addChars( default_name, unicodes, attributes );
        };
    ///////////////////////////////////////////////////////////
        unsigned int toUInt( double );
        int toInt( double );
    };
    
    inline void Paint::addChars( std::string name,
                                 const std::vector <WCHAR>& unicodes,
                                 const std::vector <WORD>& attributes )
    {
        CHAR_INFO ch;
        std::vector <CHAR_INFO> tmp_vec;
        for ( auto i : unicodes )
        {
            for ( auto j : attributes )
            {
                ch.Char.UnicodeChar = i;
                ch.Attributes = j;
                tmp_vec.push_back( ch );
            }
        }
        chars.insert( std::make_pair( name, tmp_vec ));
    }
    ////Funktionen, in denen Werte von Draw und Paint verschieden sind
    inline void Paint::resizeCoords( unsigned int co_width,
                                     unsigned int co_height )
    {
        coord.width = toUInt( co_width / 2.0 );
        coord.height = toUInt( co_height / 2.0 );
        coord.center_x = toInt( coord.width / 2.0 );
        coord.center_y = toInt( coord.height / 2.0 );
        scaled = coord;
        scaled.width = toUInt( co_width * console.getAspectRatio() / 2.0 );
        scaled.center_x = toInt( scaled.width / 2.0 );
        useCoords( used.b );
    }
    ////////////////////////////////////////////////////////////////////
    inline void Paint::useCoords( const bool& use = true )
    {
        if ( use )
        {
            used = scaled;
            used.b = true;
        }
        else
        {
            used = dim;
            used.b = false;
        }
    }
    
    inline void Paint::resetCoords()
    {
        coord.width = 1;
        coord.height = 1;
        coord.center_x = 1;
        coord.center_y = 1;
        coord.b = false;
        scaled = coord;
        used = dim;
    }
    
    inline unsigned int Paint::toUInt( double val )
    {
        return static_cast<unsigned int> ( std::round( val ) );
    }
    
    inline int Paint::toInt( double val )
    {
        return static_cast<int> ( std::round( val ) );
    }
    

    Sie werden in folgenden Grundfunktionen benutzt:

    void scaleToConsole( const Console& console, ////////////////////////Draw
                         const Draw& drawing, 
                         int& x, int& y )
    {
        double scale_x = console.getColumns() / static_cast<double> ( drawing.getXWidth() );
        x = toInt( scale_x * x );
        double scale_y = console.getRows() / static_cast<double> ( drawing.getYHeight() );
        y = toInt( scale_y * y );
    }
    
    void scalePToConsole( const Console& console, ////////////////////Paint
                          const Paint& painting, 
                          int& x, int& y )
    {
        double scale_x = console.getColumns() / static_cast<double> ( painting.getXWidth() );
        x = toInt( scale_x * x );
        double scale_y = console.getRows() / static_cast<double> ( painting.getYHeight() );
        y = toInt( scale_y * y );
    }
    
    void bufferDot( Console& console, //////////////////////////////Draw
                    const Draw& drawing, 
                    int x, int y,
                    std::string ch_name,
                    std::size_t ch_idx,
                    const bool& show )
    {
        scaleToConsole( console, drawing, x, y );
        if ( x >= 0 && x < console.getColumns() && y >= 0 && y < console.getRows() )
        {
            std::size_t out_idx = static_cast<std::size_t> ( console.getColumns() * y + x );
            console.outbuffer.at( out_idx ) = drawing.chars.find( ch_name )->second.at( ch_idx );
            if ( show ) console.writeBuffer(); //lässt den Weg der Dots folgen
        }
    }
    
    void bufferPDot( Console& console, //////////////////////////Paint
                     const Paint& painting, 
                     int x, int y,
                     std::string ch_name,
                     std::size_t ch_idx,
                     const bool& show )
    {
    
        scalePToConsole( console, painting, x, y );
        if ( x >= 0 && x < console.getColumns() && y >= 0 && y < console.getRows() )
        {
            std::size_t out_idx = static_cast<std::size_t> ( console.getColumns() * y + x );
            console.outbuffer.at( out_idx ) = painting.chars.find( ch_name )->second.at( ch_idx );
            if ( show ) console.writeBuffer(); //lässt den Weg der Dots folgen
        }
        x ++;
        if ( x >= 0 && x < console.getColumns() && y >= 0 && y < console.getRows() )
        {
            std::size_t out_idx = static_cast<std::size_t> ( console.getColumns() * y + x );
            console.outbuffer.at( out_idx ) = painting.chars.find( ch_name )->second.at( ch_idx );
            if ( show ) console.writeBuffer();
        }
    }
    
    void drawDot( Console& console,
                  const Draw& drawing,
                  int dotX1, int dotY1,
                  std::string ch_name,
                  std::size_t ch_idx,
                  const bool& show )
    {
        bufferDot( console, drawing,
                   dotX1, dotY1,
                   ch_name, ch_idx,
                   show );
    }
    
    void paintDot( Console& console,
                   const Paint& painting,
                   int dotX1, int dotY1,
                   std::string ch_name,
                   std::size_t ch_idx,
                   const bool& show )
    {
        bufferPDot( console, painting,
                    dotX1, dotY1,
                    ch_name, ch_idx,
                    show );
    }
    

    Vorgeschlagen wurde ein Template oder eine Basisklasse. Basisklasse würde ich bevorzugen. Hätte jemand Lust, sich das anzuschauen? Danke.



  • Basisklasse ... kann ich dann bei Bedarf Methoden für beide gleichzeitig aufrufen

    Irgendwie sehe ich da keinen Zusammenhang.



  • Vorgestellt in "Pseudocode" hatte ich mir das etwa so:

    class A
    {
       A( class Draw ) {}
    

    so das ich zB nicht, wenn es so sein soll,

    drawing.resizeCoords( 100, 100 );
    painting.resizeCoords( 100, 100 );
    

    aufrufen muss, sondern

    A::resizeCoords( 100, 100 );
    

    allerdings, müssen sie auch noch einzeln aufgerufen werden können, irgendwie so

    A::Draw::resizeCoords ( 100, 100 )
    

    Bleibt allerdings noch die Sache, wie ich hier vorgehen sollte. Ist aber vielleicht nicht so entscheidend.

    void scaleToConsole( const Console& console, ////////////////////////Draw
                         const Draw& drawing,
                         int& x, int& y )
    {
        double scale_x = console.getColumns() / static_cast<double> ( drawing.getXWidth() );
        x = toInt( scale_x * x );
        double scale_y = console.getRows() / static_cast<double> ( drawing.getYHeight() );
        y = toInt( scale_y * y );
    }
    
    void scalePToConsole( const Console& console, ////////////////////Paint
                          const Paint& painting,
                          int& x, int& y )
    {
        double scale_x = console.getColumns() / static_cast<double> ( painting.getXWidth() );
        x = toInt( scale_x * x );
        double scale_y = console.getRows() / static_cast<double> ( painting.getYHeight() );
        y = toInt( scale_y * y );
    }
    


  • Klar macht es Sinn, eine Basisklasse für beide zu erstellen, denn ein Großteil der Funktionen und Membervariablen sind ja komplett identisch.

    Packe einfach die entsprechenden Member in die neue Basisklasse und lasse dann beide bisherigen Klassen davon erben.

    Bei Unterschieden gibt es zwei Möglichkeiten:
    1. du machst die Basisklassenfunktion abstrakt und implementierst dann jeweils in den beiden Unterklassen die unterschiedliche Funktionalität
    oder
    2. du gibst in der Basisklasse eine der beiden Funktionalitäten als Vorgabe (virtual) und implementierst nur die andere Funktionalität in der anderen Unterklasse.

    So brauchst du auch nur noch eine Funktion

    void Dot( Console& console,
              const Base& base, // <-- hier natürlich einen besseren Namen finden
              int dotX1, int dotY1,
              std::string ch_name,
              std::size_t ch_idx,
              const bool& show );
    

    Andererseits sehe ich bisher am Source-Code zwischen beiden Klassen (und auch zwischen beiden Namen!) nicht, warum du überhaupt zwei verschiedene Funktionalitäten benötigst???
    Bis auf die Faktoren in get_Dims und resizeCoords sowie der Vector 'unicodes' sind sie identisch, und die könnte man auch einfach durch passende Eigenschaften (Konstruktorparameter bzw. Setter) bereitstellen.



  • Gut, danke für die Zielrichtung.

    Th69 schrieb:

    Andererseits sehe ich bisher am Source-Code zwischen beiden Klassen (und auch zwischen beiden Namen!) nicht, warum du überhaupt zwei verschiedene Funktionalitäten benötigst???
    Bis auf die Faktoren in get_Dims und resizeCoords sowie der Vector 'unicodes' sind sie identisch, und die könnte man auch einfach durch passende Eigenschaften (Konstruktorparameter bzw. Setter) bereitstellen.

    Ja, ich glaube ich verstehe, wie Du das meinst. Musste tatsächlich erst beide Klassen ausschreiben, bevor ich die Gemeinsamkeiten bzw Unterschiede so deutlich erkannt hatte.



  • PS: Hat jemand ne Vorstellung, wie ein Oberbegriff von draw und paint aussehen könnte? Arts...?



  • Hallo,

    wenn ich jetzt eine KLasse zB Tools habe, ist dann der Ansatz möglich und richtig, zwei Objekte zB paint und draw zu erstellen, die ihre eigenen Werte haben?

    Tools draw ( console );
    Tools paint ( console );
    


  • Ja, so funktioniert objektorientierte Programmierung 😉

    Ich verstehe nur nicht warum du die Klasse jetzt Tools nennst, und dich zwischen Draw oder Paint entschieden hast. Tools kann ja ziemlich alles sein.



  • Jupp, danke, bin ich auf der richtigen Fährte 😉

    Nun ja, da sowohl draw und paint Werkzeuge sind, um mein Ziel zu erreichen, dachte ich, ist doch ein guter Name.

    Bin Kritiken gegenüber aber aufgeschlossen, wenn es ne Alternative gibt, ok. (*)

    (*) Als Beispiel möchte ich nennen, das mir jemand beim Verändern der Konsole den Tip gab, Funktionen mit resize() und move() ) zu benennen. Dadurch wurde der weitere Code enorm erleichtert!



  • Über Benennungen kann man sich vorzüglich streiten, ich würde aber empfehlen Klassennamen so zu wählen, dass daraus, im entsprechenden Kontext, eindeutig ersichtlich wird, was die Klasse macht. Und da finde ich "Tools" ziemlich nichtssagend. In deinem Fall vlt. sowas wie "ConsolePainter".

    Edit: Tools wäre meiner Meinung nach evt. ein gutes Basisklassennamen für verschiedene Werkzeuge um z.B. die Konsole zu manipulieren.



  • Allerdings kann man sich das auch in einem fertigen Programm vorstellen. Es gibt eine Klasse Tools, um Aufgaben zu bewältigen. Bei Bedarf kann man dann noch ein Objekt spray, fill etc einfügen.

    Ist aber nur ein temporärer Name, bis sich der Kontext wieder ändert.

    Nene, class Comnsole ist ne eigene Klasse, die einfach da ist. Da gibt es außer Werte holen edit: und moving und so, von anderen nichts mehr zu machen. Außer der Parameter soll nichts auf die Grundlage console hinweisen.

    Hoffe ich jedenfalls 😉



  • Verdammt, über Klassennamen nachzudenken ist ja schon fast psychologische Grundlagenforschung



  • Ich komm hier nicht weiter. Mein erster Versuch ist etwas lächerlich, weil ich keine Ahnung habe, habe ich dies so zusammengeschustert.
    Ich kann zwar zwei Objekte erstellen, aber schon verschiedene Chars für diese muss ich so hausbacken einlesen.

    #pragma once
    
    #include "console.h"
    #include <map>
    
    class immernochKeinPlanfürName
    {
    
    public:
    
        const Console& console;
        std::map <std::string, std::vector <CHAR_INFO>> ch_draw, ch_paint;
    
        Tools( Console& console ) : console ( console )
        {
            getDefaultCoords();
            getDefaultChars();
        }
    
        unsigned int getXWidth() const { return used.width; }
        unsigned int getYHeight() const { return used.height; }
        int getCenterX() const { return used.center_x; }
        int getCenterY() const { return used.center_y; }
    
        unsigned int getDimXWidth() const { return dim.width; }
        unsigned int getDimYHeight() const { return dim.height; }
        int getDimCenterX() const { return dim.center_x; }
        int getDimCenterY() const { return dim.center_y; }
    
        unsigned int getCoordXWidth() const { return coord.width; }
        unsigned int getCoordYHeight() const { return coord.height; }
        int getCoordCenterX() const { return coord.center_x; }
        int getCoordCenterY() const { return coord.center_y; }
    
        void resizeCoords( unsigned int,
                           unsigned int );
        void resetCoords();
        void resizeCenter( int, int );
        void resizeCenterToConsole();
        void resetCenter();
    
        void addDrawChars( std::string,
                           const std::vector <WCHAR>&,
                           const std::vector <WORD>& );
        void addPaintChars( std::string,
                            const std::vector <WCHAR>&,
                            const std::vector <WORD>& );
    
    private:
    
         struct Coord
        {
            unsigned int width = 0;
            unsigned int height = 0;
            int center_x = 0;
            int center_y = 0;
            bool b = false;
        };
    
        Coord dim, coord, used;
    
        std::string draw_default_name = "default";
        std::vector <WCHAR> draw_uni = { '*', '@', 219 };
        std::vector <WORD> draw_attr = { 0, 15, 7, 8, 4, 12, 6, 14, 10, 11, 3, 9, 1, 13, 5 };
        std::string paint_default_name = "default";
        std::vector <WCHAR> paint_uni = { 179, 176, 178, 219 };
        std::vector <WORD> paint_attr = { 0, 15, 7, 8, 4, 12, 6, 14, 10, 11, 3, 9, 1, 13, 5 };
    
        void getDefaultCoords()
        {
            getConsoleCoords();
        };
    
        void getDefaultChars()
        {
            addDrawChars( draw_default_name, draw_uni, draw_attr );
            addPaintChars( paint_default_name, paint_uni, paint_attr );
        };
    
        void getConsoleCoords();
        unsigned int toUInt( double );
        int toInt( double );
    };
    
    ////////////////////////////////////////////////////////////////////////////////////////
    

    Da ich keine Idee habe, wo ich was nachschlagen muss, habe ich mal bei Vererbung geschaut.

    #pragma once
    
    #include "console.h"
    
    class Tools
    {
    
    public:
    
        const Console& console;
    
        Tools( Console& console ) : console ( console )
        {
            getDefaultCoords();
        }
    
        unsigned int getXWidth() const { return used.width; }
        unsigned int getYHeight() const { return used.height; }
        int getCenterX() const { return used.center_x; }
        int getCenterY() const { return used.center_y; }
    
        unsigned int getDimXWidth() const { return dim.width; }
        unsigned int getDimYHeight() const { return dim.height; }
        int getDimCenterX() const { return dim.center_x; }
        int getDimCenterY() const { return dim.center_y; }
    
        unsigned int getCoordXWidth() const { return coord.width; }
        unsigned int getCoordYHeight() const { return coord.height; }
        int getCoordCenterX() const { return coord.center_x; }
        int getCoordCenterY() const { return coord.center_y; }
    
        void resizeCoords( unsigned int,
                           unsigned int );
        void resetCoords();
        void resizeCenter( int, int );
        void resizeCenterToConsole();
        void resetCenter();
    
    private:
    
         struct Coord
        {
            unsigned int width = 0;
            unsigned int height = 0;
            int center_x = 0;
            int center_y = 0;
            bool b = false;
        };
    
        Coord dim, coord, used;
    
        void getDefaultCoords()
        {
            getConsoleCoords();
        };
    
        void getConsoleCoords();
        unsigned int toUInt( double );
        int toInt( double );
    };
    
    ////////////////////////////////////////////////////////////////////////////////////////
    
    #pragma once
    
    #include "tools.h"
    #include <map>
    
    class Draw : public Tools
    {
    
    public:
    
        //const Console& console;
        std::map <std::string, std::vector <CHAR_INFO>> ch_draw, ch_paint;
    
        Draw()
        {
            getDefaultChars();
        }
    
        void addDrawChars( std::string,
                           const std::vector <WCHAR>&,
                           const std::vector <WORD>& );
        void addPaintChars( std::string,
                            const std::vector <WCHAR>&,
                            const std::vector <WORD>& );
    
    private:
    
        std::string draw_default_name = "default";
        std::vector <WCHAR> draw_uni = { '*', '@', 219 };
        std::vector <WORD> draw_attr = { 0, 15, 7, 8, 4, 12, 6, 14, 10, 11, 3, 9, 1, 13, 5 };
        std::string paint_default_name = "default";
        std::vector <WCHAR> paint_uni = { 179, 176, 178, 219 };
        std::vector <WORD> paint_attr = { 0, 15, 7, 8, 4, 12, 6, 14, 10, 11, 3, 9, 1, 13, 5 };
    
        void getDefaultChars()
        {
            addDrawChars( draw_default_name, draw_uni, draw_attr );
            addPaintChars( paint_default_name, paint_uni, paint_attr );
        };
    
    };
    
    ////////////////////////////////////////////////////////////////////////////////////////
    

    Dort wird in Zeile 6 angemängelt

    draw.h|6|error: expected unqualified-id before 'class'|
    draw.h|6|error: expected constructor, destructor, or type conversion before 'class'|
    ||=== Build failed: 2 error(s), 0 warning(s) (0 minute(s), 1 second(s)) ===|
    

    Ich weiß nicht, was dort erwartet wird.



  • Hm, ein paar Dinge, ohne zu überprüfen ob das deine Fehlermeldung löst.

    In
    class immernochKeinPlanfürName hast du folgendes:

    Tools( Console& console ) : console ( console )
        {
            getDefaultCoords();
            getDefaultChars();
        }
    

    Wahrscheinlich soll das heißen:

    immernochKeinPlanfürName ( Console& console ) : console ( console )
        {
            getDefaultCoords();
            getDefaultChars();
        }
    

    In Tools hast du einen Konstruktor definiert. Du verstößt aber gegen die Rule of 5.
    Das führt auch zu einem Problem in Draw. Aus dem Draw Konstruktor wird der Basisklassen Konstruktor aufgerufen. Nur welchen soll er nehmen. Du hast einen eigenen definiert, daher wird kein default Konstruktor erstellt. Und den erstellten Kontsruktor kann er nicht aufrufen, weil der ein Parameter erwartet.

    Außerdem solltest du bei polymorphen Klassen, einen virtuellen Destruktor definieren. Je nach Nutzung kann das sonst später zu undefiniertem Verhalten führen.



  • schlangenmensch schrieb:

    In Tools hast du einen Konstruktor definiert. Du verstößt aber gegen die Rule of 5.

    Was willst du damit sagen? Meinst du man kann keinen eigenen Konstruktor definieren, ohne die anderen Operatoren und Methoden der Rule of 5 zu definieren.
    Die Rule of 3 (bzw. 5) bezieht sich nur auf den Kopierkonstruktor.



  • Argh... wo zum Teufel habe ich nur mein Kopf. Sicher, erfolgreiche Umsetzung der Rule of 0....

    Wodrauf ich eigentlich hinaus wollte ist, dass der Default Konstrukor nicht automatisch erzeugt wird, wenn er einen eigenen Konstruktor definiert.

    Und der würde hier aber für Draw::Draw() benötigt.



  • Ja, da gebe ich dir recht. Trotzdem wird hier keine Ableitung benötigt: eine Klasse (wie auch immer diese heißen mag) sowie zwei Instanzen 'Draw' und 'Paint' davon (bzw. 2 Funktionen, welche diese Instanzen erzeugen).

    Wobei ich immer noch nicht den Unterschied zwischen den beiden Namen verstanden habe. Warum braucht man zwei verschiedene "Dinge", um etwas auf der Konsole auszugeben/auszudrucken/zu zeichnen???



  • Der Klassenanme "immernoch kein Plan" steht natürlich nur hier, nicht im Code.

    Th69 schrieb:

    Wobei ich immer noch nicht den Unterschied zwischen den beiden Namen verstanden habe. Warum braucht man zwei verschiedene "Dinge", um etwas auf der Konsole auszugeben/auszudrucken/zu zeichnen???

    Dies ist meines Erachten leicht aufzuklären. In der Konsole sind die Zeichen ziemlich genau x * 2y groß. Dies muss berücksichtigt werden, wenn zB ein 50 x 50 Quadrat in der Konsole auch ein Quadrat sein soll. Beim 'zeichnen' muss man außer darauf nicht weiter achten. Beim 'malen' aber, damit die "Pixel" selbst auch quadratisch sind, jeden einzelne zweimal 'zeichnen'.

    Dazu soll sowohl 'zeichnen' und 'malen' eigene Skalierungsoptionen bekommen. Beispiel: Man hat einen Hintergrund, irgendein Muster 'gemalt', darüber wird ein anderes Muster 'gezeichnet'. Wenn ich letzteres jetzt einfach animieren (verschieben, vergrößern, skalieren, etc) will, würde auch das 'gemalte' Muster entsprechend animiert werden. Das will ich natürlich nicht.

    Ein kleines Beispiel:
    https://www.youtube.com/watch?v=BKNUR2wNsoA
    Dort wurden die Werte der Formen nicht verändert, nur die Skalierung von draw

    void Demo( Console& console,
               Tools& draw,
               Tools& paint,
               unsigned int console_size )
    {
        console.setTitle( "" );
        console.resize( console_size );
        draw.resetCoords();
        paint.resetCoords();
        paintModularColors( console, paint );
    
        unsigned int scale_size_min = 10;
        unsigned int scale_size_max = 75;
        draw.resizeCoords( scale_size_min, scale_size_min );
    
        int loops = 10, l = 0;
        while ( l < loops )
        {
            for ( unsigned int zs = scale_size_min; zs <= scale_size_max; zs += 5 )
            {
                Sleep( 10 );
                draw.resizeCoords( zs, zs );
                paintModularColors( console, paint );
                drawForms( console, draw, "default", 16 );
                console.writeBuffer();
            }
            for ( unsigned int zs = scale_size_max; zs >= scale_size_min; zs -= 5 )
            {
                Sleep ( 10 );
                draw.resizeCoords( zs, zs );
                paintModularColors( console, paint );
                drawForms( console, draw, "default", 16 );
                console.writeBuffer();
            }
            l ++;
        }
    
        std::cin.get();
        console.clearBuffer();
    }
    

    Hoffe, ich hatte Dich bei der Aufklärung richtig verstanden.



  • Schlangenmensch schrieb:

    Wodrauf ich eigentlich hinaus wollte ist, dass der Default Konstrukor nicht automatisch erzeugt wird, wenn er einen eigenen Konstruktor definiert.

    Und der würde hier aber für Draw::Draw() benötigt.

    Ja, das meine ich verstanden zu haben, darauf zielt ja auch die Fehlermeldung, das dort noch etwas in der Richtung erwartet wird. Ich weiß aber nicht, wie ich das ausschreiben muss.



  • Naja, deine Basisklasse braucht offensichtlich eine Console. Die wirst du irgendwie übergeben müssen. Zum Beispiel könnte dien Konstruktor so aussehen:

    Draw(Console& console):Tools(console)
    {
       getDefaultChars();
    }
    

Anmelden zum Antworten