Was mach ich hier falsch? (source inside)
-
Hallo,
Ich komme mir richtig dumm vor, aber irgendwie bekomme ich in C++ nicht die einfachsten Sachen hin, und dass obwohl ich in Java fast zu den Gurus gehöre.
Ich habe hier 2 Klassen Object und String, wobei String von Object erbt und Object eine Funktion bereitstellt, welche einen String zurück gibt. Ja eine wunderschöne zirkuläre Abhängigkeit. Nur wie löse ich die richtig auf? Momentan bekomme ich jedenfalls folgende Fehlermeldung von gcc:
g++ -fPIC -g -Wall -c -o src/de/jtdev/base/Object.o src/de/jtdev/base/Object.cpp src/de/jtdev/base/Object.cpp:11: Fehler: virtuelle Deklaration einer äußeren Klasse src/de/jtdev/base/Object.cpp:14: Fehler: virtuelle Deklaration einer äußeren Klasse src/de/jtdev/base/Object.cpp: In member function »virtual de_jtdev_base::String* de_jtdev_base::Object::toString() const«: src/de/jtdev/base/Object.cpp:15: Fehler: invalid use of undefined type »struct de_jtdev_base::String« src/de/jtdev/base/Object.hpp:14: Fehler: forward declaration of »struct de_jtdev_base::String«Dazu hier die 4 Sourcen der Klassen:
Object.hpp:
#ifndef DE_JTDEV_BASE_OBJECT_HPP #define DE_JTDEV_BASE_OBJECT_HPP #include <stdio.h> namespace de_jtdev_base { /* template<class CheckType, InstanceType> bool isInstanceOf(InstanceType &instance) { return (dynamic_cast<CheckType*>(&instance) != NULL); }*/ class String; class Object { public: Object(); virtual ~Object(); virtual String* toString() const; }; // class Object } // namespace de_jtdev_base #endif // DE_JTDEV_BASE_OBJECT_HPPObject.cpp:
#ifndef DE_JTDEV_BASE_OBJECT_CPP #define DE_JTDEV_BASE_OBJECT_CPP #include "Object.hpp" namespace de_jtdev_base { Object::Object() { } virtual Object::~Object() { } virtual String* Object::toString() const { return new String(); } } // namespace de_jtdev_base #endif // DE_JTDEV_BASE_OBJECT_CPPString.hpp:
#ifndef DE_JTDEV_BASE_STRING_HPP #define DE_JTDEV_BASE_STRING_HPP #include <sys/types.h> #include "Object.hpp" namespace de_jtdev_base { typedef unsigned short character; class String : public Object { private: character* data; size_t length; public: String(); String(const String &original); String(const character* data, const size_t length); String(const character* data, const size_t offset, const size_t count); ~String(); size_t getLength() const; }; // class String } // namespace de_jtdev_base #endif // DE_JTDEV_BASE_STRING_HPPString.cpp:
#ifndef DE_JTDEV_BASE_STRING_CPP #define DE_JTDEV_BASE_STRING_CPP #include <string.h> #include "String.hpp" namespace de_jtdev_base { String::String() { length = 0; data = new character[0]; } String::String(const String &original) { length = original.length; data = new character[length]; memcpy(data, original.data, sizeof(character)*length); } String::String(const character* _data, const size_t _length) { length = _length; data = new character[length]; memcpy(data, _data, sizeof(character)*length); } String::String(const character* _data, const size_t _offset, const size_t _length) { length = _length; data = new character[length]; memcpy(data, (const character*)(_data + _offset), sizeof(character)*length); } String::~String() { delete data; } size_t String::getLength() const { return length; } } // namespace de_jtdev_base #endif // DE_JTDEV_BASE_STRING_CPPIst ja eigentlich nichts so besonderes, nur was bemängelt die gcc da? Ich werde aus dieser Fehlermeldung irgendwie nicht schlau...

Hoffe ihr habt genug Ausdauer um euch da durchzufressen, ich platze hier jedenfalls gleich.
mfG
Tobain
-
In Object.cpp musst du String.h inkludieren, weil du eine Instanz von String erstellst.
-
So habe ich jetzt einfach mal so getan und #include "String.hpp" zu Object.cpp hinzugefügt, nur bekomme ich jetzt folgende Fehlermeldung:
src/de/jtdev/base/Object.cpp:12: Fehler: virtuelle Deklaration einer äußeren Klasse src/de/jtdev/base/Object.cpp:15: Fehler: virtuelle Deklaration einer äußeren KlasseWas soll hier eine "virtuelle Deklaration einer äußeren Klasse" sein?
Warum sollte ich die Includeanweisung nicht zu Headerdatei hinzufügen?Trotzdem schon mal vielen dank, denn es sind jetzt schon wesentlich weniger Fehlermeldungen..
-
Tobain schrieb:
Ich komme mir richtig dumm vor, aber irgendwie bekomme ich in C++ nicht die einfachsten Sachen hin, und dass obwohl ich in Java fast zu den Gurus gehöre.
s/obwohl/weil/ dann passt's :p
1. "virtual" bei der Deklaration und bei der Implementation zu benutzen lassen wir mal sein

2. Du möchtest in Object.cüü ein '#include "String.hpp"' einfügen. Durch Object.hpp hast du zwar die forward declaration drin, aber nicht die vollständige Deklaration. Bei einer forward declaration ohne vollständiger Deklaration kann etwas nicht stimmen, und da springt dir der G++ ins Gesicht.Mit folgendem Code gates dann bei mir (G++ 4.0.3):
// Object.hpp #ifndef DE_JTDEV_BASE_OBJECT_HPP #define DE_JTDEV_BASE_OBJECT_HPP #include <stdio.h> namespace de_jtdev_base { /* template<class CheckType, InstanceType> bool isInstanceOf(InstanceType &instance) { return (dynamic_cast<CheckType*>(&instance) != NULL); }*/ class String; class Object { public: Object(); virtual ~Object(); virtual String* toString() const; }; // class Object } // namespace de_jtdev_base #endif // DE_JTDEV_BASE_OBJECT_HPP// Object.cpp #ifndef DE_JTDEV_BASE_OBJECT_CPP #define DE_JTDEV_BASE_OBJECT_CPP #include "Object.hpp" #include "String.hpp" namespace de_jtdev_base { Object::Object() { } Object::~Object() { } String* Object::toString() const { return new String(); } } // namespace de_jtdev_base #endif // DE_JTDEV_BASE_OBJECT_CPP
-
Da wird man mal kurz abgelenkt und schon war jemand anders schneller...
Tobain schrieb:
Warum sollte ich die Includeanweisung nicht zu Headerdatei hinzufügen?
Dann müsstest du sie *nach* der Deklaration von Object einfügen, weil String.hpp von Object.hpp abhängt.
Man hätte also folgende Möglichkeiten:#include "sonstigeincludes" class String; class Object { // ... } #include "String.hpp" // oder #include "sonstigeincludes" class Object; #include "String.hpp" class Object { // ... }Oder eben das, was ich in meinem vorherigen Beitrag gezeigt habt. Und bevor ich mir meine Include-Anweisungen sonstwo im Quellcode verteile, stecke ich sie lieber zusammen in eine Implementationsdatei.