amiga-news ENGLISH VERSION
.
Links| Forum| Kommentare| News melden
.
Chat| Umfragen| Newsticker| Archiv
.

amiga-news.de Forum > Programmierung > GCC/G++ Anfängerprobleme die 2. [ - Suche - Neue Beiträge - Registrieren - Login - ]

-1- [ - Beitrag schreiben - ]

02.02.2005, 08:22 Uhr

Reth
Posts: 1858
Nutzer
Schönen Tach nochmals,

hab mal wieder Probleme mit besagten Tools.

Das Compilieren der einzelnen Klassen aus dem Makefile heraus klappt hervorragend, die Objekte werden erzeugt.
Aber dann versagt das Linken.

An einigen Stellen meint ld: undefined reference auf asl und graphics.
Das kann daran liegen, dass ich im Code vergessen habe die Libraries zu öffnen, aber deren Funktionen verwende. Das lässt sich beheben.

Was ich aber nicht verstehe ist folgendes:

Ich habe 2 Klassen A und B. A wird in B verwendet, es soll ein Objekt vom Typ A zur Laufzeit erzeugt werden. A hat einen parameterlosen Konstruktor und einen mit Parameteren. Der parameterlose Konstruktor ist dafür, dass der Compiler zufrieden ist, da bei C++ anscheinend beim Erstellen eines Objektes welches weitere Objekte erzeugt (in meinem Fall beim Erstellen von B) immer auch der Konstruktor der inneren Objekte gerufen wird (hab ich aus einem umfassenden C++ Tutorial), so dass zur Compilezeit schon geprüft wird. In meinem Fall wird in B ein Objekt vom Typ A erzeugt (wenn ichs gerad genau weiss, sogar im Konstruktor von B), darum prüft der Compiler, ob es von A einen paramterlosen Konstruktor gibt, da ich A nicht mit : hinter den Konstruktoraufruf von B gesetzt habe.

Soweit so gut. Nun sind beide Klassen in eigenen Headerdateien deklariert, wobei der Header von B den von A inkludiert und das Sourcefile von B den Header von B (das Sourcefile von A natürlich den Header von A).
Damit ist der Compiler zufrieden, kennt alles und erzeugt Objektfiles.
Der Linker jedoch mosert rum, dass es in B bei text+0x40 (oder so) eine "undefined reference to A()" gibt und bei text+0x41 eine "undefined reference to A(param1, param2, ...).
Warum das denn? Was fehlt da noch? muss ich ausser der -I Option beim g++ noch ne Option beim Linker angeben, wo er die Objektdateien findet?
Muss man libamiga oder ähnliches angeben, damit der die OS-Libraries u.dgl. findet?

Fragen über Fragen.

Wenn die Fragen zu blöd, lächerlich, offensichtlich etc. sind, wäre ich auch für ein paar weiterhelfende Links auf Tutorials, FAQ, häufige Probleme mit GCC und Konsorten, etc. dankbar!

Ciao

[ - Antworten - Zitieren - Direktlink - ]

02.02.2005, 10:41 Uhr

Solar
Posts: 3680
Nutzer
Zu wenig Informationen.

Wie sieht Deine Kommandozeile aus, mit der Du den Fehler reproduzierst?

Und... "innere Objekte" und "erzeugen von A im Konstruktor" riecht ziemlich faul. Kannst Du den fraglichen Quellcode hier mal posten?

[ - Antworten - Zitieren - Direktlink - ]

02.02.2005, 19:03 Uhr

Reth
Posts: 1858
Nutzer
Zitat:
Original von Solar:
Zu wenig Informationen.

Wie sieht Deine Kommandozeile aus, mit der Du den Fehler reproduzierst?


Einfach nur make aus dem GoldEd mittels Rexx Script. Das Makefile sieht so aus:

projectPath = <Pfad<

ScreenMode : ScreenModeRequestC.o ScreenModeDataC.o ScreenModeHookC.o ScreenMode.o
g++ -I $(projectPath) -o SCreenMode ScreenModeRequestC.o ScreenModeHookC.o ScreenMode.o

ScreenMode.o : ScreenMode.cc ScreenModeRequestC.h ScreenModeHookC.h
g++ -I $(projectPath) -c ScreenMode.cc
ScreenModeRequestC.o : ScreenModeRequestC.cc ScreenModeRequestC.h ScreenModeDataC.h
g++ -I $(projectPath) -c ScreenModeRequestC.cc
ScreenModeDataC.o : ScreenModeDataC.cc ScreenModeDataC.h
g++ -I $(projectPath) -c ScreenModeDataC.cc
ScreenModeHookC.o : ScreenModeHookC.cc ScreenModeHookC.h Constants.h
g++ -I $(projectPath) -c ScreenModeHookC.cc

clean :
delete ScreenModeHookC.o ScreenModeDataC.o ScreenModeRequestC.o ScreenMode.o

Zitat:
Und... "innere Objekte" und "erzeugen von A im Konstruktor" riecht ziemlich faul. Kannst Du den fraglichen Quellcode hier mal posten?

Hier der Header von besagter Klasse A:

#include <exec/types.h>

class ScreenModeDataC
{
public:
ScreenModeDataC();
ScreenModeDataC(ULONG width, ULONG height, ULONG depth, ULONG id);

ULONG getWidth() {return displayWidth;};
ULONG getHeight(){return displayHeight;};
ULONG getDepth() {return displayDepth;};
ULONG getID() {return displayID;};

private:
ULONG displayWidth, displayHeight, displayDepth, displayID;
};

und hier der von B:

#include <utility/hooks.h>
#include <libraries/asl.h>
#include <clib/asl_protos.h>

#include <ScreenModeDataC.h>

class ScreenModeRequestC
{
public:
ScreenModeRequestC(UWORD minWidth, UWORD minHeight, UWORD minDepth, UWORD maxWidth, UWORD maxHeight, UWORD
maxDepth, struct Hook *filterFunc);

ScreenModeDataC getScreenModeData();

private:
ScreenModeDataC scrMDData;
};


Implementierung von A:

#include <ScreenModeDataC.h>

ScreenModeDataC::ScreenModeDataC()
{
displayWidth = 0;
displayHeight= 0;
displayDepth = 0;
displayID = 0;
}

ScreenModeDataC::ScreenModeDataC(ULONG width, ULONG height, ULONG depth, ULONG id)
{
displayWidth = width;
displayHeight= height;
displayDepth = depth;
displayID = id;
}

und von B:

#include <libraries/asl.h>
#include <clib/asl_protos.h>

#include <ScreenModeRequestC.h>

ScreenModeRequestC::ScreenModeRequestC(UWORD minWidth, UWORD minHeight, UWORD minDepth, UWORD maxWidth, UWORD maxHeight,
UWORD maxDepth, struct Hook *filterFunc)
{
struct ScreenModeRequester *scrMDRQ = (struct ScreenModeRequester *)AllocAslRequestTags(ASL_ScreenModeRequest,
ASLSM_InitialInfoOpened, TRUE,
ASLSM_DoWidth, TRUE,
ASLSM_DoHeight, TRUE,
ASLSM_DoDepth, TRUE,
ASLSM_DoOverscanType, TRUE,
ASLSM_DoAutoScroll, TRUE,
ASLSM_MinWidth, minWidth,
ASLSM_MaxWidth, maxWidth,
ASLSM_MinHeight, minHeight,
ASLSM_MaxHeight, maxHeight,
ASLSM_MinDepth, minDepth,
ASLSM_MaxDepth, maxDepth,
ASLSM_FilterFunc, filterFunc,
ASLSM_PopToFront, TRUE,
ASLSM_Activate, TRUE, TAG_DONE);

if ((scrMDRQ != NULL) && (AslRequestTags(scrMDRQ, TAG_END)))
{
scrMDData = ScreenModeDataC(scrMDRQ->sm_DisplayWidth, scrMDRQ->sm_DisplayHeight, scrMDRQ->sm_DisplayDepth,
scrMDRQ->sm_DisplayID);
}
}

ScreenModeDataC ScreenModeRequestC::getScreenModeData()
{
return scrMDData;
}


Wie gesagt, es fehlen das Öffnen der Libs und noch ein paar andere Klassen. Aber um die beiden gehts erstmal.

Ausgabe von make:

ScreenModeRequestC.o(.text+0x40): undefined reference to 'ScreenModeDataC::ScreenModeDataC(void)'
ScreenModeRequestC.o(.text+0x14a): undefined reference to 'ScreenModeDataC::ScreenModeDataC(unsigned long, unsigned long, unsigned long, unsigned long)'


Keine Ahnung was fehlt? Das Einzige, was ich mir vorstellen kann, ist dass er die Objektdateien nicht findet! Oder isses was anderes?

[ - Antworten - Zitieren - Direktlink - ]

02.02.2005, 21:34 Uhr

Reth
Posts: 1858
Nutzer
Hab das Problem gelöst, es fehlte ScreenModeData.o im makefile.

Was muss ich denn angeben, damit er die Objektdateien der Amigalibs findet? Diese namentlich im makefile?

Danke schon mal für die bisherigen und evtl. weiteren Hilfen!
Ciao

[ - Antworten - Zitieren - Direktlink - ]

02.02.2005, 21:48 Uhr

Dr_X
Posts: 24
Nutzer

LDFLAGS = -L. -lamiga

--
(Amiga) µA1-C in A1000 Gehäuse aber mit Amiga OS4.0 pre

[ - Antworten - Zitieren - Direktlink - ]

03.02.2005, 07:59 Uhr

Reth
Posts: 1858
Nutzer
Zitat:
Original von Dr_X:

LDFLAGS = -L. -lamiga

--
(Amiga) µA1-C in A1000 Gehäuse aber mit Amiga OS4.0 pre


Danke! Schreib ich das einfach so ins Makefile oben rein, oder kommt das als Option an den G++ Aufruf?


[ - Antworten - Zitieren - Direktlink - ]

03.02.2005, 09:16 Uhr

gni
Posts: 1106
Nutzer
Zitat:
Dr_X:
LDFLAGS = -L. -lamiga

Wozu soll "-L." gut sein? Und wenn es um den GCC von GG geht, da wird automatisch mit -lamiga gelinkt.

[ - Antworten - Zitieren - Direktlink - ]

03.02.2005, 09:28 Uhr

gni
Posts: 1106
Nutzer
Zitat:
Reth:

und hier der von B:

#include <utility/hooks.h>
#include <libraries/asl.h>
#include <clib/asl_protos.h>

Die asl Header brauchts Du hier nicht.
Zitat:
ScreenModeDataC getScreenModeData();
Dir ist hoffentlich bewußt, daß Du hier ein Objekt zurückgibst. Vermutlich solltest Du ein const Referenz verwenden.
Zitat:
ScreenModeRequestC::ScreenModeRequestC(
if ((scrMDRQ != NULL) && (AslRequestTags(scrMDRQ, TAG_END)))
}

Sowas in einem Konstruktor zu machen ist unklug, zumal Du keine Exception benutzt. Du erzeugst also ein Objekt, das unbenutzbar ist.

[ - Antworten - Zitieren - Direktlink - ]

03.02.2005, 10:38 Uhr

Reth
Posts: 1858
Nutzer
Danke für Deine Tips!

Noch ein paar Fragen.

Zitat:
Original von gni:
Zitat:
Reth:
ScreenModeDataC getScreenModeData();

Dir ist hoffentlich bewußt, daß Du hier ein Objekt zurückgibst. Vermutlich solltest Du ein const Referenz verwenden.

Das ist ne Sache, die ich an C++ noch nicht ganz verstanden habe. Zeiger unterscheiden sich ja von Referenzen, aber der Unterschied ist mir nicht so ganz klar. Zeiger sind ne Datenstruktur, mit der man z.B. auch rechnen kann, Referenzen sind ...?

Bei Java ist das einfacher, da sind alle Objekte Zeiger (ausser Strings).

Gibts denn ein gutes C++ Standardwerk, wo man die ganzen Sachen schön differenziert erklärt bekommt, auch Exceptions in C++?
Soviel weiss ich, dass wenn man in C++ ein Objekt einer Methode übergibt, eine Kopie des Objektes angelegt wird.

Bei Referenzen ist mir das nicht so ganz klar. Wenn ich nun ein Objekt in einer Klasse erzeuge und eine Referenz darauf einer aufrufenden Klasse zurückgebe. Wie lang ist diese Referenz dort dann gültig? Wass passiert mit der Referenz in der aufrufenden Klasse, wenn das Objekt, aus dem die Referenz zurückgegeben wurde out of scope geht?

Zitat:
Zitat:
ScreenModeRequestC::ScreenModeRequestC(
if ((scrMDRQ != NULL) && (AslRequestTags(scrMDRQ, TAG_END)))
}

Sowas in einem Konstruktor zu machen ist unklug, zumal Du keine Exception benutzt. Du erzeugst also ein Objekt, das unbenutzbar ist.

Darum hab ich auch schon nachgedacht, einen Zeiger auf das Objekt zurückzugeben, welcher dann NULL ist, wenn das Objekt nicht richtig erstellt werden konnte!

[ - Antworten - Zitieren - Direktlink - ]

03.02.2005, 20:43 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von Reth:
Bei Java ist das einfacher, da sind alle Objekte Zeiger (ausser Strings).

Falsch. In Java sind alle Objekte Referenzen. Und Strings bilden keine Ausnahme.
Zitat:
Bei Referenzen ist mir das nicht so ganz klar. Wenn ich nun ein Objekt in einer Klasse erzeuge und eine Referenz darauf einer aufrufenden Klasse zurückgebe. Wie lang ist diese Referenz dort dann gültig?
So lange wie Du sie benutzt. Wenn Du sie z.B. einer Variablen zuweist, dann ist sie genauso lange gültig, wie diese Variable gültig ist. Steckst Du sie direkt in einen anderen Methoden-/Funktionsaufruf, ist sie halt für die Dauer dieses Aufrufs gültig.
Zitat:
Was passiert mit der Referenz in der aufrufenden Klasse, wenn das Objekt, aus dem die Referenz zurückgegeben wurde out of scope geht?
Wo das Objekt herkommt spielt keine Rolle. Solange die Referenz im scope ist, ist sie auch gültig.
Ist doch gar nicht so schwer. Ist doch eigentlich genau so wie in Java :D

mfg
--
Good coders do not comment. What was hard to write should be hard to read too.

[ - Antworten - Zitieren - Direktlink - ]


-1- [ - Beitrag schreiben - ]


amiga-news.de Forum > Programmierung > GCC/G++ Anfängerprobleme die 2. [ - Suche - Neue Beiträge - Registrieren - Login - ]


.
Impressum | Datenschutzerklärung | Netiquette | Werbung | Kontakt
Copyright © 1998-2024 by amiga-news.de - alle Rechte vorbehalten.
.