2009-05-08 9 views
4

Sagen, ich habe:Ist ein Zeiger auf ein C++ - Objekt die bevorzugte Methode zum Aufrufen einer statischen Elementfunktion?

class A { 
public: 
    static void DoStuff(); 

    // ... more methods here ... 
}; 

Und später habe ich eine Funktion, die DoStuff anrufen will:

B::SomeFunction(A* a_ptr) { 

Ist es besser zu sagen:

a_ptr->DoStuff(); 
} 

Oder ist die folgende besser, obwohl ich einen Instanzzeiger habe:

A::DoStuff() 
} 

Das ist rein eine Frage des Stils, aber ich möchte einige fundierte Meinungen bekommen, bevor ich eine Entscheidung treffe.

+4

Ein Gesamtnit: aber C++ hat keine "Methoden". Es hat Funktionen. Nirgendwo im C++ - Standard spricht man von "Methoden". Methode ist ein allgemeiner OO-Term, der Funktionen in C++ abbildet. Was deine Frage betrifft: Es ist eine reine Stilsache, beide machen das gleiche. –

+0

Fixed the nit ... –

+1

LOL, Entschuldigung für eine wählerische b * stard. –

Antwort

22

Ich denke, ich würde "A :: DoStuff()" bevorzugen, da es klarer ist, dass eine statische Methode aufgerufen wird.

+0

Obwohl ich Adams Beispiel wirklich mag, gebe ich dem Publikumsliebling den Scheck für diese subjektive Frage. –

6

Ich persönlich bevorzuge die A :: DoStuff() Konvention, weil es jedem, der den Code liest, sofort klar ist, dass es ein Aufruf einer statischen Memberfunktion ist.

19

Es ist besser, die statische Methode über ihren Namen und nicht über ein Objekt aufzurufen, da sie dieses Objekt überhaupt nicht verwendet. In Java gibt es das gleiche Problem. Ein nicht allzu seltenes Problem in Java ist die folgende:

Thread t = getSomeOtherThread(); 
t.sleep(1000); 

Dies kompiliert gut, aber ist fast immer ein Fehler - Thread.sleep() ist eine statische Methode, die den aktuellen Thread zu Schlaf verursacht, nicht der Faden zu sein gehandelt, als der Code zu implizieren scheint.

+0

Guter Punkt. Ich vermute ähnliche Fehler könnten in C++ Frameworks auftreten. –

+1

Wenn die API dies hat, dann denke ich, dass dies ein wichtiger "Bug" in der API ist. Vielleicht liegt es daran, dass Java nicht das Konzept der freien Funktionen hat, das es tun musste - aber das ist in C++ nicht notwendig. Eine Funktion sollte eine Memberfunktion sein, wenn sie einen speziellen Zugriff auf das Objekt hat (zB private Konstruktor). –

3

Obwohl ich zustimme, dass A :: DoStuff() ist klarer, und es ist, was ich selbst schreiben würde, kann ich ein Argument für den Weg über den Zeiger sehen, die "angenommen, der Klassenname ändert sich". Wenn Klasse A Klasse B wird, müssen wir nur den Klassennamen an einer Stelle (die Zeigerdeklaration) statt zwei aktualisieren.

Nur so ein Gedanke ...

+1

Außerdem könnte sich die statische Methode irgendwann in eine Instanzmethode ändern. Ich habe das gelegentlich gesehen. –

+0

Jede Änderung führt zu Kompilierzeitfehlern. Das Ändern von Namen ist eine einfache Frage von Suchen und Ersetzen (normalerweise - funktioniert gut mit Namen, die aussagekräftiger sind als "A" und "B"). –

0

Im Allgemeinen kann ich die A :: DoStuff(); Weg statt a-> DoStuff(); weil vielleicht eines Tages die Funktion, in der ich mich befinde, diesen Instanzzeiger wegen Refactoring nicht mehr haben wird. Aber es ist eine totale Stilsache, dass Sie keinen Schlaf verlieren sollten.

1

Jon Skeet opened my eyes warum sollten Sie nicht eine statische Methode durch einen Instanzzeiger aufrufen. Sein Beispiel ist in Java, aber das Konzept gilt für C++, auch:

Thread t = new Thread(...); 
t.start(); 
t.sleep(1000); // Which thread does it look like this will affect? 

Als ich bemerkte, als ich seine Antwort lautete: „Bis ich [Jons Beitrag] gelesen, ich als statische Methoden aufrufen zu können, durch Eine Instanz referenziert ein Feature. Jetzt weiß ich es besser. "

Kurz gesagt, rufen Sie statische Methoden mit dem Klassennamen, nicht eine Instanz. Meiner Meinung nach ist es mehr als ein Stilproblem - es kann zu irreführendem, fehlerhaften Code führen.

+0

Das sieht wie ein wirklich erfundenes Beispiel aus. Wenn Sie ein Schlafmitglied in einer Thread-Klasse haben, dann sollte, wenn dieses Mitglied * nur * nur diesen Thread betrifft, die Person erschossen werden, die die API geschrieben hat. –

+0

Eine andere Antwort erwähnt dies auch - das muss ein Problem in Java sein. Ein Fehler im Design einer Java-API (wegen des Fehlens von freien Funktionen) ist jedoch nicht unbedingt ein gutes Argument für etwas in C++. –

+0

Während das angegebene Beispiel tatsächlich Java war, ist es auch mehr oder weniger gültiges C++, wenn eine Thread-Klasse mit einer start() - Instanzmethode und einer statischen sleep() -Methode angegeben wird. Natürlich müsstest du auch entweder das 'neue' oder' t' eines Zeigers loswerden und das 't.start()' in 't-> start()' usw. ändern - aber diese Änderungen sind neben dem Punkt, eine statische Methode durch eine Instanz aufzurufen. –

0

Ich habe viele Fragen in Java gesehen, wo, wenn Leute eine statische Methode mit der Syntax des Aufrufs einer Instanzmethode durch ein Objekt aufgerufen haben und das Objekt tatsächlich eine Unterklasse des Variablentyps ist, fragen sich die Leute, warum es nicht Rufen Sie eine statische Methode desselben Namens in der Unterklasse auf.Die Tatsache, dass sie sie über ein Objekt aufrufen, lässt sie denken, dass es sich um eine Instanzmethode handelt, die überschrieben werden kann, und sie führt eine dynamische dynamische Nachschlagefunktion aus, die den Typ des Objekts verwendet.

Aber natürlich wird das Objekt nie im Aufruf verwendet - nur der Typ der Variablen wird zur Kompilierzeit verwendet, um zu entscheiden, welche statische Methode der Klasse es ist. Wenn Sie also ein Objekt dort platzieren, ist es völlig irreführend, weil es Leute denken lässt, dass es benutzt wird, wenn es nicht ist. Deshalb bevorzuge ich nur den Aufruf von statischen Methoden über den Klassennamen - es entspricht genau dem Aufruf durch eine Variable des Klassentyps; aber es sagt dir genau, was vor sich geht, ohne überflüssige irreführende Zusatzinformationen.

Verwandte Themen