Auf Protected Funktionen zugreifen



  • Hey zusammen,

    ich möchte auf ein Protected Funktion zugreifen. Das ich Zugriff innerhalb einer Funktion auf eine Protected Funktion hab ist mir klar aber ich frag mich ob ich auch noch anderweitig da zugreifen kann (Grund siehe später).
    Hier ein kleines Beispiel:

    #include <iostream>
    
    using namespace std;
    
    class Base
    {
    public:
        Base() { cout << "Base Konstruktor\n"; }
        ~Base() { cout << "Base Dekonstruktor\n"; }
    
    public:
    
        void show() { cout << "Show() from Base\n"; }
        void access() { show_protect(); }
    
    protected:
        void show_protect() { cout << "Show() protected\n"; }
    
    };
    
    int main()
    {
        cout << "Test";
    
        Base foo;
        foo.show();
        foo.access();
    
        //foo.Base::show_protect
    
        return 0;
    }
    

    Die Frage:
    Ist es möglich auf diese Protected Funktion auch anderweitig mit dem Object foo zuzugreifen? Nach meinem Ermessen nicht, da ich sonst die Funktion ja direkt auf public setzen kann, oder?

    Grüße
    Tobi


  • Mod

    (Grund siehe später)

    So? Was ist ist der Grund?

    Du kannst halt einfach eine eigene Klasse von Base erben lassen und lustig mit den protected-Membern rumspielen, wie es dir passt. Daher sieht man protected auch eher selten, da es effektiv darauf hinaus läuft, als sei es das gleiche wie public.

    Eine Ausnahme wäre vielleicht ein Teil einer eigenen Klassenhierarchie, welches ein Anwender niemals zu Gesicht bekommt. Da könnte man protected einsetzen, wenn man es braucht. Aber mit dem gleichen Argument, könnte man da dann auch alles public machen 😕



  • Hallo Sepp,

    oh da hab ich wohl noch was vergessen.
    Ich programmiere mit OpenFOAM und das hat eben verschiedene Klassen für IO.
    Zum Auslesen einer Datei hab ich mir ein IFsteam Objekt erzeugt und lese das aus (funktioniert alles wunderbar) nur muss ich nochmals eine Schleife durch diese Datei machen.

    Das Problem das ich gerade habe ist dann, dass ich zwar die Position des Zeigers wieder auf 0 setzen kann, jedoch das Bit für den Status von Bad zu Good setzen muss. Wenn ich jedoch die Funktion aufrufe, dann erhalte ich den Fehler das diese Funktion "protected" ist.

    Doxygen kann man hier nachsehen: http://www.openfoam.org/docs/cpp/

    -> Suchen nach IFstream

    Man kann dann folgende Hierarchie feststellen:

    IFstream -> ISstream -> Istream -> IOstream

    Wobei IOstream die Basisklasse ist und eine protected Funktion (setGood()) bereitstellt, die ich ja doch mit meinem Objekt (IFstream) aufrufen könnte.

    Kurzbeispiel was ich habe:

    IFstream foo("Path");
    
    string line;
    
    while(!foo.eof())
    {
        is.getLine(line);
        Info<< "While loop 1: << line << "\n";
    }
    
    foo.setGood(); // Problem
    foo.rewind;
    
    while(!foo.eof())
    {
        is.getLine(line);
        Info<< "While loop 2: << line << "\n";
    }
    

    Die Ausgabe beschränkt sich ohne "foo.setGood()" auf eine einmalige Ausführung, da im zweiten Durchlauf das Bad Bit gesetzt ist.

    Grüße Tobi

    PS: Kompilierfehler ist folgender:

    /home/shorty/OpenFOAM/OpenFOAM-2.3.1/src/OpenFOAM/lnInclude/IOstream.H:262:18: error: 'void Foam::IOstream::setGood()' is protected
                 void setGood()
                      ^
    PDF_Extraction.C:102:16: error: within this context
         is.setGood();
                    ^
    


  • Nochmals ein Beispiel das genau dem von oben entspricht:

    #include <iostream>
    
    using namespace std;
    
    class Base
    {
    public:
        Base() { cout << "Base Konstruktor\n"; }
        ~Base() { cout << "Base Dekonstruktor\n"; }
    
    public:
    
        void show() { cout << "Show() from Base\n"; }
    
    protected:
        void show_protect() { cout << "Show() protected\n"; }
    
    };
    
    class Derivate : public Base
    {
    public:
        Derivate() { cout << "Derivate Konstruktor\n"; }
        ~Derivate() { cout << "Derivate Dekonstruktor\n"; }
    };
    
    int main()
    {
        cout << "Test";
    
        Derivate foo;
        foo.show();
        foo.show_protect();
    
        return 0;
    }
    

    Ich möchte jetzt auf die Protected Funktion mit foo zugreifen.
    Hmmm vllt steh ich auch einfach auf m Schlauch grad.


  • Mod

    Wenn du meinst, die Klassenhierarchie deiner Bibliothek hacken zu müssen, dann stimmt entweder was mit der Bibliothek nicht oder du hast nicht verstanden, wie sie richtig zu benutzen ist. Was hier der Fall ist, kann ich nicht beurteilen, ohne die riesig lange Doku zu lesen. Erfahrungsgemäß würde ich davon ausgehen, dass die Entwickler von großen Bibliotheken meistens recht gut wissen, was sie tun.



  • Hey,
    ich will das doch nicht Hacken 🙂 hab auch andere Möglichkeiten, zb. diese Datei wieder zu schließen und neu zu öffnen. Aber ich dachte, dass das etwas umständlich ist und es mit den eingebauten Funktionen schon passt.

    Nur kurz eine Frage bezüglich meinem Beispiel.
    Kann Derivate nicht die protected Funktion von Base aufrufen? Denn wenn ich deine Aussage richtig auffasse

    Du kannst halt einfach eine eigene Klasse von Base erben lassen und lustig mit den protected-Membern rumspielen, wie es dir passt. Daher sieht man protected auch eher selten, da es effektiv darauf hinaus läuft, als sei es das gleiche wie public.

    sollte ich mit der abgeleiteten Klasse doch auf die protected Member zugreifen können.

    Danke nochmals für die Antwort.


  • Mod

    Shor-ty schrieb:

    sollte ich mit der abgeleiteten Klasse doch auf die protected Member zugreifen können.

    Ja, das ist möglich. Das ist der Sinn von protected.



  • 🙂 Danke dann hab ichs ja doch richtig verstanden.

    Dann frag ich mich aber wieso mein Beispiel (drei Posts bevor) nicht kompiliert werden kann?


  • Mod

    Shor-ty schrieb:

    🙂 Danke dann hab ichs ja doch richtig verstanden.

    Dann frag ich mich aber wieso mein Beispiel (drei Posts bevor) nicht kompiliert werden kann?

    Dieses?

    IFstream foo("Path");
     
    string line;
     
    while(!foo.eof())
    {
        is.getLine(line);
        Info<< "While loop 1: << line << "\n";
    }
     
    foo.setGood(); // Problem
    foo.rewind;
     
    while(!foo.eof())
    {
        is.getLine(line);
        Info<< "While loop 2: << line << "\n";
    }
    

    Bloß weil meine Kinder daheim an meinen geschützten Teilen rumspielen dürfen, darf das noch lange nicht jeder Fremde, der meine Kinder irgendwie kennt. Er kann sie aber fragen, ob sie nicht in seinem Namen daheim an meinen geschützten Teilen rumspielen wollen.

    (Nach dieser Analogie erwarte ich, dass mir gleich ein Sondereinsatzkommando die Bude stürmt 😃 )



  • Hi,

    möglicherweise kommt die KSK zu dir 🙂

    Nein das Beispiel meinte ich nicht. Ich meinte das hier:

    #include <iostream>
    
    using namespace std;
    
    class Base
    {
    public:
        Base() { cout << "Base Konstruktor\n"; }
        ~Base() { cout << "Base Dekonstruktor\n"; }
    
    public:
    
        void show() { cout << "Show() from Base\n"; }
    
    protected:
        void show_protect() { cout << "Show() protected\n"; }
    
    };
    
    class Derivate : public Base
    {
    public:
        Derivate() { cout << "Derivate Konstruktor\n"; }
        ~Derivate() { cout << "Derivate Dekonstruktor\n"; }
    };
    
    int main()
    {
        Derivate foo;
        foo.show();
        foo.show_protect();
    
        return 0;
    }
    

    Da Derivate von Base abgeleitet ist und die Funktion "show_protect()" als protected deklariert wurde, sollte ich doch mit dem Objekt der Klasse Derivate darauf zu greifen können.



  • Nee, dieses (ist näher an 3) 😉
    Änderungen scon eingebaut:

    #include <iostream>
    
    using namespace std;
    
    class Base
    {
    
    protected:
        void show_protect() { cout << "Show() protected\n"; }
    
    };
    
    class Derivate : public Base
    {
    public:
        void show_protect() { Base::showProtect();}
    };
    
    int main()
    {
        cout << "Test";
    
        Derivate foo;
        foo.show();
        foo.show_protect();
    
        return 0;
    }
    

    Du kannst nur innerhalb der abgeleiteten Klasse auf die protected member zugreifen.



  • Hey,

    jetzt hats klick gemacht 🙂
    Danke dir. D.h. ich brauch ne Funktion innerhalb der abgeleiteten Klasse, die mir quasi die protected Funktion aufruft.

    Dann mach ich mich gleich mal auf die Suche 🙂
    Nochmals Danke und ich hoffe das kein Sonderkommando zu dir nach Hause kommt 😉


  • Mod

    Ja, du kannst aus Memberfunktionen von Derivate auf die protected-Member von Base zugreifen. Die protected Member von Base werden dadurch aber keine public Member von Derivate. Für jeden, der nicht von Base oder Derivate erbt, verhalten sie sich so, als seien sie private.

    Es hält halt bloß niemand einen davon ab, eine eigene Klasse zu schreiben:

    class GetProtectedAccess : public Base
    {
    public:
      void access() { show_protect(); }
    };
    

    Wodurch sich im Endeffekt jeder Zugriff auf die protected-Member verschaffen kann, wenn er möchte.



  • @Jockelx

    class Base
    {
    protected:
        void show_protect() { ... }
    };
    
    class Derivate : public Base
    {
    public:
        //void show_protect() { Base::showProtect();}
        using Base::show_protect; // tut's auch
    };
    


  • Das stimmt, aber ich nehme an in diesem numerischen Bereich möchte niemand eine Klasse erstellen um auf Diskretisierungsmethoden zugreifen zu müssen.

    Ich habe eine Funktion gefunden, die mich auf die std::istream Funktionalitäten zugreifen lässt (wie dumm ich auch bin). Damit kann ich also

    is.std::istream.clear()
    

    aufrufen und mein Problem hat sich damit gelöst 🙂
    Danke aber nochmals für die Erklärung. Ist etwas in den Hintergrund gerutscht.

    SChönen Abend noch,
    Tobi


  • Mod

    Shor-ty schrieb:

    Ich habe eine Funktion gefunden, die mich auf die std::istream Funktionalitäten zugreifen lässt (wie dumm ich auch bin). Damit kann ich also

    is.std::istream.clear()
    

    aufrufen und mein Problem hat sich damit gelöst 🙂

    Das habe ich mir schon fast gedacht, dass solch eine Funktion existieren muss, habe sie bloß nicht in der Dokumentation gefunden. Man könnte fast zu dem Schluss kommen, jemand hätte die C++-Standardbibliothek 1:1 nachprogrammiert 😉



  • Joa die haben vieles Nachprogrammiert und eben neu definiert.
    Bspw. ist ein:

    vector<type> 
    
    List<type>
    

    Oder ein Double -> Scalar.



  • hustbaer schrieb:

    @Jockelx

    👍
    Stimmt, hab ich nicht dran gedacht, ist aber besser.


Anmelden zum Antworten