Aggregation vermeiden



  • Hallo,

    ich habe ein Problem mit meiner neusten Klasse. Diese sieht in etwa so aus:

    struct Test
    {
    	int a = 1, b = 2, c = 3;
    
    	int get_a_variant1() { return a + 1; } // Verschiedene "Varianten" von a
    	int get_a_variant2() { return a + 3; }
    	int get_a_variant3() { return a + 7; }
    
    	int get_b_variant1() { return b + 1; } // Verschiedene "Varianten" von b
    	int get_b_variant2() { return b + 3; }
    	int get_b_variant3() { return b + 7; }
    
    	int get_c_variant1() { return c + 1; } // Verschiedene "Varianten" von c
    	int get_c_variant2() { return c + 3; }
    	int get_c_variant3() { return c + 7; }
    };
    

    Wie sieht gibt es jede Membervariable in bestimmten "Varianten". Ich kann zwar für jede Kombination wie oben eine eigene Funktion schreiben, das ist aber sehr viel Redundanz und unübersichtlich.
    Bei n Membervariablen und m Varianten wären dass dann n*m Memberfunktionen was sehr viel werden kann.

    Meine Idee deswegen:

    struct variant
    {
    	int &val_ref;
    	variant(int &val_ref) : val_ref(val_ref) {}
    
    	int get_variant1() { return val_ref + 1; }
    	int get_variant2() { return val_ref + 3; }
    	int get_variant3() { return val_ref + 7; }
    };
    
    struct Test
    {
    	int a = 1, b = 2, c = 3;
    	variant get_a() { return variant(a); }
    	variant get_b() { return variant(b); }
    	variant get_c() { return variant(c); }
    };
    
    int main()
    {
    	Test test;
    	int test_a_1 = test.get_a().get_variant1();
    	int test_b_3 = test.get_b().get_variant3();
    }
    

    Vorteil: Bei n Membervariablen habe ich nur n Getter, also so wie ich das haben will. Übersichtlich ist es auch.

    Nachteil: Ich mag solche Konstrukte eigentlich nicht weil man dann immer mitdenken muss ob jetzt das besitzende Objekt noch lebt damit man keine ungültigen Referenzen rumhängen hat.

    Deswegen Frage: Kann ich das Ganze irgendwie mit n Gettern für n Membervariablen realisieren ohne eine Aggregation nutzen zu müssen?



  • Du beschreibst deine Intention hier schon auf einer zu abstrakten Ebene.
    Dein Code schließt für mich auf eine verkrampfte Verwendung von Klassen/ Strukturen.
    Jede Memberfunktion manipuliert einen Datenmember, den du danach mit einem getter ausliest. Es gleicht dem Prinzip eines Funktionsaufrufs... .
    In diesem Sinne können Templatefunktionen und, allgemeiner, funktionale Programmiertechniken eine gute Alternative sein.



  • neyize schrieb:

    Du beschreibst deine Intention hier schon auf einer zu abstrakten Ebene.
    Dein Code schließt für mich auf eine verkrampfte Verwendung von Klassen/ Strukturen.
    Jede Memberfunktion manipuliert einen Datenmember, den du danach mit einem getter ausliest. Es gleicht dem Prinzip eines Funktionsaufrufs... .
    In diesem Sinne können Templatefunktionen und, allgemeiner, funktionale Programmiertechniken eine gute Alternative sein.

    Also dass hier eine Klasse/Struct verwendet wird macht schon Sinn, das Ding macht in Wirklichkeit noch mehr als nur ein paar Getter für einige Werte bereitzustellen.

    Aber wahrscheinlichwar das Beispiel ungünstig gewählt... Mein Problem (warum ich das auch nicht als freie Funktion implmentiert habe) ist dass jede Variante von mehreren Membern abhängt:

    struct Test
    {
        int a = 1, b = 2;
        int x = 2;
    
        int get_a_variant_1() { return a + x; } // Eine Möglichkeit
    };
    

    Wenn ich jetzt eine freie Funktion schreiben würde sähe die ja z.B. so aus:

    int variant_1(int a, int x) { return a + x; }
    
    int main()
    {
        Test test;
        int a_var1 = variant_1(test.a, test.x);
    }
    

    Problem ist dass man dabei alle Member auflisten ist und vor allem dass man Werte mischen kann. Die Berechnung einer Variante macht nur Sinn wenn alle Werte vom selben Objekt kommen. Sowas:

    int a_var1 = variant_1(test_1.a, test_2.x); // zwei verschiedene Objekte!
    

    sollte am besten gar nicht erst möglich sein da es Unsinn ist.

    Übergibt man aber nur das Objekt, weiß man in der Funktion nicht welche Membervariable der Nutzer jetzt haben will:

    int a_var1 = variant_1(test); // Variante von a oder b?
    

Anmelden zum Antworten