Mein polymorphic_ptr
-
a)
template<typename Base, typename = typename std::enable_if<std::is_base_of<typename Base::value_type, value_type>::value>::type> operator Base(){ return Base(dynamic_cast<typename Base::pointer_type>(pointer)); }b)
static_assert(std::is_base_of<typename Base::value_type, value_type>::value, "Hey, this is not the base");c) NEIN! Mach das nicht! Einen dynamic_cast sollte man immer argwöhnisch betrachten. Der ist selten gut, oft unnötig. Ihn in einem impliziten Cast zu verstecken ist so mit das schlimmste, was man machen kann. Explizit vielleicht, da kann man sich streiten, aber implizit nie.
d) Wofür brauchst du das, das riecht nach schlechtem Design.
static_assert(false, "You are trying to hide a dynamic_cast. Your design is broken!");
-
Soso.
Ich dachte bei sowas wie "operator T()" könnte man T genauso wie einen Rückgabetypen behandeln. Wohl doch nicht.
Nun, das dynamic_cast hab ich dann mal entfernt (werde gleich mal seine Nachteile ergoogeln).
abcd schrieb:
d) Wofür brauchst du das, das riecht nach schlechtem Design.
Ist das nun auf das dynamic_cast, oder auf meine gesamte Klasse bezogen?
Also ich finde einen polymorph-artigen Pointer schon nützlich und sähe es eher als Nachteil, wenn man einen Smart Pointer vom Typ Derived nicht in einen Smart Pointer vom Typ Base konvertieren könnte.Ansonsten vielen Dank für die Antworten!
-
Was kann dein Smart-Pointer, das
std::unique_ptrnicht kann?Oder was genau verstehst du unter "polymorph"?
-
Naja, er hat "Referenzzähler" erwähnt. Also wird das Ding wohl im Gegensatz zu unique_ptr kopierbar sein.

Aber im Ernst: Was sabber mit "polymorph" in diesem Kontext meint, verstehe ich auch nicht. Der Rest klingt nur nach Konvertierungsmöglichkeiten.
shared_ptr ist ungefähr so gestrickt:
namespace shared_ptr_details { // Internas struct control_base { std::atomic<unsigned long> refcounter; // hier fehlt noch die Unterstuetzung von weak_ptr virtual ~control_base() {} }; } // namespace shared_ptr_details template<class T> class shared_ptr { public: shared_ptr() : ptr(nullptr), control(nullptr) {} template<class U> explicit shared_ptr(U* p, typename std::enable_if< std::is_convertible<U*,T*>::value >::type* =0); template<class U> shared_ptr(shared_ptr<U> const& sp, typename std::enable_if< std::is_convertible<U*,T*>::value >::type* =0) : ptr(sp.ptr), control(sp.control) { if (control) ++(control->refcounter); } ... T* operator->() const {return ptr;} T& operator*() const {return *ptr;} explicit operator bool() const {return ptr;} bool operator!() const {return !ptr;} ~shared_ptr() { if (control && (control->refcounter-- == 0)) delete control; } private: T* ptr; shared_ptr_details::control_base* control; template<class> friend class shared_ptr; };und erlaubt damit beispielsweise implizite shared_ptr<Derived> zu shared_ptr<Base> Konvertierungen, genauso wie shared_ptr<int> zu shared_ptr<const int>.

Fehler dürfen vom Fragesteller korrigiert werden.
-
*kopfkratz*
Ich dachte immer Polymorphie bedeutet, dass eine Variable unterschiedliche Datentypen annehmen kann. Wohl doch nicht?
Meine Englischkenntnisse sind nicht gerade hervorragend, d.h. ich könnte vieles in den englischen Lektüren die ich gelesen habe ganz einfach falsch interpretiert haben.
Grüße.
-
sabber schrieb:
Ich dachte immer Polymorphie bedeutet, dass eine Variable unterschiedliche Datentypen annehmen kann. Wohl doch nicht?
Das würde ich eher "dynamic typing" nennen. Aber das meinst Du wahrscheinlich auch nicht.
Wie auch immer: Du machst das nur als Übrung, oder? Denn sonst wüsste ich auch gerne, wie sich das, was du bauen willst, von std::shared_ptr unterscheiden soll.
-
krümelkacker schrieb:
Wie auch immer: Du machst das nur als Übrung, oder? Denn sonst wüsste ich auch gerne, wie sich das, was du bauen willst, von std::shared_ptr unterscheiden soll.
Jo.
Nun, der Unterschied ist halt, dass man bei meinem Smart Pointer halt nur Konvertierungen zwischen vererbten und Basisklassen zugelassen werden, wobei man z.B. beimstd::shared_ptr(wie Du auch schon gesagt hast)intzuconst intkonvertieren kann.
Mir ist halt im Moment etwas langweilig
krümelkacker schrieb:
Das würde ich eher "dynamic typing" nennen. Aber das meinst Du wahrscheinlich auch nicht.
Nun, doch, genau das mein ich.
Unter Wikipedia lese ich z.B. folgendes:Wikipedia (<a href= schrieb:
Quelle)">Polymorphie oder Polymorphismus (griechisch, „Vielgestaltigkeit“) ist ein Konzept in Programmiersprachen, das die Fähigkeit eines Bezeichners beschreibt, abhängig von seiner Verwendung unterschiedliche Datentypen anzunehmen.
Andere Quellen gehen auch auf ungf. das Gleiche hinaus, wie das, was auch Wikipedia steht.
krümelkacker: Könntest Du mir dann vielleicht noch verraten, was Du unter Polymorphie verstehst? Das würd mich dann mal brennend interessieren!
Grüßle
-
volkard schrieb:
sabber schrieb:
Unter Wikipedia lese ich z.B. folgendes:
Wikipedia (<a href= schrieb:
Quelle)">Polymorphie oder Polymorphismus (griechisch, „Vielgestaltigkeit“) ist ein Konzept in Programmiersprachen, das die Fähigkeit eines Bezeichners beschreibt, abhängig von seiner Verwendung unterschiedliche Datentypen anzunehmen.
Andere Quellen gehen auch auf ungf. das Gleiche hinaus, wie das, was auch Wikipedia steht.
Sehr schwach.
Wechle mal nach Englisch. "In computer science, polymorphism is a programming language feature that allows values of different data types to be handled using a uniform interface. "
-
Wenn ich das also richtig verstanden habe, ist das Wort "Polymorphie" also eher den virtuellen Methoden gewidmet(?)
-
sabber schrieb:
Wenn ich das also richtig verstanden habe, ist das Wort "Polymorphie" also eher den virtuellen Methoden gewidmet(?)
Je nach Quelle.
Die älteren, schlechteren oder von C++ weiter entfernten Quellen meinen damit oft ausschließlich diese Art der Polymorphie der virtuellen Methoden.Der deute Wikipediaeintrag gibt sich gerade Mühe, ein wenig weiter zu sehen, wird aber mit "Polymorphie in der Softwareentwicklung" schon von Schwätzern vergiftet.
-
sabber schrieb:
krümelkacker schrieb:
Wie auch immer: Du machst das nur als Übrung, oder? Denn sonst wüsste ich auch gerne, wie sich das, was du bauen willst, von std::shared_ptr unterscheiden soll.
Jo.
Nun, der Unterschied ist halt, dass man bei meinem Smart Pointer halt nur Konvertierungen zwischen vererbten und Basisklassen zugelassen werden, wobei man z.B. beimstd::shared_ptr(wie Du auch schon gesagt hast)intzuconst intkonvertieren kann.Wieso diese künstliche Einschränkung? Du kannst doch beides auf einen Schlag abdecken mit dem templatisierten Konvertierungskonstruktor.
sabber schrieb:
krümelkacker schrieb:
Das würde ich eher "dynamic typing" nennen. Aber das meinst Du wahrscheinlich auch nicht.
Nun, doch, genau das mein ich.
Unter Wikipedia lese ich z.B. folgendes:
[...]Wenn du sagst, dass der Typ einer Variablen sich ändern kann, dann hat das nichts mit C++ zu tun, weil in C++ der Typ einer Variablen immer derselbe ist. Erst wenn du eine Indirektionsstufe (Zeiger o. ä.) hinzufügst und die Basisklasse "polymorph" machst, indem du ihr einen virtuellen Destruktor oder mindestens eine virtuelle Funktion spendierst, kann es Polymorphie im OOP-Sinne geben.
Base* p = ...;Der statische Typ von p ist Base* und immer derselbe. Der statische Typ von *p, also p dereferenziert, ist Base und auch immer derselbe. Aber, der dynamische Typ von *p kann etwas anderes als Base sein, wobei der dynamische Typ von *p aber dann wenigstens von Base abgeleitet ist. Du kannst p jetzt zwar auf ein anderes Objekt mit einem anderen dynamischen Typen zeigen lassen, aber p ist immer noch ein Base-Zeiger.
-
Nadann!
Danke nochmals für die Aufklärungen.
Ich werde meinen polymorphic_ptr dann halt in my_shared_ptr umtaufen und die künstliche Beschränkung dann halt verwerfen.
Desweiteren glaube ich jetzt das Wort "Polymorphie" (zumindest) besser verstanden zu haben als vorhin und da ich diesen Satz hier jetzt nicht gleich mit einem Punkt beenden will, sage ich nochmals Danke!

Grüße.
*eine Packung Merci-Schokolade in den Thread stell*