Schnittstelle oder wie?



  • Moin Moin! 🕶

    int _tmain(int argc, _TCHAR* argv[]) //Argument wird übergeben (0, sonst)
    	....
    	if(argv[1]==0){
    		CKlasseFall_Null A;	//A lokal angelegt
    	}
    	else{
    		CKlasseFall_Sonst A;	//A lokal angelegt
    	}
    
    	A.Funktion();	//Problem: A ist hier unbekannt
    
    	return 0;
    }
    

    Der Code zeigt schon mein Problem. Ich hab zwei mögliche Fälle (0, sonst) und will davon abhängig ein Objekt der einen oder anderen Klasse anlegen, daher die if-Abfrage. Leider ist die Klasse lokal angelegt und damit außerhalb des if-Blockes unbekannt. Wie löst man denn so ein Problem in C++?

    Vielen Dank 😕



  • Stichwort: Abstrakte Klasse



  • btw:
    if(argv[1]==0){
    du prüfst aber vorher schon, ob argc > 1 bzw >= 2 ist?!

    bb



  • unskilled schrieb:

    btw:
    if(argv[1]==0){
    du prüfst aber vorher schon, ob argc > 1 bzw >= 2 ist?!

    bb

    In meinen Augen beinhaltet sonst alles ausser 0 also passt das doch??



  • Ich hoffe mal, ich verstehe deinen unvollständigen Satz richtig.

    Wenn argc == 1 ist, dann ist ein Zugriff auf argv[1] undefiniertes Verhalten. Da kann alles Mögliche stehen, auch 0.



  • Das Programm darf genauso gut in einem Absturz enden oder irgendein merkwürdiges Verhalten aufweisen. Von daher ist das Zugreifen über Array-Grenzen hinweg nie gut.



  • Firefighter schrieb:

    Stichwort: Abstrakte Klasse

    Wenn sich das Verhalten von CKlasse_ aendert bei unterschiedlichen argumenten vielleicht noch auch soetwas:

    int main (int argc, char **argv)
    {
        CKlasse *pCKlasse;
    
        pCKlasse = new CKlasse (argc, argv);
    
        pCKlasse->MachWas ();
    
        // ...
    
        delete pCKlasse;
    }
    

    Wobei im ueberlagerten new-Operator die Klasse entsprechend initalisiert wird.



  • Wobei im ueberlagerten new-Operator die Klasse entsprechend initalisiert wird.

    Ehm, Du meinst wohl Konstruktor, nicht new Operator.
    Simon



  • theta schrieb:

    Wobei im ueberlagerten new-Operator die Klasse entsprechend initalisiert wird.

    Ehm, Du meinst wohl Konstruktor, nicht new Operator.

    Ja - Idiot (recursive).



  • Abstrakte Klassen klingt eigentlich ganz gut, aber das Problem bleibt trotzdem bestehen. Objekt A ist nur lokal innerhalb des if-Blockes bekannt.

    Ich hab das Problem gelöst indem ich die Methoden von A auch innerhalb des if-Blockes aufrufe. Allerdings hab ich da Code mehrfach drin und das sollte ja vermieden werden.

    int _tmain(int argc, _TCHAR* argv[]) //Argument wird übergeben (0, sonst) 
        //....
        if(Fall A){ 
            CKlasseFall_A A;
            A.getSize();
            A.read();
            A.print();
            //...
        } 
        else{ //Fall B
            CKlasseFall_B A;
            A.getSize();
            A.read();
            A.print();
            //...
        } 
    
        return 0; 
    }
    

    😕



  • Nee du hast das system von Abstrakten Klassen nicht verstanden.

    class Basis
    {
      public:
       virtual void getSize()=0;
    }
    
    class KlasseA : public Basis
    {
       void getSize()
       {
          //berechne sachen für A
    
        }
    }
    
    class KlasseB : public Basis
    {
       void getSize()
       {
          //berechne sachen für B
    
        }
    }
    

    Main.cpp

    int main(/*irgendwas*/)
    {
      Basis *zeiger;
    
      if(/*irgendwas*/)
         zeiger = new KlasseA()
      else if(*/irgendwas*/)
         zeiger = new KlasseB()
    
      //und der Aufruf
        zeiger->getSize();
      //hier wird nun jenachdem welche Klasse erzeugt wurde, die funktion für diese Klasse aufgerufen
     //informier dich mal bisschen über Polymorphismus
    
    delete zeiger;
    }
    

    edit:delete zeiger ergänzt.



  • Abstrakte Klassen klingt eigentlich ganz gut, aber das Problem bleibt trotzdem bestehen. Objekt A ist nur lokal innerhalb des if-Blockes bekannt.

    klingen gut... obwohl du nicht weist, was es ist!? Oo

    int main (int argc, char **argv)
    {
        Tclass *A;
        if (argc >= 2)
           A = new Tclass_fall_a(argv[1]);
        else
           A = new Tclass_null();
    
        A->do_something();
    
        delete A;
    }
    

    alternativ würde (je nach gegebenheiten) auch folgendes gehen:

    int main (int argc, char **argv)
    {
        Tclass A;
        if (argc >= 2)
           A = Tclass_fall_a(argv[1]);
        else
           A = Tclass_null();
    
        A.do_something();
    }
    

    bb



  • "Heureka, es funktioniert!!" (um mal Volkard zu zitieren..)

    Dank Firefighter's Ausführungen habe auch ich als noob es hinbekommen.. 😃

    War ja gar nicht so schwer. Vielen Dank an alle für die Hilfe!! 👍

    klingen gut... obwohl du nicht weist, was es ist!? Oo

    Ja. Nach dem Stichwort von Firefighter hab ich im Buch darüber gelesen und das schien zu passen. Abstrakte Klassen als Interface. Aber lesen und dann richtig anwenden, das ist mir alleine nicht gelungen.



  • Übrigens gehen in dem Fall auch Templates:

    template <typename FallKlasseT>
    void BehandleFall()
    {
        FallKlasseT obj;
        obj.getSize();
        obj.read();
        obj.print();
    }
    
    int main()
    {
        //...
        if (FallA)
            BehandleFall<FallKlasseA>();
        else
            BehandleFall<FallKlasseB>();
    }
    
    }
    

    Das ganze ist aber nicht so dynamisch wie die Lösung mit den abstrakten Klassen (statische vs. dynamische Polymorphie). Dafür kannst du jede Klasse mit entsprechendem Interface benutzen ohne von einer gemeinsamen Basisklasse abzuleiten und virtuellen Methoden zu überschreiben.

    Gruß
    Don06



  • Don06 schrieb:

    Übrigens gehen in dem Fall auch Templates:

    template <typename FallKlasseT>
    void BehandleFall()
    {
        FallKlasseT obj;
        obj.getSize();
        obj.read();
        obj.print();
    }
    
    int main()
    {
        //...
        if (FallA)
            BehandleFall<FallKlasseA>();
        else
            BehandleFall<FallKlasseB>();
    }
    
    }
    

    Das ganze ist aber nicht so dynamisch wie die Lösung mit den abstrakten Klassen (statische vs. dynamische Polymorphie). Dafür kannst du jede Klasse mit entsprechendem Interface benutzen ohne von einer gemeinsamen Basisklasse abzuleiten und virtuellen Methoden zu überschreiben.

    Gruß
    Don06

    Nur blöd wenn ich da einen nativen Datentyp übergebe 😃



  • Firefighter schrieb:

    Nur blöd wenn ich da einen nativen Datentyp übergebe 😃

    Was meinst du? Ein nativer Typ kann auch nicht von einer abtrakten Basisklasse erben. Natürlich könnte man noch durch eine weitere Abstraktionsebene (z.B. Traits, Concept Maps) eingebaute Typen erlauben. Allerdings glaube ich, dass das hier nicht nötig ist.



  • Don06 schrieb:

    Firefighter schrieb:

    Nur blöd wenn ich da einen nativen Datentyp übergebe 😃

    Was meinst du? Ein nativer Typ kann auch nicht von einer abtrakten Basisklasse erben. Natürlich könnte man noch durch eine weitere Abstraktionsebene (z.B. Traits, Concept Maps) eingebaute Typen erlauben. Allerdings glaube ich, dass das hier nicht nötig ist.

    er redet von PODs, wie int/float/...
    aber das is ja normal, dass man templates _immer_ mit falschen typen füttern kann - also nix besonderes...

    bb


Log in to reply