Anfängerfehler in OOP für Dummies ?



  • Heiho,

    Insgesammt find ich das Buch gut, es ist sehr angenehm zu lesen.
    Was mir aufgefallen ist ist dieses beispiel "Book"

    Book.h

    #ifndef _BOOK_H
    #define _BOOK_H
    
    #include <string>
    
    class Book
    {
    public:
       Book();
       Book(const std::string& title,
            const std::string& author);
       Book(const Book& book);
       ~Book();
    
       Book& operator=(const Book& book);
    
       const std::string& getTitle() const {return m_Title;}
       const std::string& getAuthor() const {return m_Author;}
    
       void setTitle(const std::string& title) {m_Title = title;}
       void setAuthor(const std::string& author) {m_Author = author;}
    
    private:
       std::string m_Title;
       std::string m_Author;
    };
    
    bool operator==(const Book& left,
                    const Book& right);
    
    bool operator<(const Book& left,
                   const Book& right);
    
    #endif
    

    Book.cpp

    #include "Book.h"
    
    Book::Book() 
       : m_Title(), m_Author()
    {
    }
    
    Book::Book(const std::string& title,
               const std::string& author)
       : m_Title(title), m_Author(author)
    {
    }
    
    Book::Book(const Book& book)
       : m_Title(book.m_Title), m_Author(book.m_Author)
    {
    }
    
    Book::~Book()
    {
    }
    
    Book& Book::operator=(const Book& book)
    {
       if (this == &book)
          return *this;
    
       Book swapBook(book);
    
       m_Title.swap(swapBook.m_Title);
       m_Author.swap(swapBook.m_Author);
       return *this;
    }
    
    bool operator==(const Book& left,
                    const Book& right)
    {
       bool authorMatch = false;
       bool titleMatch = false;
    
       if ( (left.getAuthor() == right.getAuthor()) ||
            (left.getAuthor() == "*") ||
            (right.getAuthor() == "*") )
          authorMatch = true;
    
       if ( (left.getTitle() == right.getTitle()) ||
            (left.getTitle() == "*") ||
            (right.getTitle() == "*") )
          titleMatch = true;
    
       return authorMatch && titleMatch;
    }
    
    bool operator<(const Book& left,
                   const Book& right)
    {
       if (left == right)
          return false;
    
       if (left.getAuthor() < right.getAuthor())
          return true;
       else if (left.getAuthor() == right.getAuthor())
       {
          if (left.getTitle() < right.getTitle())
             return true;
       }
       return false;
    }
    

    Ich habe es nicht test compiliert, aber das brauch ich nicht um direkt die fehler zu sehen die im Compiler anschlagen müssten:

    Book::Book(const Book& book)
    : m_Title(book.m_Title), m_Author(book.m_Author)
    

    sowie

    m_Title.swap(swapBook.m_Title);
    m_Author.swap(swapBook.m_Author);
    

    bin ich gerade total doof oder warum wird auf die privaten m_Author und m_Title variable zugegriffen?
    Das muesste doch eher heissen book.getTitle() sowie getAuthor()

    Was ich mir noch frage:

    Book::Book() 
    : m_Title(), m_Author()
    

    Wozu? die std::strings werden doch automatisch eh leer initialisiert



  • exemplare derselben klasse dürfen gegenseitig auf ihre privaten member zugreifen, das erlaubt c++.

    und die member strings zu initialisieren ist nicht verkehrt. so sieht man sofort, dass der autor explizit möchte, dass der default konstruktor aufgerufen wird und er das nicht etwa "vergessen" hat.



  • Übrigens sind Copy-Ctor, Dtor und operator= in diesem Beispiel gar nicht notwendig - schließlich arbeitest du nicht mit dynamischen Daten (daß std::string dynamische Daten hat, stört nicht, da es sich selber um deren Verwaltung kümmert).



  • das beispiel ist nicht von mir, sondern eine direkte kopie aus dem buch - ich pers. find es nicht verkehrt das das alles da ist
    nur das direkt auf den privaten daten zugegriffen wird find ich irgendwie haesslich, auch wenn es erlaubt ist {sollte eine bemerkung darueber ins buch find ich}



  • Hast du eventuell mal daran gedacht, daß eine Klasse mitunter nicht alle internen Daten über Getter zur Verfügung stellt (vieles davon ist ein Implementierungsdetail und geht niemanden außerhalb der Klasse etwas an)? Da wäre es für den Copy-Ctor recht schwer, etwas zu kopieren, wenn er keinen Zugriff auf die privaten Daten der Quelle hat.



  • stimmt, daran hatte ich noch gar nicht gedacht, is ja logisch {=
    danke dir



  • Mr Evil schrieb:

    ...
    nur das direkt auf den privaten daten zugegriffen wird find ich irgendwie haesslich, ...

    Also ich finde
    - das weder "häßlich" noch,
    - dass "Häßlichkeit" ein Kriterium zur Bücherverbrennung sein sollte 😉

    Innerhalb der Klasse darf (im Sinne eines guten Stils) IMHO durchaus auf die eigene interne Repräsentation zurückgreifen - schließlich macht der getter auch nichts Anderes. Wenn sich an der internen Repräsentation etwas ändert, muss man sowieso alles auf Anpassungsbedarf checken und gerade die "technischen Funktionen" (CopyCtor, operator=, operator==, ...) würde ich dabei nie vergessen.

    Bei der "fachlichen Schnittstelle" wäre das für mich schon eher ein Argument (was für mich auch ein guter Grund ist, ausgefeilte Fachlichkeit ebenso in andere Klassen/Funktionen auszulagern wie ausgefeilte Technik).

    Gruß,

    Simon2.



  • Hallo

    Ich wollte gerade ähnliches schreiben: es gibt doch immer wieder Member für die ich gar keine getter oder setter schreibe, weil sie nur innerhalb der Klasse genutzt werden. Da kann ich ja dann auch direkt auf sie zugreifen.

    chrische



  • Zugriffsschutz nach Innen macht wenig Sinn :p.

    Aber

    #define _BOOK_H
    

    ist dagegen ein echter Fehler. http://www.c-plusplus.net/forum/viewtopic-var-t-is-39461.html

    op==/op< sind ein bisschen merkwürdig implementiert. 🙂


Anmelden zum Antworten