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

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

11

14.07.2016, 17:02

Also ich wüsste nicht, wie man das, was er da oben zu machen versucht, in Python ohne Konstruktor hinbekommen sollte...

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

12

14.07.2016, 17:04

C-/C++-Quelltext

1
2
3
4
5
    Button()
    {
        this->typeTag = BUTTON;
    }
};

Das ist keine schöne Lösung. Koschi hatte ja schon gesagt, dass du das Attribut an den parent-class-Konstruktor übergeben solltest und dieser dann das Feld setzt. Am besten über Initializer-Listen. Das da ist jedenfalls ganz schlecht. Und noch schlechter ist, dass die Moderatoren belanglosen Mist diskutieren, statt auf den schlechten Code einzugehen. Völlig Off-Topic.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

13

14.07.2016, 17:08

Koschi hatte ja schon gesagt, dass du das Attribut an den parent-class-Konstruktor übergeben solltest und dieser dann das Feld setzt.

Richtig, Koschi hat das schon gesagt...

Das ist keine schöne Lösung.

In der Tat. Wenn wir über schöne Lösungen diskutieren wollen, dann müssen wir aber bereits bei der Frage ansetzen, wieso es überhaupt einen solchen Enum gibt. In einer "schönen" Lösung kommt ein solcher Enum nämlich definitiv nicht vor... ;)

MitgliedXYZ

Alter Hase

  • »MitgliedXYZ« ist der Autor dieses Themas

Beiträge: 1 369

Wohnort: Bayern

  • Private Nachricht senden

14

14.07.2016, 17:10

Wie soll das funktionieren, die Typen über den Parent Konstruktor zu setzen? Die Objekte können doch unterschiedliche Attribute haben, etc.

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
class UiControl
{
protected:
    UiControl()
    {
        //The constructor UiControl is private, only objects of subclasses can be created
    }

public:
    int x;
    int y;
    
    int width;
    int height;

    enum TypeTag { BUTTON, TEXT_FIELD };
    TypeTag typeTag;
};

class Button : public UiControl
{
public:
    string caption;

    ofColor backgroundColor;
    ofColor foregroundColor;

    Button(int x, int y, int width = 200, int height = 50, string caption = "")
    {
        this->x = x;
        this->y = y;
        this->width = width;
        this->height = height;
        this->caption = caption;

        this->backgroundColor = lightBlue;
        this->foregroundColor = grey;

        this->typeTag = BUTTON;
    }
};


Die Klasse des Objekts mit einem Enum zu ermitteln ist nicht so schön, aber RTTI Funktionen wollte ich dafür nicht verwenden. Oder ist das doch besser?
Auf Stackoverflow habe ich dazu diesen Thread gelesen.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

15

14.07.2016, 17:16

Du hast nicht mal im Internet gesucht, wie man super-Konstruktoren und Initializer-Listen benutzt, oder?

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class UiControl
{
protected:
    UiControl(TypeTag tag)
        : typeTag(tag)
    { }

public:
...
    enum TypeTag { BUTTON, TEXT_FIELD };

private:
    TypeTag typeTag;
};

class Button : public UiControl
{
    string caption;
public:
    ...
    Button(int x, int y, int width = 200, int height = 50, string caption = "")
        : UIControl(BUTTON), caption(caption)
    {
    }
};

Uncool bleibt dann trotzdem noch, dass die Parent-Class indirekt eigentlich schon wissen muss, was es jemals für Child-Klassen überhaupt geben kann (weil sie ja das Enum definiert). Nicht schön.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

MitgliedXYZ

Alter Hase

  • »MitgliedXYZ« ist der Autor dieses Themas

Beiträge: 1 369

Wohnort: Bayern

  • Private Nachricht senden

16

14.07.2016, 17:18

Deine Antwort hat sich wohl mit meinem bearbeiteten Beitrag überschnitten.

Also ich habe mich an der dritten Stackoverflow Antwort orientiert. Das war zwar die einfachste Möglichkeit, allerdings eben nicht schön. Die RTTI Umsetzung ist dann doch besser?

Edit: Du hast deinen Beitrag während ich diesen geschrieben habe editiert.

Die Initializer-Listen kenne ich aus der C++ Vorlesung, die sind mir nur irgendwie unleserlicher vorgekommen. Ist der von dir verbesserte Code in dem Fall wirklich besser? Ich erkenne da die Vorteile nicht

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

17

14.07.2016, 17:31

Die RTTI Umsetzung ist dann doch besser?

Besser wäre die Lösung, die ohne Type Lookup auskommt. Für was genau brauchst du diesen Enum? Wenn du Code hast, der nur ein UIControl bekommt und dann rausfinden muss, ob es sich um einen Button handelt, dann hast du ganz weit oben irgendwo einen Designfehler. Code, der jedes UIControl annimmt, muss mit jedem UIControl umgehen können, unabhängig davon, um was für eine Art UIControl es sich konkret handelt. Code, der nur mit Buttons funktioniert, sollte von vorn herein nur einen Button annehmen. Wenn du Code hast, der jedes UIControl annimmt und dann unterscheiden muss, ob es sich um einen Button handelt oder nicht, dann zeigt das auf, dass dein Design in sich selbst widersprüchlich ist (entweder ist das Interface von UIControl unpassend oder das Interface das das UIControl annimmt). Die gute Lösung ist nicht, mit RTTI (in welcher Form auch immer) die Symptome zu verschleiern, sondern den Widerspruch zu beseitigen...

Die Initializer-Listen kenne ich aus der C++ Vorlesung, die sind mir nur irgendwie unleserlicher vorgekommen.

Das kommt dir dann wohl nur so vor weil du C++ nicht gewohnt bist. Im Gegensatz zur Zuweisung im C'tor Body (bei der der Member erst default-initialized wird und dann einen neuen Wert bekommt), wird in der Initializer Liste direkt initialisiert. Beachte: Zwischen Initialisierung und Zuweisung besteht ein wesentlicher Unterschied! Es gibt Dinge wie z.B. Konstanten oder Referenzen, die nur durch eine Initialisierung einen Wert bekommen/gebunden werden können... ;)

Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von »dot« (14.07.2016, 17:44)


MitgliedXYZ

Alter Hase

  • »MitgliedXYZ« ist der Autor dieses Themas

Beiträge: 1 369

Wohnort: Bayern

  • Private Nachricht senden

18

14.07.2016, 17:48

Das Program sollte unabhängig vom UiControl des Element zeichnen können. Habe noch mal drüber nachgedacht und es war ein Designfehler, eine Methode alle UiControls zeichnen zu lassen, die für jedes Objekt die Subclass überprüft. Es ist besser wenn jedes Control eine Methode von UiControl überschreibt, die den Code zum zeichnen enthält.

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

19

14.07.2016, 17:49

Es ist besser wenn jedes Control eine Methode von UiControl überschreibt, die den Code zum zeichnen enthält.

Bingo!

MitgliedXYZ

Alter Hase

  • »MitgliedXYZ« ist der Autor dieses Themas

Beiträge: 1 369

Wohnort: Bayern

  • Private Nachricht senden

20

14.07.2016, 18:04

Also, alle Controls werden dieser Liste hinzugefügt

C-/C++-Quelltext

1
2
3
4
5
std::list<UiControl> uiControls;
Button button(10, 10);
button.caption = "Text";

uiControls.insert(uiControls.begin(), button);


Und dann so gezeichnet

C-/C++-Quelltext

1
2
3
4
for (UiControl uiControl : uiControls)
{
    uiControl.draw();
}


Allerdings wird die draw() Methode der Klasse UiControl und nicht von der abgeleiteten Klasse Button verwenden. Wie kann das geändert werden?

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
class UiControl
{
protected:
    UiControl()
    {
        //The constructor UiControl is private, only objects of subclasses can be created
    }

public:
    int x;
    int y;
    
    int width;
    int height;

    enum TypeTag { BUTTON, TEXT_FIELD };
    TypeTag typeTag;

    void draw()
    {
        
    }
};

class Button : public UiControl
{
public:
    string caption;

    ofColor backgroundColor;
    ofColor foregroundColor;

    MaterialButton(int x, int y, int width = 200, int height = 50, string caption = "")
    {
        this->x = x;
        this->y = y;
        this->width = width;
        this->height = height;
        this->caption = caption;

        this->backgroundColor = LightBlue;
        this->foregroundColor = Grey;

        this->typeTag = BUTTON;
    }

    void draw()
    {
        //Code zum zeichnen
    }
};

Werbeanzeige