Namespaces vs. Friends
-
Hi,
ich bin heute über ein kurioses Problem gestolpert, bei dem ich jetzt nicht weiterkomme. Dazu zuerst folgender Code// Header-Datei namespace ErrHandling { class ExceptionEx : public std::runtime_error { friend ExceptionEx * createException(ExceptionEx *, const std::string &, size_t); private: std::string file_; size_t line_; public: ExceptionEx(const std::string & msg); std::string getFile() const; size_t getLine() const; }; ExceptionEx * createException(ExceptionEx * e, const std::string & file, size_t line); #define THROW(T,msg) (throw createException(new T(msg), __FILE__, __LINE__)) } //--------------------------------------------------------------------------- // Cpp-Datei #include "Exceptional.h" #pragma package(smart_init) using namespace ME_Exception; using namespace std; [...] ExceptionEx * createException(ExceptionEx *e, const std::string & file, const int line) { e->file_ = file; e->line_ = line; return e; }
Das Problem ist, dass wenn die Klasse und die friend-Funktion sich in einem Namespace befinden es sich nicht kompilieren lässt. Unter BCB 5.0 bekomme ich dann "E2247 Zugriff auf 'ExceptionEx::file_' nicht möglich". Das Seltsame dabei ist, dass es dann funktioniert wenn ich die namespace-Anweisung entferne. Weiß jemand was ich da falsch mache?
EDIT: Es gab im Quelltext ein paar Fehler, die nichts mit der Frage zu tun hatten
-
er behandelt deine createException Definition in der implementierung als ::createException. und ::createException hat keine friend rechte, die hat nur ErrHandling::createException. Für diese funktion hast du aber keine definition
Du musst ebendiese in der implementierungsdatei als ErrHandling::createException definieren (oder namespace ErrHandling drum herum bauen)
-
das #define landet niemals im namespace, sollte also
#define THROW(T,msg) (throw ErrHandling::createException(new T(msg), __FILE__, __LINE__))
sein.
Ansonsten "frißt" VC7 eine Deklaration wie folgende:
namespace nsFoo { class CBar { int x; friend void Foo(Bar * p); }; void Foo(CBar * p) { p->x = 0; } }
Nach meinem Verständnis von namespaces ist das auch richtig (das unqualifizierte Foo liegt innerhalb des namespaces) - da bin ich mir aber nicht sicher ob das auch der C++ Standard denkt...
was meckert der herr Compiler denn?
-
Danke erstmal für die Vorschläge. Ich habe es inzwischen aber etwas anders gelöst, in dem ich createException zu einer Methode der Klasse machte, und den ersten Parameter entfernte. Ich werde aber für das nächste mal es im Auge behalten
peterchen, ich verstehe nicht ganz was Du meinst, ist aber auch nicht wichtig weil ich den borland Compiler verwende
. Die Meldungen waren : "E2247 Zugriff auf 'ExceptionEx::file_' nicht möglich", und "E2247 Zugriff auf 'ExceptionEx::line_' nicht möglich"
-
Was ich meinte ist: Ich hab' keinen C++ standard zur hand, also mußte ich mich mit dem "rekonstuieren" des Konstrukts zufriedengeben..