Klassen über Header verbunden funktionieren nicht wie sie sollen...
-
Hi,
ich wollte mich grade einw enig in Headerdateien und so einarbeiten und habe dazu eine Klasse "Testprogram" mit Header und .cc Teil programmiert. Ein Objekt erstelle ich dann in der Datei start.cc, hier sind die Dateien:
Testprogramm.hh:
#include <iostream> #include <cstdio> using namespace std; class Testprogram { public: Testprogram(); void ausgabe(); };
#include <iostream> #include <cstdio> #include "Testprogram.hh" using namespace std; void Testprogram::Testprogram() { cout<<"ich wurde erstellt!"<<endl; } void HotEnergy::ausgabe() { cout<<"Und die Ausgabe funktioniert auch!"<<endl; }
#include "Testprogram.hh" using namespace std; int main() { Testprogram objekt1; objekt1.ausgabe(); }
aber wenn ich kompelieren möchte bekomme ich immer den Fehler:
undefenied reference to...
wo ist mein Denkfehler?
danke schon mal
Liebe Grüße
Laura
-
Schau dir mal deine Ausgabefunktion an. Deine Klasse hats Testprogramm und dort steht
void HotEnergy::ausgabe(){ //.. } // muestte aber: void Testprogramm::ausgeben(){ //.. } // geschrieben werden
Die Klasse HotEnergy kennt dein Programm nicht.
-
Prometheus87 schrieb:
Testprogramm.hh:
[cpp]
#include <iostream>
#include <cstdio>using namespace std;
Nein und nein. Include-Guards fehlen und ein using namespace std; hat in einem Header auf globaler Ebene nichts zu suchen. Du musst Dir darüber im Klaren sein, dass ein #include (logisch gesehen) nur vom Preprocessor ausgewertet wird, welcher eine reine Textersetzung macht. Alle anderen Regeln ergeben sich aus der ODR (one definition rule, bitte im Buch nachschlagen). Include-Guards haben sich als "best practice" herausgebildet.
Prometheus87 schrieb:
[...]
aber wenn ich kompelieren möchte bekomme ich immer den Fehler:undefenied reference to...
wo ist mein Denkfehler?
danke schon mal
Strenggenommen ist das kein Kompilierfehler sondern ein Linkerfehler. Typischerweise sind das zwei Schritte, die man getrennt durchführen kann.
1. Kompilieren, c/cpp/h/hpp --> o/obj
2. Verbinden, o/obj --> exeDas Zwischenergebnis sind sogenannte Objektdateien. In Deinem Fall hat sich der Linker beschwert, dass er eine Definition nicht gefunden hat. Wahrscheinlich hast Du versucht, aus indirekt nur einer Objekt-Datei eine ausführbare Datei zu erzeugen, wobei in einer anderen Objekt-Datei eine noch benötigte Funktionsdefinition enthalten ist, die dem Linker jetzt hier fehlt.
Stichwort dazu: Getrennte Übersetzung
Wenn Du Dich vorher mit beispielsweise Java auseinander gesetzt hast und auf G++ umsteigst, dann ist das keine Überraschung. Der "Standard-" Java-Compiler kompiliert automatisch alles benötigte. Beim G++ musst du alle Quelldateien (nur *.cpp, keine Header!) mit angeben. Also:
> g++ -c tu1.cpp > g++ -c tu2.cpp > g++ -o fertig tu1.o tu2.o
oder in einem Schritt:
> g++ -o fertig tu1.cpp tu2.cpp
wobei das "-c" für das Erzeugen der Objektdateien ist und über "-o" der Dateiname für das "Binary" angegeben werden kann.
-
argh, vesur, sorry!
hab das aus meinem Originalversuch (das Programm heißt HotEnergy...), rauskopiert weils nicht funktioniert hat, und wollte es hier mit "normalen" Namen reinsetzen, das hab ich vergsessen zu verändern, hat aber mit meinem Problem nix zu tun
thx, und richtig geraten, komme von Java, und da gabs kein Header-Zeugs...;-)
aber funktioniert leider immer noch nicht... momentane Dateien:
#include <iostream> #include <cstdio> #include "Testprogram.hh" using namespace std; void Testprogram::Testprogram() { cout<<"ich wurde erstellt!"<<endl; } void Testprogram::ausgabe() { cout<<"Und die Ausgabe funktioniert auch!"<<endl; }
Testprogram.hh:
#include <iostream> #include <cstdio> class Testprogram { public: Testprogram(); void ausgabe(); };
#include "Testprogram.hh" using namespace std; int main() { Testprogram objekt1; objekt1.ausgabe(); }
Er gibt einen Fehler in Testprogram.cc in line 8 aus:
return type specification for constructor invalid
kann mir da noch jemand helfen? danke
-
ah habs, Konstruktor ohne Rückgabetyp, dann funktionierts!
danke nochmal an alle!
Ich glaube mich übrigens zu erinnern, mal ein scons benutzt zu haben um was zu compelieren... muss man da dann nicht jede Datei einzeln erwähnen?
-
Include-Guards fehlen noch:
Testprogram.hh
#ifndef TESTPROGRAM_HH_INCLUDED #define TESTPROGRAM_HH_INCLUDED class TestProgramm { public: TestProgramm(); void ausgabe(); }; #endif
Du brauchst hier auch kein #include<iostream> im Header. Benutzt Du ja gar nicht.
Ein gutes Build-System nimmt Dir da vieles ab, ja. Ich verwende da meist das eingebaute der IDE oder auch mal ein von Hand geschriebenes Makefile unter Linux. Für ein Projekt habe ich auch cmake ausprobiert. So richtig klar komme ich damit aber nicht und ich finde es nervig, ständig in den Dokus nachgucken zu müssen, wie nochmal dies und das ging/funktionierte/etc. cmake ist bestimmt toll. Ich bin nur 'n bissel faul und leicht vergesslich...
-
krümelkacker schrieb:
Für ein Projekt habe ich auch cmake ausprobiert. So richtig klar komme ich damit aber nicht und ich finde es nervig, ständig in den Dokus nachgucken zu müssen, wie nochmal dies und das ging/funktionierte/etc. cmake ist bestimmt toll. Ich bin nur 'n bissel faul und leicht vergesslich...
Ich hab mich vor ein paar Wochen in CMake eingearbeitet. Bis man einmal etwas zustande bringt, ist CMake wirklich extrem mühsam. Ich habe auch kaum wirklich sinnvolle Tutorials dazu gefunden, und ein Buch kaufe ich dafür sicher nicht.
So langsam habe ich aber zumindest bei den Grundfeatures den Durchblick. Vieles ist halt immer noch unschön und erfordert teilweise etwas Boilerplate-Code, auch die Syntax ist gewöhnungsbedürftig. Aber von der Flexibilität her bin ich grundsätzlich damit zufrieden.
Aber sofern ich nicht plattforumunabhängig entwickle (d.h. der Code muss nicht zu jeder Zeit auf jeder Plattform kompilierbar sein), benutze ich Visual Studio und Visual Assist X, das ist meiner Meinung nach sehr komfortabel. Makefiles schreibe ich nur wenns wirklich nötig ist, auf Linux ziehe ich auch fertige IDEs wie Code::Blocks vor
-
Nexus schrieb:
Ich hab mich vor ein paar Wochen in CMake eingearbeitet. Bis man einmal etwas zustande bringt, ist CMake wirklich extrem mühsam. Ich habe auch kaum wirklich sinnvolle Tutorials dazu gefunden, und ein Buch kaufe ich dafür sicher nicht.
Ich hab mich mit gmake angefreundet. Auf der Arbeit brauche ichs eh, und für privat fand ich nmake von MS dann doch zu blöd. Wenn ich schon makefiles tippseln muss, dann gleich portable. Also benutz ich cygwin+gmake, sobald ich mehr als nur ein paar Codezeilen brauche, sprich wenn Dateien herumgeschoben werden müssen, doxygen über den Code laufen soll, Codegeneratoren im Spiel sind etc.
-
Hilfe
ich hab das ganze vor ein paar Tagen eingegeben, und mit
g++ start -o start.cc Testprogram.cc
compeliert und bin mir zu 99,99% sicher, dass es funktioniert hatte. Jetzt hab ichs heut wieder eingegeben, und es kommt die Fehlermeldung:
/tmp/ccNItuC8.o: In function
\_\_static\_initialization\_and\_destruction_0(int, int)': start.cc:(.text+0x45): undefined reference to
std::ios_base::Init::Init()'
start.cc:(.text+0x4a): undefined reference tostd::ios_base::Init::~Init()' /tmp/ccNItuC8.o:(.eh\_frame+0x12): undefined reference to
__gxx_personality_v0'
/tmp/ccgdpiWS.o: In functionTestprogram::Testprogram()': Testprogram.cc:(.text+0x11): undefined reference to
std::cout'
Testprogram.cc:(.text+0x16): undefined reference tostd::basic\_ostream<char, std::char\_traits<char> >& std::operator<< <std::char\_traits<char> >(std::basic\_ostream<char, std::char_traits<char> >&, char const*)' Testprogram.cc:(.text+0x1e): undefined reference to
std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)'
Testprogram.cc:(.text+0x26): undefined reference tostd::basic\_ostream<char, std::char\_traits<char> >::operator<<(std::basic\_ostream<char, std::char\_traits<char> >& (*)(std::basic\_ostream<char, std::char\_traits<char> >&))' /tmp/ccgdpiWS.o: In function
Testprogram::Testprogram()':
Testprogram.cc:(.text+0x3d): undefined reference tostd::cout' Testprogram.cc:(.text+0x42): undefined reference to
std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)'
Testprogram.cc:(.text+0x4a): undefined reference tostd::basic\_ostream<char, std::char\_traits<char> >& std::endl<char, std::char\_traits<char> >(std::basic\_ostream<char, std::char_traits<char> >&)' Testprogram.cc:(.text+0x52): undefined reference to
std::basic_ostream<char, std::char_traits<char> >::operator<<(std::basic_ostream<char, std::char_traits<char> >& (*)(std::basic_ostream<char, std::char_traits<char> >&))'
/tmp/ccgdpiWS.o: In functionTestprogram::ausgabe()': Testprogram.cc:(.text+0x69): undefined reference to
std::cout'
Testprogram.cc:(.text+0x6e): undefined reference tostd::basic\_ostream<char, std::char\_traits<char> >& std::operator<< <std::char\_traits<char> >(std::basic\_ostream<char, std::char_traits<char> >&, char const*)' Testprogram.cc:(.text+0x76): undefined reference to
std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)'
Testprogram.cc:(.text+0x7e): undefined reference tostd::basic\_ostream<char, std::char\_traits<char> >::operator<<(std::basic\_ostream<char, std::char\_traits<char> >& (*)(std::basic\_ostream<char, std::char\_traits<char> >&))' /tmp/ccgdpiWS.o: In function
__static_initialization_and_destruction_0(int, int)':
Testprogram.cc:(.text+0xa1): undefined reference tostd::ios_base::Init::Init()' Testprogram.cc:(.text+0xa6): undefined reference to
std::ios_base::Init::~Init()'
/tmp/ccgdpiWS.o:(.eh_frame+0x12): undefined reference to `__gxx_personality_v0'
collect2: ld returned 1 exit statusähhhm... was bedeutet das???
danke schon mal
-
g++ start -o start.cc Testprogram.cc
Na das hast du hoffentlich nicht so eingegeben. Nach -o steht die Datei, in die das ausführbare Programm geschrieben wird. Wenn der Compiler soweit gekommen wäre, hätte er dir deinen Quelltext start.cc überschrieben.
Richtig wäre:
g++ -o start start.cc Testprogramm.cc
Aber wahrscheinlich hast du gcc statt g++ genommen? Das wäre so eine typische Fehlermeldung dafür, dann fehlt nämlich die C++-Standardbibliothek beim Linken.
-
arrrrrrrrrrrgh blöder Fehler!!!
sorry an alle und danke
-
Prometheus87_gastzugang schrieb:
Hilfe
ich hab das ganze vor ein paar Tagen eingegeben, und mit
g++ start -o start.cc Testprogram.cc
probiere:
g++ start.cc Testprogram.cc -o start
-
Und das Verb heisst "compilieren".