2015-12-27 3 views
7

Nach meinem Verständnis von C++ ist der folgende Code fehlerhaft.Warum funktioniert das Aufrufen eines Members so, als wäre es statisch (wenn nicht) in C++?

#include <iostream> 

class Test { 
private: 
    int num_; 

public: 
    Test(int n) : num_(n) {} 
    void printNum() { std::cout << num_ << '\n'; } 
    void weird() { Test::printNum(); } 
}; 

int main() { 
    Test t(10); 
    t.weird(); 
    return 0; 
} 

Test::weird() Anrufe Test::printNum() als wäre es eine statische Member-Funktion. Test::printNum() greift jedoch auf ein Instanzattribut zu und ist eindeutig nicht statisch. Der Code wird kompiliert und ausgeführt, um 10 auszugeben.

Mein Compiler Apple LLVM Version 7.0.0 (klirren-700.1.76)

Was bin ich?

+3

In diesem Kontext fungiert der Klassennamen-Qualifier als Disambiguator und ist vollkommen legal und in einigen Fällen (z. B. Vererbung) muss unterschieden werden, welche von mehreren ähnlich benannten Funktionen aufgerufen wird. – Galik

+0

@Galik: Bitte beantworten Sie keine Fragen im Kommentarbereich, der zur Klärung dient. –

+0

_ "ist eindeutig keine Klassenmethode" _ Vielleicht ist es nur, dass Ihre Terminologie aus ist, aber es ist definitiv eine "Methode" aka Mitgliedsfunktion. –

Antwort

8

Sie können printNum(); statt dies-> printNum(); .

Wenn Sie Klassen erben, verwenden Sie NameOfClass :: printNum(); die printNum() zu verwenden; Sie wollen.

Beispiel:

class A { public: void test() { std::cout << "hey" << std:endl; } } 
class B : public A { public: void test() { std::cout << "oh" << std:endl; } } 
class C : public B { public: void test() { A::test(); } } 

So Test :: printNum(); ist nur der Aufruf der Methode printNum(); dieser Klasse.

+4

Alles wahr, aber eher irreführend. Die Fähigkeit, den Namen der Funktion zu qualifizieren, hat wenig mit der Vererbung zu tun, außer dass sie zum Aufruf von Basismembern geeignet ist, und selbst wenn dies der Fall wäre, würde dies nicht erklären, warum das OP denkt, dass es für Aufrufe statischer Memberfunktionen reserviert ist oder erklären, warum es nicht ist. –

+2

Dies ist keine Antwort. –

+0

Es ist eine Antwort, wsaleem hat nicht verstanden, warum es funktioniert, diese Antwort ist genug, um ihm eine Idee davon zu geben, warum es funktioniert. "Lightness Races" im Orbit hat eine detaillierte geschrieben, ich habe sie hochgestuft. –

19

Was fehlt mir?

Du irrst dich dazu:

Test::weird() nennt Test::printNum() als Klasse (statisch) Methode.

Es wird nicht als static Methode aufgerufen. Es kann nicht sein, weil es keiner ist.

Innerhalb einer Elementfunktion benötigen Sie keine Objektreferenz oder Zeiger (z. B. this), um eine andere Elementfunktion aufzurufen. So können Sie entweder von diesen schreiben:

this->printNum(); 
printNum(); 

Der vollständige Name von printNum ist eigentlich Test::printNum, so können Sie diese auch tun:

this->Test::printNum(); 
Test::printNum(); 

Außerhalb einer Elementfunktion, die zweite Option in beiden Fällen ist falsch, weil die Funktion nicht statisch ist und Sie keine Objektreferenz oder einen Zeiger zur Verfügung gestellt haben.

Außerhalb eines Member-Funktion würden Sie auch haben, schreiben die Test:: sonst der Compiler nicht über die printNum Sie sprechen würde wissen, aber das allein den Anruf nicht zwingen, eine „statisch zu sein " Anruf. Es wird ein statischer Aufruf sein, wenn die Elementfunktion statisch ist; Zeitraum!

+1

_ "Außerhalb einer Member-Funktion müssten Sie auch den Test schreiben: Andernfalls würde der Compiler nicht wissen, über welche printNum Sie sprechen" _. Ich nehme an, der Compiler würde auch nicht wissen, für welche Instanz er die Funktion aufrufen soll. – wsaleem

+1

@wsaleem: Wahr, das hat nichts damit zu tun, ob Sie 'Test ::' geschrieben haben oder nicht (siehe _previous_ paragraph! _ "Die Funktion ist nicht statisch und Sie haben keine Objektreferenz oder Zeiger angegeben" _), Das ist eher der Punkt hier. –

+0

Ihre Antwort ist großartig, ich war in Konflikt, und ich [recherchiert, was zu tun ist] (http://meta.stackoverflow.com/questions/255150/how-to-choose-between-multiple-correct-answers). Deine Antwort hat mir Dinge erzählt, die ich größtenteils kannte. Der von mir akzeptierte enthält Ihre Antwort _und_ zeigt einen Anwendungsfall, der zeigt, warum die nicht intuitive (für mich) Syntax notwendig ist. Das heißt, ich erkenne Ihre Bemühungen an, die Post und mein Verständnis zu verbessern. Vielen Dank. Und ich habe deinen Kommentar oben erwartet! Aber wie der Meta-Link sagt, musste ich die Antwort wählen, die mir mehr half. Also ging ich mit der anderen Antwort. – wsaleem