13

Was ist der Vorteil einer freien Funktion (im anonymen Namespace und nur in einer einzigen Quelldatei zugänglich) und Senden aller Variablen als Parameter im Gegensatz zu einer privaten Klasse Member-Funktion frei von Parametern und direkt auf Mitgliedsvariablen zugreifen? Vielen Dank!Freie Funktion gegen Member-Funktion

Header:

Class A { 
    int myVariable; 
    void DoSomething() { 
     myVariable = 1; 
    } 
}; 

Quelle:

namespace { 
    void DoSomething2(int &a) { 
     a = 1; 
    } 
} 

int A::SomeFunction() { 
    DoSomething2(myVariable); // calling free function 
    DoSomething(); // calling member fucntion 
} 

Wenn Sie es vorziehen, sie Mitglieder dann machen, was, wenn ich einen Fall, der ich zuerst eine Funktion aufrufen, die keine Mitgliedsvariablen zugreift, sondern dass Funktion ruft eine andere Funktion auf, die auf ein Mitglied zugreift. Sollten sie beide Mitgliedfunktionen oder kostenlos sein?

+1

Kannst du zumindest Code schreiben, der * triest * kompiliert? – Shoe

+0

@StephaneRolland Nein, dieser Link ist über öffentliche Schnittstelle, nicht über die Implementierung – TemplateRex

+1

@TemplateRex lassen Sie mich darauf bestehen, es geht um die Verwendung von Member-Funktionen oder nicht. Ich zitiere die Antwort mit den Worten: "Da viele und viele Methoden direkt von den Interna der Klasse abhängen, impliziert die geringste Veränderung eine ganze Neuschreibung. Es muss nicht so sein." –

Antwort

5

sehen diese Frage: Effective C++ Item 23 Prefer non-member non-friend functions to member functions und auch C++ Member Functions vs Free Functions

Sie sollten in dem Maße frei Funktionen bevorzugen, dass es lose Kopplung fördert.

Überlegen Sie, ob Sie es nur dann zu einer Mitgliedsfunktion machen, wenn es funktioniert auf den Eingeweiden Ihrer Klasse, und dass Sie es wirklich wirklich an Ihre Klasse gebunden betrachten.

Es ist ein Punkt des Buches 101 C++ Codierungsstandards, die angibt, freie Funktion und statische Funktion über Elementfunktionen zu bevorzugen.

Obwohl dies als meinungsbasiert angesehen werden kann, erlaubt es, die Klasse klein zu halten und Bedenken zu trennen.

Diese answer besagt: "Der Grund für diese Regel ist, dass Sie sich bei der Verwendung von Member-Funktionen versehentlich zu sehr auf die Interna einer Klasse verlassen können."

+0

Ist das Problem mit den Member-Funktionen nicht, dass sie den Status von Variablen oder Zeigern nicht behalten? Ich meine, wenn die freie Funktion beendet wird, so tun alle mögliche Zeiger und Variablen, die Sie in der Mitgliedsfunktion erklärt haben ... –

+1

Nicht sicher verstehe ich, was Sie meinen. Ich würde Ihren Satz auf diese Weise zu meinem Verständnis korrigieren und rephasieren: Es gibt nicht viele Unterschiede zwischen einer freien Funktion und einer Methode. Wir könnten vereinfachen und sagen, dass Methoden einfach Zugriff auf einen anderen Eingabeparameter haben, der "this" genannt wird und der implizit übergeben wird und innerhalb der Methode zugänglich ist. Eine Methode hat ** ABSOLUT ** kein anderes Verhalten als freie Funktionen bezüglich des Umfangs der Leben von lokalen Variablen und Zeigern. –

9

Ein Vorteil einer Nichtmitgliedsfunktion in einer Quelldatei ähnelt den Vorteilen von Pimpl idiom: Clients, die Ihre Header verwenden, müssen nicht neu kompiliert werden, wenn Sie Ihre Implementierung ändern.

// widget.h 
class Widget 
{ 
public: 
    void meh(); 
private: 
    int bla_; 
}; 

// widget.cpp 
namespace { 
    void helper(Widget* w) // clients will never know about this 
    { /* yadayada */ } 
} 

void widget::meh() 
{ helper(this); } 

Natürlich, wenn so geschrieben, kann helper() nur die öffentliche Schnittstelle von Widget verwenden, so dass Sie wenig gewinnen. Sie können eine friend Deklaration für helper() innerhalb Widget setzen, aber irgendwann wechseln Sie besser zu einer ausgewachsenen Pimpl-Lösung.

4

Der Hauptvorteil von freien Funktionen gegenüber Elementfunktionen besteht darin, dass die Schnittstelle von der Implementierung entkoppelt wird. Zum Beispiel braucht std::sort nicht irgendetwas über den zugrunde liegenden Container, auf dem es funktioniert, nur, dass es Zugriff auf einen Container (über Iteratoren) gegeben, die bestimmte Merkmale bereitstellen.

In Ihrem Beispiel macht die DoSomething2 Methode nicht viel, um die Kopplung zu verringern, da sie immer noch auf das private Member zugreifen muss, indem sie als Referenz übergeben wird. Es ist fast sicher offensichtlicher, die Zustandsänderung einfach in der einfachen DoSomething Methode stattdessen durchzuführen.

Wenn Sie eine Aufgabe oder einen Algorithmus in Bezug auf die öffentliche Schnittstelle einer Klasse implementieren können, dann ist dies ein guter Kandidat für eine freie Funktion.Scott Meyers fasst hier einen vernünftigen Satz von Regeln zusammen: http://cpptips.com/nmemfunc_encap