Boost noncopyable funktioniert nicht
-
Hallo zusammen, Hallo pros !
ich habe folgendes Problem: Boost::noncopyable scheint nicht zu greifen. Verwundert ? Hier der Beispiel-Code (getestet Windows, MSVS 2005):
Eine static lib mit einer Datei (TestClasses.hpp) und folgendem Inhalt:
#include <boost/noncopyable.hpp>
class INonCopyNormalClass: boost::noncopyable
{
public:
virtual INonCopyNormalClass* clone() = 0;
};Eine DLL mit folgenden Dateien:
DLLMain.cpp:
#include "DLLmain.hpp"YetAnotherNonNormalCopyClass::YetAnotherNonNormalCopyClass()
{
}INonCopyNormalClass* YetAnotherNonNormalCopyClass::clone()
{
return new YetAnotherNonNormalCopyClass(*this);
}DLLMain.hpp:
#include "../TestLib/TestClasses.hpp"# if defined(UNCOPYABLETESTDLL_EXPORTS)
# define DLL_API __declspec(dllexport)
# else
# define DLL_API
# endifclass DLL_API AnotherNonNormalCopyClass: public INonCopyNormalClass
{
};class YetAnotherNonNormalCopyClass: public AnotherNonNormalCopyClass
{
public:
YetAnotherNonNormalCopyClass();virtual INonCopyNormalClass* clone();
};Nun der Clou: alles kompiliert korrekt, sollte aber nicht möglich sein,
da YetAnotherNonNormalCopyClass in der clone() fct nicht kopierbar sein sollte !
Entfernt man nun das DLL_API (also das exportieren der Symbole), kommt es zum erwarteten Compiler-Fehler. Warum ?Grüße,
PhilippPS: das Projekt ist natürlich sehr viel größer, es wurde auf das Kernproblem reduziert. Für alle, die es trotzdem wundert: Die Idee war, den Benutzer des Interfaces dazu zu zwingen, die clone() fct zu benutzen (slicing), daher soll es von boost::noncopyable erben.
-
Vermutung: Die Idee von noncopyable ist, dass man Kopierkonstruktor und Zuweisungsoperator privat macht und nicht implementiert, so dass das spätestens beim Linken auffällt. Dadurch, dass du deine Klasse als DLL exportierst, entfällt aber das Linken, so dass schonmal beim Bauen kein Fehler fliegen dürfte.
Das Linken zur Laufzeit hat anscheinend nicht genau die gleiche Semantik wie das statische Linken, so dass es auch keinen Laufzeitfehler gibt.
-
Bashar schrieb:
Die Idee von noncopyable ist, dass man Kopierkonstruktor und Zuweisungsoperator privat macht
Dadurch, dass er privat ist, sollte der Aufruf desselben in der abgeleiteten Klasse doch auch schon verhindert werden?
EDIT:
Rest war quatsch.
-
Stimmt, Denkfehler.
-
PM1302 schrieb:
#include <boost/noncopyable.hpp> class INonCopyNormalClass: boost::noncopyable { public: virtual INonCopyNormalClass* clone() = 0; };Nun private Vererbung von boost::noncopyable in deine Klasse hebt die Wirkung auf, welches noncopyable haben sollte. Private Vererbung stellt die Beziehung "ist Implementiert durch" da und hat mit der eigentlich Vererbung nicht viel gemeinsam ausser der Syntax.
-
Danke für die ersten Vermutungen, aber:
a) durch wegnehmen von DLL_API zeigt die Vererbung von noncopyable den gewünschten Effekt, was in einem compiler fehler mündet, da der compiler den copy constructors der abgeleiteten Klassen nicht automatisch erzeugen kannb) ob public / private Vererbung von noncopyable ist egal. Der Effekt ist der gleiche: mit DLL_API funktioniert es (was es nicht sollte), ohne DLL_API nicht (wie es sein sollte).
However, das Problem bleibt: Durch das exportieren "verschwindet die Wirkung" von noncopyable, was nicht sein darf !
-
BTW:
"The public keyword in the inheritance syntax means that publicly accessible members inherited from the base class stay publicly accessible in the derived class".
Da aber assigment operator/copy constructor bereits in der Basisklasse "private" sind, spielt es keine Rolle, ob private, protected oder pubic vererbt wird, oder irre ich mich jetzt ?
-
Bekommst du eigentlich die hier?
http://msdn.microsoft.com/en-us/library/3tdb471s(VS.80).aspx
-
ja, C4275 bekomme ich. Aber ich verstehe den Zusammenhang nicht.
BTW, wenn das der Grund wäre, könnte man boost::uncopyable ja gar nicht (bzw. das Konzept dahinter) immer sicher verwenden.
Warum ist das nicht dokumentiert bzw. fällt das niemandem auf ?
-
Und es wird noch besser: (kleineres beispiel, eine DLL):
DLLmain.hpp:
#include "boost/noncopyable.hpp"# if defined(UNCOPYABLETESTDLL_EXPORTS)
# define DLL_API __declspec(dllexport)
# else
# define DLL_API
# endifclass DLL_API AnotherNonNormalCopyClass: private boost::noncopyable
{
};class YetAnotherNonNormalCopyClass: public AnotherNonNormalCopyClass
{
public:
virtual AnotherNonNormalCopyClass* clone();
};
DLLmain.cpp:
#include "DLLmain.hpp"AnotherNonNormalCopyClass* YetAnotherNonNormalCopyClass::clone()
{
return new YetAnotherNonNormalCopyClass(*this);
}Ich verstehe das nicht: das kompiliert/linkt !.....

-
wie sieht es auf der Nutzerseite aus, also __declspec(dllimport) ?
-
Wie meinst Du das genau ? Ich exportiere ja noch keine Symbole....?
-
Doch, die Klasse.
-
PM1302 schrieb:
Und es wird noch besser: (kleineres beispiel, eine DLL):
DLLmain.hpp:
#include "boost/noncopyable.hpp"# if defined(UNCOPYABLETESTDLL_EXPORTS)
# define DLL_API __declspec(dllexport)
# else
# define DLL_API
# endifclass DLL_API AnotherNonNormalCopyClass: private boost::noncopyable
{
};class YetAnotherNonNormalCopyClass: public AnotherNonNormalCopyClass
{
public:
virtual AnotherNonNormalCopyClass* clone();
};
DLLmain.cpp:
#include "DLLmain.hpp"AnotherNonNormalCopyClass* YetAnotherNonNormalCopyClass::clone()
{
return new YetAnotherNonNormalCopyClass(*this);
}Ich verstehe das nicht: das kompiliert/linkt !.....

Bei mir auf jeden fall nicht
d:\workspace\dll_test\dll_test\main.h(11) : error C2248: 'boost::noncopyable_::noncopyable::noncopyable' : cannot access private member declared in class 'boost::noncopyable_::noncopyable'
1> d:\develop\include\boost\noncopyable.hpp(27) : see declaration of 'boost::noncopyable_::noncopyable::noncopyable'
1> d:\develop\include\boost\noncopyable.hpp(22) : see declaration of 'boost::noncopyable_::noncopyable'
1> This diagnostic occurred in the compiler generated function 'AnotherNonNormalCopyClass::AnotherNonNormalCopyClass(const AnotherNonNormalCopyClass &)'
-
@Zeus: Hast Du UNCOPYABLETESTDLL_EXPORTS definiert?
-
Ok, welcher Compiler/Linker ? ServicePack ?
-
Ja, ok, die Klasse...sorry, mein Fehler
-
LordJaxom schrieb:
@Zeus: Hast Du UNCOPYABLETESTDLL_EXPORTS definiert?
Oh irgendwas musste ich ja vergessen mit UNCOPYABLETESTDLL_EXPORTS gibst nur 1 Warnung <.<
-
Folgender Code in einem DLL-Projekt erzeugt einen internen Compilerfehler in MSVC 2005:
class __declspec(dllexport) base { private: base( const base& ); }; class __declspec(dllexport) derived : public base { public: void foo() { derived p( *this ); } };Übrigens auch ohne dllexport an der Basisklasse.
-
@MDK: Es geht aber nicht um die Compiler-Warning, sondern, dass die (beasichtigte und erwartete) Wirkung von boost::noncopyable aufgehoben wird und zwar so, dass es der Entwickler zur Compile/Link Zeit nichts bemerkt. Erst zur Laufzeit gibt es "komisches" Verhalten i.e. zeigt sich, dass clone() eben doch nicht funktioniert z.B. unitialisierte Member etc, aber keinen Crash