mam pytanie odnośnie funkcji inline a ich typu linkage. W standardzie C++ jest napisane (7.1.1.7):
Jak widać wg tego, funkcja inline ma external linkage.
A dlaczego nie internal linkage :?: Wg mnie powinno tak być z 2 powodow:
- dzięki external linkage możemy korzystać z funkcji w 2 albo więcej plikach. Jeżeli kompilator rzeczywiście spełni prośbę z inline (czasem może nie spełnić) to ta funkcja zostanie wklejona w miejsce wywołań, a sama zniknie -dzieki temu nie będzie widoczna w drugim pliku i linker wyświetli błąd.
- nawet jakby linker tej prośby nie spełnił i funkcja nie będzie inline, to to słowo dalej zostanie. Dla osób nie wiedzących że inline jest external linkage,będzie wydawał się dziwny taki zapis z funkcją inline 2 dwoch plikach…
niemożliwe - nie możesz używać funkcji w jednostce translacji, w której nie ma deklaracji funkcji (np. z nagłówka). inline, natomiast, wymusza wtedy użycie pełnej definicji (w każdym miejscu identycznej) funkcji, więc siłą rzeczy - opisana sytuacja nie może mieć miejsca.
Nie musi być w każdym pliku identyczna (sprawdzone w g++).
Ale to fakt - definicja musi być w każdym pliku. Jeżeli w jednym dam deklarację a w drugim definicję to w tym pierwszym wyświetli się błąd o nieznalezieniu funkcji.
// file: def.h
#ifndef _DEF_H_
#define _DEF_H_
inline /* static */ int foo() // mozliwy wariant ze static
{
static int i = 0;
return i++;
}
#endif
// file: bar.cpp
//#include "def.h"
inline int foo() // wykomentuj i odkomentuj wyzej, aby uzywac starej definicji foo()
{
static int i = 0;
return i--;
}
int bar()
{
return foo();
}
// file main.cpp
#include
#include "def.h"
extern int bar();
int main()
{
for (int i = 0; i < 5; ++i)
{
foo();
bar();
}
std::cout << foo() << std::endl;
std::cout << bar() << std::endl;
return 0;
}
kompiluj za pomocą:
g++ -Wall -pedantic main.cpp bar.cpp -o main
Prześledź różne warianty. Rezultat jest ciekawy w przypadku, kiedy g++ “dopuszcza” różne definicje foo() (kiedy ta ma external linkage) - wtedy tak naprawdę, wybierana jest podczas linkowania tylko definicja z pliku def.h, pomimo, że podczas kompilacji bar.cpp znana jest zupełnie inna definicja foo().
OK skoro [alex] powiedział ze g++ tutaj nie respektuje standardu to nie drążmy już tego tematu
Podsumowując: funkcja inline musi być zdefiniowana za każdym razem kiedy chcemy jej użyć w danej jednostce translacyjnej i ta definicja musi być taka sama. Konflikt nie wystąpi (jak kompilator odrzuci prosbę o inline) pomimo external linkage.
Ostatnie zdanie jest bardzo logiczne ^.^ - ale to już zasługa twórcow. Nie było by tego tematu gdyby inline była po prostu static…
static jest widoczny tylko w jednej swojej jednostce translacyjnej. Czyli w każdym pliku może być inna funkcja o tej samej nazwie oraz tymi samymi parametrami.
Nie zupełnie. Bo inline to prawie jak static (musi być również zdefiniowana przed miejscem wywołania) dopóki z jakieś racji kompilator nie zdecyduje na rezygnacje z jej inline’ości wtedy to już normalna funkcja - nie static, z tym że nie daje ostrzeżeń o dublowaniu i berze pierwszą lepszą z nich (jeżeli jest ich kilka).
Kto powiedział że muszą być takie same? Wcale nie muszą. W każdym pliku możesz mieć inną funkcje inline o tej samej nazwie. O ile kompilator obsługuje te inline to będzie w każdym pliku inna funkcja wykonywana. Ale jak kompilator z jakiś przyczyn “anuluje” inline to traktuje to jako normalną funkcje. A linkier we wszystkich takich miejscach podstawi pierwszą lepszą co właściwie przydarzyło się flash4gordon’owi kiedy która funkcją się wykona zależało od kolejności linkowania.
No właśnie pierwszą lepszą… Lepiej więc robić tak jak mowi standard - takie same funkcje inline, i wtedy nie musimy sie zastanawiac która wygra w losowaniu, jezeli inline nie zostanie wzięte pod uwage…
Wygląda na to że w tej dyskusji absolutnie nic nie zrozumiałeś. Dopóki masz przyzwoite funkcje inline a kompilator ich obsługuje to wszystko gra.
Co do standardu - Nie masz szans dopilnować żeby pisząc jakiś program nie użyć jakieś nazwy dla funkcji inline która przypadkiem została użyta w jednej z dziesięciu bibliotek które dołączyłeś do programu.
zatem g++ respektuje tu standard, ponieważ wcale nie musi respektować inline.
Dlatego warto używać static (internal linkage) lub własnych przestrzeni nazw. Przecież nie będziesz sprawdzał co kompilację, czy kompilator przypilnował inline czy nie.
Nie mam szans, ale taki błąd zostanie wychwytany przez kompilator - nie mogą istnieć chyba 2 funkcje o tej samej nazwie w tym samym pliku, prawda ? Więc problem praktycznie nie istnieje, bo nazwe szybko zmienimy na jakas inna, nie wchodzaca w konflikt…