Inteligentne linkowanie

0

Witam,

chciałbym się dowiedzieć, czy da się zrobić tak (lub raczej: jak to zrobili autorzy bibliotek std), ażeby plik, który zawiera zarówno deklaracje jak i definicje- mógł być załączany do wielu plików w jednym projekcie nie wywołując błędu linkera (że taka a taka funkcja/zmienna została już zdefiniowana).

Można spytać:
po co? przecież od tego jest plik nagłówkowy *.h i *.cpp.

Tak, ale sprawa się komplikuje w przypadku użyciu szablonów.
Rozdzielenie klasy na plik nagłówkowy i definicje w innym pliku (cpp) powoduje zazwyczaj błąd (unresolved external symbol).

Poza tym w przypadku małych klas, które używamy w wielu projektach.. bez sensu jest kompilować statycznego lib'a i załączać 1kb do projektu za każdym razem :|

Zauważcie: jak używacie bilbiotek std::vector czy std::string i innych.. Każdy z tych plików zawiera zarówno deklaracje jak i definicje (wystarczy otworzyć te pliki). Załączamy je w dowolnych plikach, a mimo to nie powoduje to błędu.

I moje pytanie brzmi:
Czy ktoś wie jak to osiągnąć?

0

Az sam sprawdzilem czy rzeczywiscie te pliki az takie wyjatkowe sa jak piszesz, ale niestety nie ;(

#ifndef blablabla
#define blablabla
<tutaj zawartosc>
#endif // blablabla
0

No właśnie nie.. kiedyś myślałem, że ten "trik" tak samo jak #pragma once rozwiązuje problem jednakże..

te triki zapewniają jedynie, że dany plik nagłówkowy nie zostanie załączony podczas kompilacji DANEGO pliku .cpp więcej niż raz,
jednakże są załączane "po razie" do każdego pliku .cpp w projekcie.

a zatem każdy skompilowany plik cpp zawiera identyczne definicje, stąd- przy linkowaniu error: "already defined in.. "

jednakże właśnie te standardowe biblioteki jakoś się wycwaniły.

W książce z której uczyłem się c++ był podobny problem, i pisał tam (pan Grębosz- Pasja) iż stosuje się tzw. smart linking- linker widząc dwie identyczne definicje, po prostu jedną ignoruje.
Jednakże w visualu 2010 nigdzie się tej opcji nie mogę doszukać :|

0

Masz racje, ale w kodzie nic nie widac na temat jakichs sprytnych rozwiazan.

Edit: Szablony mozna dolaczac wielokrotnie po prostu, ze wzgledu na czas ich konkretyzacji.

0

Przed funkcjami dołączasz inline, nawet jeżeli kompilator to zignoruje to i tak możesz dołączyć taką funkcję wielokrotnie.

0

Tak, ale sprawa się komplikuje w przypadku użyciu szablonów.
Twój problem nie istnieje. Pokaż może kod, który ci nie działa ;-)

Czy ktoś wie jak to osiągnąć?
Nie trzeba niczego osiągać. Samo działa.

0

Ok. widzę o co chodzi :p
plik vectora jest tak rozwleczony, że nie zauważyłem, iż wszystkie funkcje definiowane są w ciele klasy.. Dlatego nie ma problemu z wielokrotnym linkowaniem.

jednakże da się coś zrobić w przypadku statycznych obiektów w klasie (muszą być zdefiniowane poza klasą), tak żeby uniknąć podziału na plik *.cpp tej klasy?

czym to motywuje?
prostotą dołączania takich "klas", nie trzeba ściągać lib'ów dla niej, szczególnie jeśli klasa jest mała, i plik cpp składałby się z kilku linijek :p

Nie słyszał ktoś z Was o opcji "smart linking" lub coś w tym rodzaju? Że linker po prostu igronuje powtarzające się (identyczne) definicje?

Azarien,
mam tak w każdym projekcie, jeśli funkcje szablonowe definiuje w odrębnym pliku .cpp, co używając potem tej klasy dostaje błąd "unresolved external symbol"- nie widzi definicji tych funkcji.

przykład, tylko tak symbolicznie:
plik class.h

template <class A>
class ALFA {
 A  liczba;
 A  funkcja();
};

plik class.cpp

#include "class.h"

template <class A>
A
ALFA<A:: funkcja() {
 return liczba;
}

plik main.cpp

#include "class.h"
...
ALFA<int>  p;
p.funkcja();

podczas kompilacji błąd- niezdefiniowana funkcja

0

Azarien,
mam tak w każdym projekcie, jeśli funkcje szablonowe definiuje w odrębnym pliku .cpp, co używając potem tej klasy dostaje błąd "unresolved external symbol"- nie widzi definicji tych funkcji.

Nie rozumiem cię, albo ty mnie nie rozumiesz.
Miałem na mysli, że definicja funkcji szablonowej w pliku .h nie powoduje błędu linkera o wielokrotnej definicji.

0

hm.. nie rozumiemy się nawzajem :p
w pierwszy poście jako "komplikacja" napisałem, że właśnie chodzi mi o rozdzielenie klasy na dwa pliki- .h i .cpp, co powoduje błąd "unresolved external symbol",
dlatego tak zależy mi, ażeby znaleźć sposób na "upakowanie" klasy szablonowej w jednym pliku i ominięcia błędu linkera, a raczej powiedzenie mu:
że powtarzające się definicje ma po prostu pominąć.. a nie częstować mnie FATAL ERROR'em :D

Jerzy Grębosz w swojej książce Pasja (tom 1) opisał dokładnie ten sam problem w rozdziale "Jak rozmieszczać w plikach szablony klas." jeśli ktoś ma, tam jest dokładnie pokazane o co chodzi.. I jako rozwiązanie jest podane ustawienie opcji "smart" w linkerze.
Jednakże nigdzie tego nie mogę znaleźć w VC10 :(

PS przepraszam za nie umieszczenie tak ładnego kodu :p nie wiedziałem o tym : (

0

w pierwszy poście jako "komplikacja" napisałem, że właśnie chodzi mi o rozdzielenie klasy na dwa pliki- .h i .cpp, co powoduje błąd "unresolved external symbol"
W przypadku szablonów tak się właśnie dzieje, a przyczyna jest dość skomplikowana.

dlatego tak zależy mi, ażeby znaleźć sposób na "upakowanie" klasy szablonowej w jednym pliku
No i tak najlepiej zrobić...

i ominięcia błędu linkera, a raczej powiedzenie mu:
że powtarzające się definicje ma po prostu pominąć..
Jakiego błędu, nie ma żadnego błędu. To chciałem powiedzieć, że w przypadku szablonów tak można zrobić, bez żadnego kombinowania.

a nie częstować mnie FATAL ERROR'em
Pokaż kod. Twój problem polega najprawdopodobniej na czymś innym, a czepiłeś się biednego linkera.

0

@Azarien: to, że nie ma błędu to rzeczywiście kwestia linkera. Nie wiem co mówi o tym standard, ale pewnie tyle, ze "jakoś trzeba zrobić, żeby to działało". A może nie mówi nic. Linker ld rozwiązuje to tak, że symbole związane z szablonami są oznaczone jako weak symbols co powoduje, że napotkanie wielu takich samych symboli podczas linkowania nie powoduje błędu. Gdyby te symbole oznaczone były by jako normalne symbole wtedy błąd o wielokrotnej definicji z pewnością by się pojawił.

Oczywiście w ld nie trzeba niczego konfigurować, żeby to działało, podejrzewam że nigdzie indziej też nie. Autor zapewne popsuł coś innego...

0

Macie rację, musiałem popsuć coś innego ;|
napisany przykład na szybko.. działa.

No nic, ważne, że dowiedziałem się, iż typowana przyczyna błędu jest nieprawdziwa i kwestia leży po mojej stronie, i.. w takim razie- jest do rozwiązania :)
W wolnej chwili znów "popsuję" kod i będę wiercił (bo obecnie zastosowałem kompromis.. program upakowany w jeden plik cpp, zatem nie ma żadnych redefinicji ;x ).

Dzięki za odpowiedzi : )

0

to, że nie ma błędu to rzeczywiście kwestia linkera. Nie wiem co mówi o tym standard, ale pewnie tyle, ze "jakoś trzeba zrobić, żeby to działało"
Standard mówi, że program ma działać. Samo istnienie linkera, jako osobnego od kompilatora programu, to szczegół implementacji danego kompilatora.

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