2008-11-28 8 views
30

Oto mały program testowy:C++ metoda statyczna członkiem klasy wezwanie na przykład

Na VS2008 + SP1 (VC9) kompiluje grzywny: „przetestować” konsola tylko wyświetlać.

O ile mi wiadomo, metody elementów statycznych nie powinny być wywoływane na obiekcie instancji.

  1. Czy się mylę? Czy ten kod jest poprawny ze standardowego punktu widzenia?
  2. Jeśli to prawda, dlaczego tak jest? Nie mogę znaleźć powodu, dla którego byłoby to dozwolone, a może pomóc w użyciu metody "statycznej lub nie" w szablonach?
+0

co z mvc t ag? – Kiril

+0

Naprawiono: Mogłem mieszać z msvc w tym czasie, myślałem, że może to być problem z kompilatorem. – Klaim

Odpowiedz

54

Standard stwierdza, że ​​nie jest konieczne wywoływanie metody przez instancję, co nie oznacza, że ​​nie można tego zrobić. Istnieje nawet przykład, gdzie jest on stosowany:

C++ 03, 9,4 statyczne członkowie

Statyczny członek s klasy X mogą być określone za pomocą wyrażenia kwalifikowaną id X :: s ; nie jest konieczne używanie składni dostępu do elementów klasy (5.2.5), aby odsyłać do statycznego elementu. Statyczny element członkowski może być oznaczony za pomocą składni dostępu do elementu klasy, w której wartość wyrażenia obiektowego wynosi .

class process { 
public: 
    static void reschedule(); 
}; 

process& g(); 

void f() 
{ 
    process::reschedule(); // OK: no object necessary    
    g().reschedule(); // g() is called 
} 
+0

Wow, nigdy o tym nie wiedziałem. Zakładam, że wywoływana funkcja jest oparta tylko na typie kompilacji (nie w typie środowiska wykonawczego) wyrażenia? –

+0

@SethCarnegie: Tak, używa typu czasu kompilacji obiektu (lub odniesienia do niego), nie można uzyskać dynamicznej wysyłki do metod statycznych. –

+0

To szkoda. +1 –

2

metody statyczne można wywoływać również za pomocą obiektu klasy, tak jak można to zrobić w Javie. Niemniej jednak nie powinieneś tego robić. Użyj operatora zakres jak Test::DoCrash(); Może myślisz o nazw:

namespace Test { 
    void DoCrash() { 
     std::cout << "Crashed!!" << std::endl; 
    } 
}; 

która może być wywołana tylko przez Test::DoCrash(); spoza tego obszaru nazw, jeśli funkcja nie jest importowany bezpośrednio za pomocą using directive/declaration do zakresu rozmówcy.

+2

Tak, wiem, że powinienem to zrobić, dlatego pytam, dlaczego w inny sposób (dzwonienie jak członek) jest dozwolone/nie zabronione. :) – Klaim

8

funkcje statyczne nie potrzebuje się instanciated obiekt na miano, więc

k.DoCrash(); 

zachowuje się dokładnie tak samo jak

Test::DoCrash(); 

używając operatora rozdzielczość zakres (::), aby określić funkcję statyczną wewnątrz klasy.

Należy zauważyć, że w obu przypadkach kompilator nie umieszcza wskaźnika this w stosie, ponieważ funkcja statyczna go nie potrzebuje.

+1

Wolę powiedzieć _pass "ten" wskaźnik jako parametr_ zamiast _put go w stosie_. Rzeczywisty sposób podlega konwencji wywoływania konkretnej platformy. Jednak +1 za wzmiankę o tej funkcji metod statycznych. – Melebius

+0

Jest jedna różnica: w 'k.DoCrash()' obliczany jest przedrostek 'k'. Jeśli 'k' jest po prostu nazwą obiektu, to prawdopodobnie nie ma znaczenia, ale może to być wywołanie funkcji lub inne wyrażenie z efektami ubocznymi:' func(). DoCrash() ' –

3

2) Jeśli to prawda, dlaczego tak jest? Nie mogę znaleźć powodu, dla którego byłoby to dozwolone, a może pomóc w użyciu metody "statycznej lub nie" w szablonach?

To potencjalnie użyteczne w kilku sytuacjach:

  • [The „«statyczne lub nie»metoda w szablonach” zasugerować:] gdy wiele rodzajów mógł zostać określony na podstawie szablonu, a szablon następnie wywołuje element: typy zapewniające funkcję statyczną mogą być wywoływane przy użyciu tej samej notacji co funkcja składowa - pierwsza z nich może być bardziej wydajna (brak wskaźnika do przejścia/wiązania), podczas gdy druga pozwala na polimorficzne (virtual) wysyłka i wykorzystanie danych członkowskich

  • minimalizując konserwacja KOD

    • jeżeli funkcja zmienia się od potrzeby dane specyficzne dla instancji nie potrzebują go - i w związku z tym wykonane static aby umożliwić łatwe instancji darmowy i zapobiega przypadkowemu użyciu przykład danych - wszystkie punkty istniejącego użytkowania klienta nie muszą być labouriously aktualizowane

    • jeśli się zmienił polu wpisz var.f() inwokacja nadal użyć funkcji var TYP za, natomiast Type::f() może wymagać korekty ręcznej

  • gdy masz ekspresji lub funkcji połączenia przekazujących wartości i chcą wywołać (potencjalnie lub zawsze) static funkcję oznaczenie . może uniemożliwić konieczności korzystania decltype lub szablon wsparcie, aby uzyskać dostęp do typ, tak więc można użyć :: notacji

  • czasem nazwa zmiennej jest po prostu o wiele krótszy, bardziej wygodne, i nazwane w bardziej samodokumentujące sposób

+1

Co najmniej na kompilatorze MSVC 2013, wywołując metody statyczne za pośrednictwem instancji działają, ale generują ostrzeżenie kompilatora dotyczące zmiennej bez odniesienia, jeśli zmienna nie jest używana do niczego innego niż wywoływanie metody statycznej. – abelenky

Powiązane problemy