Funktionen besser als Methoden
-
Ich hab gehört, dass man, wenn es möglich ist, besser eine Funktion schreiben ,soll als eine Methode, damit die Klasse schlank bleibt. Dabei geht es nicht nur um statische Methoden, sondern um alle Methoden die irgendwie raus können. Was soll da der Vorteil sein?
-
Wo hast du das denn gehört? Um eine Klasse schlank zu halten, kannst du eine neue Klasse schreiben.
-
Soweit ich weiss sollte man Methoden, die nicht auf klasseninterne Variabeln und Methoden zugreifen muessen, als Funktionen implementieren. Allerdings nicht umbedingt um die Klasse schlank zu halten. Es ist halt einfach besser, dass das, was nicht internen Zugriff braucht, auch keinen hat.
-
icarus2 schrieb:
Soweit ich weiss sollte man Methoden, die nicht auf klasseninterne Variabeln und Methoden zugreifen muessen, als Funktionen implementieren. Allerdings nicht umbedingt um die Klasse schlank zu halten. Es ist halt einfach besser, dass das, was nicht internen Zugriff braucht, auch keinen hat.
Warum? Kannst du mal ein Beispiel machen um das zu zeigen?
-
funktiomethoder schrieb:
icarus2 schrieb:
Soweit ich weiss sollte man Methoden, die nicht auf klasseninterne Variabeln und Methoden zugreifen muessen, als Funktionen implementieren. Allerdings nicht umbedingt um die Klasse schlank zu halten. Es ist halt einfach besser, dass das, was nicht internen Zugriff braucht, auch keinen hat.
Warum? Kannst du mal ein Beispiel machen um das zu zeigen?
Erklaerung und Beispiel im "Effective C++, Third Edition" von Scott Meyers, Item 23 "Prefer non-member non-friend functions to member functions".
Hast du das Buch per Zufall zur Hand? Falls nicht kann ichs sehr empfehlen.
-
ja da war etwas...
an das kapitel erinnere ich mich
-
Interessanter Artikel zu einem verwandten Thema: http://www.gotw.ca/publications/mill02.htm
Wenn Du die Wahl hast, eine freie Funktion oder eine Methode zu schreiben, dann ist das mit der freien Funktion vielleicht gar keine schlechte Idee, da Du dann nicht versehentlich Invarianten verletzen kannst und eben nur auf public Member Zugriff hast.
Und sonst fällt mir dazu noch ein, dass in generischen Funktionen freie Funktionsaufrufe bevorzugt werden sollten. Beispiel:
template<class Container> void show(Container const& c) { using std::begin; using std::end; auto it = begin(c); auto const ee = end(c); while (it!=ee) { std::cout << *it << ' '; ++it; } std::cout << '\n'; }Statt hier c.begin() und c.end() zu schreiben, werden freie Funktionen begin/end aufgerufen. Das ermöglicht es, dieses Funktionstemplate auch für Typen nutzbar zu machen, die solche Methoden gar nicht anbieten. Für rohe Arrays werden in diesem Beispiel dann std::begin/std::end verwendet, die für Arrays auch überladen sind. Und sonst wird noch ADL verwendet, um ggf passende begin/end Funktionen zu suchen.
ADL = argument dependent lookup
-
Könnt ihr mal ein paar Beispiele aus eurem Code zeigen, wo ihr das macht? So ein Container show programmiert man ja nicht so wirklich oft.
-
inline Quaternion operator * (Quaternion const& q1, Quaternion const& q2) { Quaternion q(q1[0] * q2[0] - q1[1] * q2[1] - q1[2] * q2[2] - q1[3] * q2[3], q1[0] * q2[1] + q1[1] * q2[0] + q1[2] * q2[3] - q1[3] * q2[2], q1[0] * q2[2] - q1[1] * q2[3] + q1[2] * q2[0] + q1[3] * q2[1], q1[0] * q2[3] + q1[1] * q2[2] - q1[2] * q2[1] + q1[3] * q2[0]); return q; }template<unsigned int N> BlockMatrix<N> operator * (BlockMatrix<N> const& m1, BlockMatrix<N> const& m2) { BlockMatrix<N> m; for (unsigned i = 0; i < N; ++i) for (unsigned j = 0; j < N; ++j) for (unsigned k = 0; k < N; ++k) m[i][j] += m1[k][j] * m2[i][k]; return m; }
-
Ich bringe mal das Beispiel von Scott Meyers. Sagen wir du moechtest einen Web-Browser programmieren. Dann kannst du neben anderem den Cache, die Histoy und die Cookies loeschen. Du hast also folgende Klasse:
class WebBrowser { public: ... void clearCachge(); void clearHistroy(); void clearCookies(); ... };Viele Benutzer moechten nun alles auf einmal loeschen koennen. Man koennte nun eine Methode void clearEverything implementieren in WebBrowser, die den Cache, die Histroy und die Cookies loescht:
class WebBrowser { public: ... void clearEverything(); ... };Die Methode clearEverything() braucht allerdings keinen Zugriff auf Internes von WebBrowser. Man kann sie ohne weiteres mit clearHistroy(), clearCache() und clearCookies() implementieren, die oeffentlich sind.
Nach dem Grundsatz der Data Encapsulation (Datenkapselung) sollte man deshalb clearEverything auch keinen Zugriff auf die internen Dinge geben.
Deshalb ist es besser clearEverything() als als non-member function zu implementieren:void clearBrowser(WebBrowser& wb) { wb.clearCache(); wb.clearHistory(); wb.clearCookies(); }Man kann sich natuerlich ueber dieses Konzept streiten. Falls du genauere und ausfuehrlichere Argumente moechtest verweise ich dich auf meine Quelle oben.