In STL sind verschiedene Entwurfsmuster wie Adapter und Iterator implementiert.
Bedeutet das, dass STL mit OO-Konzepten implementiert wird?
Welche Beziehung besteht zwischen OO und Vorlagenteilen von C ++?
Ich habe erfahren, dass die Funktion eines virtuellen Mitglieds, die die OO rechtfertigt, der Vorlage widerspricht. Ist das richtig?
Antworten:
Erstens ist die "STL" kein offizieller Begriff, sondern der Name der Bibliothek, die für die Aufnahme in die C ++ - Standardbibliothek vorgeschlagen wurde, wenn keine Container vorhanden waren. Es bietet im Wesentlichen Container- und Algorithmusvorlagen.
Diese Container- und Algorithmusvorlagen sind ... Vorlagen, sodass sie nach Bedarf Typen erzeugen. Sie sind aus Sicht des Benutzers nicht auf Vererbung angewiesen.
Die Standardbibliothek gibt jedoch im Wesentlichen die Schnittstelle der Bibliothek an, nicht die Implementierung. Viele STL-Implementierungen verwenden ein wenig Objektorientierung in ihrer Implementierung, aber als Benutzer werden Sie es nicht sehen, wenn Sie nicht in den Quellcode Ihrer Implementierung eintauchen (der verfügbar gemacht werden muss, da es sich im Wesentlichen um Vorlagencode handelt).
Nein, es handelt sich um orthogonale Konzepte, die sehr unterschiedliche Vor- und Nachteile bieten. In C ++ besteht einer der Hauptvorteile bei der Verwendung einer solchen Sprache darin, dass Sie sowohl verfügbar sind als auch eine verwenden und nicht mit der anderen abbrechen. Es ist sogar ein sehr großer Vorteil. Eine der interessantesten Redewendungen in C ++ ist beispielsweise CRTP , das sowohl Vorlagen als auch Vererbung verwendet. Die Idee ist, dass Sie mit dem Vererbungsteil mehrere Typen mit einem gemeinsamen Verhalten und gemeinsamen Daten als Basisklasse erweitern können. Während der Vorlagenteil sicherstellt, dass für jedes untergeordnete Element bestimmte Basisklassen generiert werden, ist es unmöglich, einen Zeiger auf alle Klassen zu haben, die die CRTP-Klasse als Basis verwenden. Dies ist äußerst nützlich und erlaubt es nicht, mit der Vererbung herumzuspielen, wo es keine geben sollte.
Ich habe auch sehr generische Ereignisverteilungssysteme implementiert, die weder Ereignistypen noch Listenertypen kannten, sondern intern dynamischen und statischen Code kombinierten, der es zusammen ermöglichte, die richtigen internen Typen zu generieren, die den richtigen Laufzeittypen entsprechen.
Und das ist der Punkt: Sie brauchen nicht immer "Objektorientierung". Tatsächlich müssen Sie die meiste Zeit, wenn Sie sie überhaupt nicht benötigen, einige Typen definieren und sie direkt als unterschiedlichen Teil einer abstrakten Engine (Komposition) verwenden. Sie benötigen nicht immer generischen Code, auch Vorlagen genannt. Manchmal muss eine Funktion verallgemeinert werden, um sie auf mehrere nicht verwandte Typen anzuwenden. Wenn sie verwandt sind, können Sie stattdessen ihre Basisklasse verwenden und benötigen keine Vorlagen.
Sie haben unterschiedliche Vorteile und völlig unterschiedliche Kosten, sodass sie gut kombiniert werden können, um komplexe Probleme zu lösen.
STL ist ein gutes Beispiel für ein Problem, bei dem es hauptsächlich darum geht, Typen (Container) und Funktionen (Algorithmen) bereitzustellen, die sich auf einen bestimmten Typ beziehen, anstatt auf eine Hierarchie von Laufzeitobjekten. In der Standardbibliothek werden Streams auf eine für die Objektorientierung typische Weise erstellt: Es handelt sich um eine Hierarchie von Stream-Klassen, die verschiedene Funktionen ausführt, um eine Sub-Stream-Klasse zu definieren, die unterschiedliche Verhaltensweisen / Kapazitäten kombiniert. Dort ist die Objektorientierung nützlich, auch wenn einige Leute es vorziehen würden, wenn sie eher der STL ähnelt (ich bin kein Spezialist auf diesem Gebiet).
Stellen Sie sich diese also als sehr unterschiedliche Werkzeuge vor, als Schraubenzieher und Hammer. In C ++ können Sie nicht nur an ein Tool denken.
quelle
Tatsächlich führte die STL das Paradigma der generischen Programmierung in den Mainstream ein.
Als ich vor 15 Jahren (von einem Professor) über das objektorientierte Programmierparadigma unterrichtet wurde, wurden mir die drei entscheidenden Säulen Kapselung, Vererbung und Polymorphismus beigebracht (heute sollte letzteres wahrscheinlich als Laufzeitpolymorphismus bezeichnet werden ), während Wikipedia derzeit listet Datenabstraktion, Kapselung, Messaging, Modularität, Polymorphismus und Vererbung als definierende OOP-Merkmale auf. Natürlich verwendet die STL einige davon, wie die Kapselung, aber dann verwendet sie auch Funktionen, die für das Paradigma der strukturierten Programmierung charakteristisch sind . Dennoch würde niemand argumentieren, dass die STL strukturierte Programmierung ist .
Beachten Sie, dass eine der stärksten Funktionen von C ++ die Tatsache ist, dass es viele Programmierparadigmen unterstützt (strukturierte, objektorientierte, generische, funktionale Programmierung und andere) und dass es dort am hellsten leuchtet, wo Sie sie mischen und mischen.
quelle
Um Alexander Stepanov aus seinem STLPort-Interview zu zitieren :
Eine individuelle Implementierung könnte jedoch stellenweise unter Verwendung von Vererbung und Polymorphismus erfolgen. Ich habe zum Beispiel eine Implementierung gesehen, von der
iterator
abgeleitet wurdeconst_iterator
, um die implizite Konvertierung voniterator
nach zu unterstützenconst_iterator
. Die Ableitung ist jedoch nicht charakteristisch für das Design oder wird von diesem verlangt.Fazit: Während Sie objektorientierten Code verwenden können / könnten, um einige Teile der STL zu implementieren, ist das Design der STL selbst (nachdrücklich) nicht objektorientiert.
quelle
Nein, ich würde sagen, die STL ist nicht besonders OO, wenn überhaupt, entspricht sie eher einem funktionalen Programmierstil. Bestimmtes:
Ebenso kann man argumentieren, dass die Container selbst Monaden sind
vector<string>(1,"Foo")
Bei Ihren anderen Fragen sind die OO-Teile und Vorlagenteile von C ++ getrennt, und virtuelle Funktionen schließen Vorlagen nicht aus. Im Fall der STL verwendet das Design einfach keine virtuellen Funktionen.
quelle
std::vector<int>
nicht objektorientiert ist.Es hängt davon ab, wen Sie nach einer Definition von OOP fragen, da OOP ein notorisch schlecht definierter Begriff ist und es keinen guten Konsens darüber gibt, was OOP ausmacht und was nicht.
Aus der Sicht einer Java-Person lautet die Antwort wahrscheinlich "Nein", da die Algorithmen- und Containerbibliothek von C ++ sich nicht mit Laufzeitpolymorphismus befasst, keine Klassenvererbung verwendet und die Syntax nicht OOP-y aussieht.
Wenn Sie andererseits eine funktionierende Programmierperson fragen, lautet die Antwort möglicherweise "Ja".
So definiert Wikipedia OOP:
All dies wird in der Standardbibliothek von C ++ und insbesondere in dem Teil, der sich mit Containern und Algorithmen befasst, realisiert oder unterstützt. Insbesondere stärken die Algorithmen die Kapselung und Abstraktion (und damit die Modularität) und sind durch die Verwendung von Vorlagen polymorph.
quelle
Meiner Meinung nach geht es bei STL mehr um Algorithmen über iterierbare Container als um OO.
Es definiert eine gemeinsame Schnittstelle (den Iterator), die implementiert werden soll, um die Algorithmen zu verwenden.
C / C ++ - Iteratoren werden in Java und C # als enumerator / enumeratable bezeichnet
Vielleicht ist STL aspektorientierter als OO.
quelle
Wo um alles in der Welt hast du das gehört?
Die entscheidenden Grundsätze der Objektorientierung sind Kapselung und Abstraktion.
virtual
Funktionen sind nur ein Mittel, mit dem dies erreicht wird. Sie sind für die tatsächliche Objektorientierung überhaupt nicht erforderlich. In der Tat ist eine Vorlage ein perfekt geeignetes Mittel. Es ist vielleicht keine Vererbung, aber es ist immer noch eine Art Polymorphismus. Und einige Klassen erfordern keine.Die Container der Standardbibliothek sind absolut objektorientiert. Sie kapseln alle unnötigen Details von der Schnittstelle und abstrahieren die Implementierung so weit wie möglich.
quelle
Die OOP-Implementierung an sich bedeutet nichts, bis Sie nicht definieren, was Sie unter "Objekt" verstehen. Wenn Objekte Werte sind (keine Entitäten, wie die meisten sogenannten OOP-Sprachen, aber C ++ annimmt), dann ist STL OOP, andernfalls nein.
Angenommen, dieses Codefragment:
Sind
a
undb
zwei Darstellungen derselben lebenden Person oder nur zwei lebende Pesons mit demselben Namen?Was ist das Objekt?
a
,b
Oder die lebende Person (en) sie vertreten?Außerdem ist die C ++ - Vererbung ein technischer Aggregationsmechanismus, der sich von der Objektvererbung (dh einer Abstraktion) unterscheidet. Die beiden können zusammenfallen, wenn Sie eine bestimmte Disziplin auferlegen (wie Objekte, die alle durch Indirektion zugänglich und austauschbar sind - das heißt, alle relevanten Methoden sind virtuell), andernfalls können sie unterschiedliche Ziele ansprechen (C ++ - Vererbung ist nichts anderes als eine "implizite Komposition"). )
Vorlagen können auch (über Spezialisierung) einen "Substitutions" -Mechanismus bieten, der auf statischen Typen und nicht auf dynamischen Typen (basierend auf virtuellen Funktionen) basiert, und in diesem Sinne - wenn zur Kompilierungszeit dieselbe Disziplin verwendet wird - eine OOP zur Kompilierungszeit bereitstellen.
Im Wesentlichen ist keines der C ++ - Aggregations- und Dispatching-Schemata für sich genommen OOP oder rechtfertigt OOP. Sie können auch andere Dinge tun. OOP ist eine abstrakte Methode, um Objekte miteinander zu beschreiben und in Beziehung zu setzen. Diese Beziehung kann der Vererbung und dem virtuellen Versand zugeordnet werden, wenn die Objekttypen von der Laufzeitausführung abhängen, oder sie kann der Vorlagenspezialisierung und impliziten Konvertierungen zugeordnet werden, wenn die Objekttypen während der Kompilierung definiert werden können. Vererbung kann nur eine Möglichkeit sein, eine implizite Konvertierung zwischen Referenzen und Zeigern bereitzustellen.
quelle