Problem med statiska bibliotek (C++)

Permalänk
Medlem

Problem med statiska bibliotek (C++)

Hej. Jag har ett litet projekt med diverse underprojekt, där projekten är beroende av varandra.

Det finns en superklass Object som alla andra klasser ärver. Men t ex Object har metoder som returnerar objekt av subklasstyper. Detta ger en del småkrångliga beroenden som jag inte lyckas ta mig ur. Det fungerar men jag får en faslig massa meddelanden som t ex:

Exception.lib(Character.obj) : warning LNK4006: "public: __thiscall Character::Character(char)" (??0Character@@QAE@D@Z) already defined in Character.lib(Character.obj); second definition ignored

Hur kommer jag ifrån det här?

(Detta är i VC .NET)

Visa signatur

//Sami

Permalänk

Det är inte helt lätt. Börja med att sätta upp enklast möjliga projekt så är det lättare att se vad som går fel. Gör ett workspace som innehåller två projekt, ett statiskt lib (till skillnad från en dll med ett länk-lib till, för det är väl så du har?) och en exe som använder lib:et. Förslagsvis kallar du dessa "lib" (som resulterar i det fantasifulla lib.lib) respektive "exe".

Din katalogstruktur blir ju då typ:
c:\temp
c:\temp\lib
c:\temp\exe

Sedan lägger du till en klass "CFoo" i lib:et (foo.h/foo.cpp), som du senare ska använda från din exe. Både lib:et och exe:n måste då förstås inkludera "..\inc\foo.h".

Först ska vi se till att bryta loss det som är gemensamt i en inc-katalog, så skapa:
c:\temp\inc
och flytta foo.h (som är det enda gemensamma) dit.

I din exe ska du nu använda CFoo, så inkludera foo.h från din main-fil och låt din main se ut såhär:

int main() { CFoo foo; return 0; }

När då fått upp den strukturen är det lättare att tala om vad som går fel, eftersom vi har en gemensam kod att prata om.

Permalänk
Medlem

Projektet är redan rätt stort

Problemet kommer när två (eller fler) statiska lib är beronede av varandra. Jag hittar inget sätt att få länkaren att förstå att saker o ting redan är definierade. Det går igenom, men man kan ju får en hel del varningar. Det större problemet är att varje lib-fil som skapas verkar innehålla alla lib-filer som skapats hittills. Så om min "solution" har 5 projekt som alla skapar varsin lib-fil, blir den sista lätt stor =(

Men visst, jag skapade det du ville

Visa signatur

//Sami

Permalänk

Korsberoende är verkligen det du borde satsa på att få bort, man ska höra varningsklockorna ringa så fort man har ett korsberoende. Jag menar det verkligen, du kommer aldrig få rätsida på dina problem annars. Försök bryta ut beroende sakerna i ett tredje bibliotek istället.

Permalänk
Medlem

developer erhåller ett MYCKET starkt medhåll.
Du kommer att få ett problem varje gång du gör någon ändring på något av libarna och när du kompilerar om produkten.
Tänk alltid att beroendena skall bilda ett träd där beroendena alltid är mot de yttersta löven, aldrig in mot stammen.

Edit:
Detta gäller instantierande objekt. När det gäller klasshirearkier är beroendet på andra hållet.

Visa signatur

/ Assar

Permalänk
Medlem

Situtationen: (fin UML va? )

--------------- | Object | --------------- ^ | | --------------- | StringConst | ---------------

Object (superklass) har en metod som returnerar en StringConst*

Går det att ordna utan att dra in fler klasser && komma undan tidigare diskuterade problem...?

Visa signatur

//Sami

Permalänk
Medlem

Förstår jag dig rätt?:
StringConst ärver Object som i sin tur returnerar en StringConst.

Är det så så bör du ha någon virtuell metod i Object som returnerar ett Object. Denna metod skall du överrida i ditt arv.

Edit alternativ:
Du har en lista i Object som du vill returnera StringConst från:
Lagra då dina StringConst som Object då de i arvet också är sådana. Du får då ur metoden ett Object som du dynamiskt kan typecasta till StringObject.

Visa signatur

/ Assar

Permalänk
Medlem

Japp StringConst är ett Object. Alla klasser har metoden toString() som returnerar ett StringConst (precis som i java).

Visa signatur

//Sami

Permalänk
Medlem

Har du provat de förslag jag angav?
Använd virtuella metoder.
Själv skulle jag nog bygga en templatefunktion av toString och inte lägga den i alla klasser, det blir mer allmängiltigt.

Visa signatur

/ Assar

Permalänk
Medlem

Tack för er hjälp!

Jag började lite med ett nytt projekt. Där finns inte dessa cirkulära beroenden. Men det räcker tydligen med mycket mindre för att dessa "already defined in xy.lib" ska hemsöka mig.

Säg att jag har en klass DXError som finns i en lib-fil, DXError.lib. Sen har jag en klass DXWindow, som använder DXError. DXWindow finns förstås i DXWindow.lib. Men varför i hela friden måste DXError.lib includeras in i DXWindow.lib? Kan de inte bara finnas sida vid sida? Det är ju därför som dessa fel kommer... Hur kommer jag runt det?

Visa signatur

//Sami

Permalänk
Medlem

Förmodligen inkluderar du h-filen i andra h-filer och får då dubbla defenitioner. Prova att skriva följande:

#ifndef XXXXX_H #define XXXXX_H .... #endif

Där XXXXX är h-filens namn. På detta vis kommer definitionerna inte att återkomma hur många gånger du än inkluderar h-filen.

Dessutom skulle jag tro att du placerat kodgenererande saker i din h-fil.

Visa signatur

/ Assar

Permalänk
Medlem

Jag använder alltid tillvägagångssättet ovan. Men lib-filerna tar jag inte med genom headerfilerna.

Dock löste sig problemet av nån skum anledning. Jag tog bara bort lib-filen från "Additional dependencies" i DXWindow-projektet, så funkade det... konstigt dock att den klagade på motsatsen INNAN jag skrev in den där... jaja, nu fungerar det iaf!

Tackar så mycket

Visa signatur

//Sami