Ein paar Theoriefragen



    1. Nein, eine Klasse ist abstrakt, wenn keine Instanz von ihr erzeugt werden kann. Dafuer gibt es verschiedene Methoden, z.B. eine rein virtuelle Mehtode, privater Konstruktor/Destruktor.

    Darüber kann man sich streiten: Auch bei privatem Ctor / Dtor können Instanzen erstellt werden. Meiner Meinung nach sind pure virtual Methoden das einzige was eine Klasse abtrakt macht.



  • Ein Singleton kann ja einen privaten ctor/dtor haben, trotzdem lässt sich eine Instance davon erzeugen. Klar muss es entsprechend implementiert sein, aber möglich ist es.



  • Huhu, ich habs mal kurz durchgemacht, hoffe es stimmt einigermaßen, wenn nicht, dann korrigiert mich bitte 😉

    1. richtig (lass das "z.B." da weg)

    2. Das Problem ist, dass die Objekte, auf die die Zeiger zeigen, nicht kopiert werden, sprich du hast dann viele Zeiger auf nur 1 Objekt. Jetzt steht in deinem Destruktor ein "delete", dann werden ja zig Objekte zerstört, aber in Wirklichkeit hast du ja nur 1.

    3. Der Kopiekonstruktur wird dann aufgerufen, wenn du ein neues Objekt erzeugen willst und der Parameter ein Objekt dieser Klasse (oder Oberklasse) übergibst.

    4. Was heißt effizienter... wenn du late-binding (für Polymorphy) brauchst, dann nimmst du es, wenn du es nicht brauchst, dann lass es auch weg.

    5. Wenn du den Zeiger verschoben hast, dann ist es ein Undefiniertes Verhalten ?!.

      • falls return-by-value, der Kopiekonstruktor, falls keine Optimierung.
        - falls return-by-reference natürlich nichts.
    6. Sowas kannst du doch austesten. Schreibst 2 kleine Klassen und mache die Zuweisung... vielleicht beschimpft dich der Compiler, vielleicher aber auch nicht.

    7. Bei einer virtuellen Methode wird zur Laufzeit entschieden, ob sie aufgerufen wird, oder nicht... der dynamische Typ des Objekts, mit dem sie aufrufst, entscheidet dies.

    8. Eine Klasse ist abstrakt, wenn sie min. 1 rein-virtuelle Methode hat.

    Gruß



  • Haimi schrieb:

    1. Jede Funktion einer Oberklasse ist in einer abgeleiteten Klasse immer sichtbar.
      Ich würde nein sagen, z.b. bei private Funktionen der Oberklasse.

    Ich habe nochmal drueber nachgedacht. Sichtbarkeit wird nicht durch private eingeschraenkt. Habe ich beispielsweise eine friend-Funktion, so kann sie auf die privaten Methoden zugreifen. D.h. sie muessen sichtbar sein, wobei das ganz auf den Sichtbarkeitsbegriff deines Lehrers/Professors ankommt.



  • Ich nehme an, dass mit 5) sicheres Löschen in dem Sinn gemeint ist, dass die Daten, auf die der Zeiger zeigt, gelöscht (überschrieben) werden, so dass niemand sie jemals wiederfinden kann. Bei kryptographischen Werkzeugen ist so etwas wichtig. Von Haus aus tut delete[] das üblicherweise nicht, will sagen, ich kenne keine Implementation, bei der das der Fall ist.

    Für 7) braucht es einen entsprechenden Konstruktor. Etwa ergibt

    struct tier { };
    struct hund : tier { };
    
    // ...
    
    tier kuh;
    hund bello = kuh; // Äh...wie bitte?
    

    keinen Sinn, aber

    struct tier { };
    
    struct hund : tier {
      hund(tier &futter) { std::cout << "Lecker! Ich meine...wuff!" << std::endl; }
    };
    
    // ...
    
    tier kuh;
    hund bello(kuh);
    

    freut den Hund. Was eine Konversion mit der Sache zu tun haben soll...vielleicht geht es da in verdrehter Weise um RTTI-Konstrukte, von denen man besser die Finger lässt (wenn du dynamic_cast brauchst, solltest du dein Design überdenken).



  • knivil schrieb:

    Ich habe nochmal drueber nachgedacht. Sichtbarkeit wird nicht durch private eingeschraenkt. Habe ich beispielsweise eine friend-Funktion, so kann sie auf die privaten Methoden zugreifen. D.h. sie muessen sichtbar sein, wobei das ganz auf den Sichtbarkeitsbegriff deines Lehrers/Professors ankommt.

    In diesem Fall meint der Prof. bestimmt ausschließlich Vererbung.
    Macht es Sinn, eine Methode privat zu machen und dann friend herzunehem, dass die Subklasse auf die private Methode der Oberklasse zugreifen kann?



  • Vielen Dank für eure Hilfe! Die Fragen sind zum Teil echt nicht ganz eindeutig, wie es scheint.

    Leider handelt es sich auch noch um ja/nein Fragen ohne Begründung, bei denen falsche sogar Punktabzüge geben.

    Ich habe mal eure Vorschläge ausgewertet und zusammengefasst... und die Fragen mit Ja/ Nein beantwortet:

    1. Jede Funktion einer Oberklasse ist in einer abgeleiteten Klasse immer sichtbar.
      Falsch

    2. Das Problem der flachen Kopie bei der Zuweisung von Objekten ist, dass die Zeiger nicht kopiert werden.
      Falsch

    3. Der Kopierkonstruktor wird implizit bei der Call-by-Reference Parameterübergabe von Objekten aufgerufen.
      Falsch

    4. Die späte Bindung einer Funktion ist Laufzeit-effizienter als die frühe Bindung.
      Falsch

    5. delete[] nimmt ein sicheres Löschen vor. Die Daten können nicht wiederhergestellt werden.
      Falsch

    6. Bei der Rückgabe von Objekten aus Funktionen wird immer der überladene Zuweisungsoperator aufgerufen.
      Falsch

    7. Weist man einer Variablen vom Typ der Unterklasse einen Wert vom Typ einer Oberklasse dieser Unterklasse zu, so ist dies nur mit expliziter Konversion möglich.
      Falsch

    8. Eine virtuelle Funktion ist eine Funktion, deren Code zur Laufzeit generiert wird.
      Falsch

    9. Eine Klasse ist genau dann abstrakt, wenn sie ausschließlich rein virtuelle Methoden enthält.
      Falsch

    Greez
    Haimi



  • Ich an deiner Stelle wuerde mal die Musterloesung einholen oder deinen Prof fragen. Ein "Falsch" ueberall wuerde mich stutzig machen.



  • Dweb schrieb:

    knivil schrieb:

    Ich habe nochmal drueber nachgedacht. Sichtbarkeit wird nicht durch private eingeschraenkt. Habe ich beispielsweise eine friend-Funktion, so kann sie auf die privaten Methoden zugreifen. D.h. sie muessen sichtbar sein, wobei das ganz auf den Sichtbarkeitsbegriff deines Lehrers/Professors ankommt.

    In diesem Fall meint der Prof. bestimmt ausschließlich Vererbung.

    class A {
    private:
       void foo(int) {}
    };
    
    void foo(int) {}
    
    class B : public A {
    public:
       void test() {
          foo(1); // function "A::foo" is inaccessible
       }
    };
    

    Sichtbarkeit wird nicht durch private eingeschränkt.



  • Shade Of Mine schrieb:

    Sichtbarkeit wird nicht durch private eingeschränkt.

    Das Problem ist nur, das wir dennoch nur raten können, wie der Professor die Antworten auslegt. Und Professoren sind (nach meiner bisherigen Erfahrung, zumindest wenn es um die Theoretiker geht) im IT-Bereich tendenziell lernresistent und halten ihre Meinung automatisch für die einzig richtige.

    Ich würde mich im Zweifel wirklich an den Professor wenden, und dies ggf. mit ihm durchsprechen, wenn eine Antwort anders ausfällt als erwartet (dann sollte man sich aber im Vorfeld notieren, warum man so und nicht anders geantwortet hätte...).



  • asc schrieb:

    Das Problem ist nur, das wir dennoch nur raten können, wie der Professor die Antworten auslegt.

    Keine Frage. zB wird der Professor auch erwarten dass späte bindung langsamer ist als frühe 😉



  • Haimi schrieb:

    Die Fragen sind zum Teil echt nicht ganz eindeutig, wie es scheint.

    Ich tippe, es liegt daran, dass der, der die Klausur erstellt hat, C++ besser beherrschen könnte.

    Haimi schrieb:

    Leider handelt es sich auch noch um ja/nein Fragen ohne Begründung, bei denen falsche sogar Punktabzüge geben.

    Habt ihr so etwas wie eine Klausureinsicht? Wenn ja, würde ich auf jeden Fall dahin gehen und nachgucken, wie sie korrigiert wurde und ggf für die Punkte kämpfen.

    Haimi schrieb:

    1. Jede Funktion einer Oberklasse ist in einer abgeleiteten Klasse immer sichtbar.
      Falsch

    Kann nich nichts zu sagen, weil ich nicht weiß, was der Prüfer mit "Sichtbarkeit" meint. Das, was public, private, protected steuert ist die sogenannte "Zugriffskontrolle". Wenn der Prüfer das Konzept der Zugriffskontrolle "Sichtbarkeit" nennt, dann wäre das gut zu wissen. Guck Dir mal die Vorlesungsunterlagen dazu an.

    Haimi schrieb:

    1. Das Problem der flachen Kopie bei der Zuweisung von Objekten ist, dass die Zeiger nicht kopiert werden.
      Falsch

    👍

    Haimi schrieb:

    1. Der Kopierkonstruktor wird implizit bei der Call-by-Reference Parameterübergabe von Objekten aufgerufen.
      Falsch

    👍

    Haimi schrieb:

    1. Die späte Bindung einer Funktion ist Laufzeit-effizienter als die frühe Bindung.
      Falsch

    👍 Sicherlich will der Prüfer hier ein "Falsch" sehen, obwohl der Unterschied wahrscheinlich kaum spürbar sein sollte.

    Haimi schrieb:

    1. delete[] nimmt ein sicheres Löschen vor. Die Daten können nicht wiederhergestellt werden.
      Falsch

    👍 (Zumindest macht der C++ Standard keine solche Garantie)

    Haimi schrieb:

    1. Weist man einer Variablen vom Typ der Unterklasse einen Wert vom Typ einer Oberklasse dieser Unterklasse zu, so ist dies nur mit expliziter Konversion möglich.
      Falsch

    kommt drauf an, was der Prüfer genau mit "expliziter Konversion" meinst.

    Haimi schrieb:

    1. Eine virtuelle Funktion ist eine Funktion, deren Code zur Laufzeit generiert wird.
      Falsch

    👍

    Haimi schrieb:

    1. Eine Klasse ist genau dann abstrakt, wenn sie ausschließlich rein virtuelle Methoden enthält.
      Falsch

    👍



  • krümelkacker schrieb:

    Haimi schrieb:

    1. Die späte Bindung einer Funktion ist Laufzeit-effizienter als die frühe Bindung.
      Falsch

    👍 Sicherlich will der Prüfer hier ein "Falsch" sehen, obwohl der Unterschied wahrscheinlich kaum spürbar sein sollte.

    Müsste das nicht gleich schnell sein (was ja heißt: "nicht effizienter")? Späte Bindung ist doch, wenn man gegen eine DLL linkt, richtig?

    krümelkacker schrieb:

    Haimi schrieb:

    1. Weist man einer Variablen vom Typ der Unterklasse einen Wert vom Typ einer Oberklasse dieser Unterklasse zu, so ist dies nur mit expliziter Konversion möglich.
      Falsch

    kommt drauf an, was der Prüfer genau mit "expliziter Konversion" meinst.

    Einen static_cast oder so wahrscheinlich..?



  • Zum Thema Sichtbarkeit lässt sich H.Sutter in einem der Exceptional Büchern aus (glaube Excepional Style). Den entsprechenden gotw finde ich grad nicht. Auf jeden Fall sind auch private Methoden sichtbar, merkt man z.B. bei der Überladungsauflösung. Man kann nur den Namen eines privaten Symbols nicht verwenden, sehen kann man es.
    Allerdings wird der Begriff Sichtbarkeit sehr häufig im Zusammenhang mit Zugriffskontrolle verwendet, darum weiß ich auch nicht ob ich da 'Ja' ankreuzen würde.
    Man könnte auch noch darüber diskutieren, was denn überhaupt eine Funktion einer Basisklasse ist (What's in a class). Funktionen, die gar nicht im header deklariert sind, sind dann tatsächlich nicht sichtbar, zumindest nicht bis zum Linken.



  • Vielleicht ist mit Sichtbarkeit das gemeint:

    #include <iostream>
    #include <string>
    using namespace std;
    
    struct A
    {
      void f( string x ) {}
    };
    
    struct B : A
    {
      void f( int x ) {}
      void g() { f( "aa" ); }
    };
    
    int main()
    {
      B aB;
      aB.g();
    }
    

    f mit Parameter std::string ist in g nicht sichtbar => Fehler
    Mit using A::f funktioniert es dann.



  • krümelkacker schrieb:

    Haimi schrieb:

    1. Die späte Bindung einer Funktion ist Laufzeit-effizienter als die frühe Bindung.
      Falsch

    👍 Sicherlich will der Prüfer hier ein "Falsch" sehen, obwohl der Unterschied wahrscheinlich kaum spürbar sein sollte.

    Na 100%ig will er hier "Falsch" sehen. Selbst wenn es überhaupt keinen Unterschied gäbe, wäre die Behauptung falsch.



  • ichduersiees schrieb:

    krümelkacker schrieb:

    Haimi schrieb:

    1. Die späte Bindung einer Funktion ist Laufzeit-effizienter als die frühe Bindung.
      Falsch

    👍 Sicherlich will der Prüfer hier ein "Falsch" sehen, obwohl der Unterschied wahrscheinlich kaum spürbar sein sollte.

    Müsste das nicht gleich schnell sein (was ja heißt: "nicht effizienter")? Späte Bindung ist doch, wenn man gegen eine DLL linkt, richtig?

    "Späte Bindung" (late binding) ist ein OOP-Begriff und bezieht sich im Falle von C++ auf virtuelle Funktionen.

    ichduersiees schrieb:

    krümelkacker schrieb:

    Haimi schrieb:

    1. Weist man einer Variablen vom Typ der Unterklasse einen Wert vom Typ einer Oberklasse dieser Unterklasse zu, so ist dies nur mit expliziter Konversion möglich.
      Falsch

    kommt drauf an, was der Prüfer genau mit "expliziter Konversion" meint.

    Einen static_cast oder so wahrscheinlich..?

    Ja wie denn?

    class Oberklasse
    {
      int i;
    public:
      Oberklasse() : i(0) {}
    };
    
    class Unterklasse : public Oberklasse
    {
      int j;
    public:
      Unterklasse() : j(0) {}
    };
    
    ...
    
    Unterklasse d;
    Oberklasse s;
    d = s;                            // kompiliert nicht
    d = static_cast<Unterklasse>(s);  // kompiliert nicht
    d = static_cast<Unterklasse&>(s); // kompiliert, aber undefiniertes Verhalten
    static_cast<Oberklasse&>(d) = s;  // kompiliert, alles OK
    


  • krümelkacker schrieb:

    [...]

    Die Unterklasse könnte auch einen Konvertierungs-Ctor/Zuweisungs-Operator haben, welcher ein Objekt der Oberklasse annimmt. Ob man (der Prof.) dass dann als explizit oder implizit betrachtet, weiß ich nicht.



  • krümelkacker schrieb:

    "Späte Bindung" (late binding) ist ein OOP-Begriff und bezieht sich im Falle von C++ auf virtuelle Funktionen.

    hm..?

    http://en.wikipedia.org/wiki/Late_binding schrieb:

    Late binding is often confused with dynamic dispatch, but there are significant differences. With early binding the compiler statically verifies that there are one or more methods with the appropriate method name and signature. This is usually stored in the compiled program as an offer in a virtual method table and is very efficient. With late binding the compiler doesn’t have enough information to verify the method even exists, let along bind to its particular slot on the v-table. Instead the method is looked up by name at runtime.



  • > Late binding is often confused with dynamic dispatch [...] Instead the method is looked up by name at runtime.

    Aha. Die Definition kannte ich nicht. Danke Dir für den Hinweis!

    Dann macht die Frage in der Klausur natürlich noch weniger Sinn, zumindest wenn sie sich auf C++ bezieht.


Anmelden zum Antworten