2015-12-27 9 views
7

Zgodnie z moim rozumieniem języka C++ następujący kod jest błędny.Dlaczego wywoływanie funkcji członka działa tak, jakby było statyczne (gdy nie jest) działa w 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() rozmowy Test::printNum() gdyż statycznej funkcji składowej. Jednak Test::printNum() uzyskuje dostęp do atrybutu instancji i wyraźnie nie jest statyczny. Jednak kod kompiluje się i uruchamia, aby wyprowadzić 10.

Moje kompilator jest jabłko LLVM w wersji 7.0.0 (dzyń-700.1.76)

Czego mi brakuje?

+3

W tym kontekście kwalifikator nazwy klasy działa jak disambiguator i jest całkowicie legalny, aw niektórych przypadkach (np. Dziedziczenia) wymagane jest rozróżnienie, która z kilku podobnych funkcji zostanie wywołana. – Galik

+0

@Galik: Proszę nie odpowiadać na pytania w sekcji komentarzy, która dotyczy prośby o wyjaśnienia. –

+0

_ "z pewnością nie jest metodą klasową" _ Może po prostu Twoja terminologia jest wyłączona, ale z pewnością jest to "metoda" zwana funkcją członka. –

Odpowiedz

8

Możesz użyć funkcji printNum(); zamiast tego -> printNum(); .

Kiedy dziedziczysz klasy, używasz NameOfClass :: printNum(); używać funkcji printNum(); chcesz.

przykład:

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(); } } 

więc test :: printNum(); jest po prostu wołaniem do metody printNum(); tej klasy.

+4

Wszystko prawda, ale raczej wprowadza w błąd. Możliwość zakwalifikowania nazwy funkcji ma niewiele wspólnego z dziedziczeniem, poza faktem, że wygodnie jest wywoływać elementy podstawowe, a nawet gdyby tak było, nie wyjaśniałoby to, dlaczego OP myśli, że jest zarezerwowany dla wywołań funkcji statycznych' lub wyjaśnij, dlaczego tak nie jest. –

+2

To nie jest odpowiedź. –

+0

To odpowiedź. Wsaleem nie rozumiał, dlaczego działa, ta odpowiedź wystarczy, aby dać mu pojęcie, dlaczego to działa. Lekkość Races in Orbit napisała szczegółową, przegłosowałem ją. –

19

Czego mi brakuje?

Mylisz o tym:

Test::weird() wzywa Test::printNum() jako metody klasy (statyczna).

Nie jest to tak zwana metoda static. Nie może tak być, ponieważ to nie on.

W ramach funkcji składowej nie jest wymagane odwołanie do obiektu lub wskaźnik (np. this) w celu wywołania innej funkcji składowej. Więc można napisać jedną z nich:

this->printNum(); 
printNum(); 

Pełna nazwa printNum jest rzeczywiście Test::printNum, więc można zrobić to zbyt:

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

Poza funkcji składowej, druga opcja w obu przypadkach jest niepoprawny, ponieważ funkcja nie jest statyczna i nie podano referencji obiektu ani wskaźnika.

Poza funkcji składowej, którą również mieć napisać Test:: inaczej kompilator nie wiedziałby, która printNum mówisz, ale samo w sobie nie zmusza wezwanie być „statyczne " połączenie. Będzie to statyczne wywołanie, ponieważ funkcja członka jest statyczna; Kropka!

+1

_ "Poza funkcją członka musisz też napisać Test :: w przeciwnym razie kompilator nie będzie wiedział, o której nazwie" ". Przypuszczam, że kompilator również nie wiedziałby, do której instancji wywołać funkcję. – wsaleem

+1

@wsaleem: Wprawdzie to prawda, ale nie ma to nic wspólnego z tym, czy napisałeś 'Test ::" czy nie (patrz _previous_ paragraph! _ "Funkcja nie jest statyczna i nie podałeś referencji obiektu lub wskaźnika" _), co jest raczej punktem tutaj. –

+0

Twoja odpowiedź jest wspaniała, byłem w konflikcie, a ja [badałem, co należy zrobić] (http://meta.stackoverflow.com/questions/255150/how-to-choose-between-multiple-correct-answers). Twoja odpowiedź opowiedziała mi o rzeczach, które w większości wiedziałem. Ten, który zaakceptowałem zawiera twoją odpowiedź _ i_ pokazuje przypadek użycia, pokazujący, dlaczego niezrozumiała jest składnia (do mnie). To powiedziawszy, uznaję twoje wysiłki w poprawie stanowiska i mojego zrozumienia. Dziękuję Ci. I oczekiwałem twojego komentarza powyżej! Ale, jak mówi meta link, musiałem wybrać odpowiedź, która pomogła mi bardziej. Więc poszedłem z drugą odpowiedzią. – wsaleem

Powiązane problemy