Funkcje virtualne w C++ - wywołanie via obiekt a wydajność

0

Heyka :)
Mam następujące pytanka dot. funkcji virtualnych w C++:

  1. czy jeśli mam obiekt bazowy z funkcją virtualną oraz obiekt klasy pochodnej, który "zasłania" ową funkcję to czy jeśli wywołam tą funkcję przez obiekt tj. obiket.funkcja() a nie przez wskaźnik tj. wskaznik->funkcja(); to czy wydajność mojej aplikacji się pogorszy?
  2. Drugie pytanie jest trochę analogiczne: jeśli mam wskaźnik do klasy pochodnej (a nie bazowej) to czy jeśli wywołam ową funkcję to czy stracę na wydajności?
  3. Trzecie pytanie to czy jeśli mam wskaźnik do klasy bazowej, który pokazuje na obiekt klasy bazowej (a nie pochodnej) i wywołam funkcję wirtualną to czy stracę na wydajności?
  4. No i ostatnie pytanie: dlaczego w javie mogą być wszystkie funkcje virtualne i nie powoduje to utraty wydajności a w C++ ma to negatywny skutek na działanie aplikacji? W jaki sposób radzi sobie z tym Java, że jest lepsza od natywnego C++? A może to C++ ma mało wydajnie to zaimplementowane?

Z góry dzięki za odpowiedzi na moje wątpliwości.
pozdrawiam

2

1,2,3 Bardzo nieznacznie. Pierwsza różnica będzie właściwie tylko taka że raz musisz dereferować wskaźnik a raz nie. Różnica w narzucie na wywołanie metody wirtualnej będzie bardzo niewielka, związana raczej z tym że kompilator nie może sobie tego wygodnie zinlinować ani zoptymalizować kodu bo decyzja o tym którą funkcję wykonać podejmowana jest w czasie wykonania a nie kompilacji.
4. Java jest językiem pół-interpretowanym i ma kompilator JIT wbudowany w maszynę wirtualną, w efekcie w Javie można optymalizować kod w czasie wykonania. W C++ takiej możliwości nie ma, bo kod jest kompilowany do kodu maszynowego i wykonywany bezpośrednio przez procesor. To nie kwesta optymalnej implementacji tylko zupełne innego mechanizmu działania.

0

dzięki za wyjaśnienie ;-)

1

dlaczego w javie mogą być wszystkie funkcje virtualne i nie powoduje to utraty wydajności
W Javie masz utratę wydajności już na dzień dobry ze względu na maszynę wirtualną. Prędkość nie jest głównym celem javy, więc nikomu nie będzie przeszkadzało jeśli wszystkie funkcje będą wirtualne.
C++ ma ambicje bycia najszybszym na świecie i takie coś miałoby negatywny wpływ (nawet jeśli niemierzalny) na wydajność programu.
Co prawda C++ daje ciała na innym polu, radośnie kopiując sobie obiekty na prawo i lewo gdy nikt o to nie prosi...

0

@Azarien
"Co prawda C++ daje ciała na innym polu, radośnie kopiując sobie obiekty na prawo i lewo gdy nikt o to nie prosi..."
Mógłbyś rozwinąć?

0

@pingwindyktator standardowa metoda przekazywania obiektów w C++ to kopiowanie. Jak argumentem funkcji jest np. vector<> to ten vector zostanie skopiowany, co bywa bolesne. Dlatego trzeba pamiętać o tym żeby czasem dopisać & za argumentem ;)

0

Właśnie się zastanawiałem, czy chodzi o to, czy może o coś jeszcze innego. Ale w takim razie c++ dostarcza nam mnóstwo narzędzi, by tego unikać, wiec jak ktoś z tego nie korzysta to trochę na swoje własne życzenie. Nawet kompilator nieraz przypomni, że przekazujemy obiekt klasy przez wartość. Swoją drogą na pewno optymalizator nie może tego zmienić? Skoro widzi, że w funkcji "nie tykamy" obiektu.

1

W Javie niby jest coś na wzór metod niewirtualnych, np:

  • funkcje statyczne - są one zawsze niewirtualne,
  • funkcje finalne, które nie nadpisują żadnej z funkcji z dziedziczonych klas (w szczególności wliczają się w to funkcje prywatne),
  • dostęp do statycznych pól w klasie,
  • dostęp do pól obiektu bezpośrednio (bez getterów/ setterów),

Generalnie referencyjna (Oraclowa) JVMka ma świetnie zrobioną dewirtualizację i praktycznie nie ma szans, by narzut na wywołania wirtualne był większy niż w C++, no chyba, że w C++ kompilujesz z PGO, a w Javie mierzysz wydajność przed sprofilowaniem w locie.
Mam wrażenie, że w C++ programiści unikają metod wirtualnych jak ognia jeśli chodzi o miejsca gdzie wydajność jest ważna, tymczasem gdy Javowcy się tym jakoś mocno nie przejmują bo JVMka i tak sobie nieźle radzi.

1 użytkowników online, w tym zalogowanych: 0, gości: 1