Wenn Sie auf der Suche nach relativ einfachen C++ Reflexion - Ich habe aus verschiedenen Quellen Makro / Defines gesammelt, und kommentiert sie aus, wie sie funktioniert. Sie können die Header Dateien von hier herunterladen:
https://github.com/tapika/TestCppReflect/blob/master/MacroHelpers.h
Satz von Definitionen und darüber hinausgehende Funktionen:
https://github.com/tapika/TestCppReflect/blob/master/CppReflect.h https://github.com/tapika/TestCppReflect/blob/master/CppReflect.cpp https://github.com/tapika/TestCppReflect/blob/master/TypeTraits.h
Die Beispielanwendung befindet sich ebenfalls im Git-Repository, und zwar hier: https://github.com/tapika/TestCppReflect/
Ich kopiere ihn hier teilweise mit Erläuterungen:
#include "CppReflect.h"
using namespace std;
class Person
{
public:
// Repack your code into REFLECTABLE macro, in (<C++ Type>) <Field name>
// form , like this:
REFLECTABLE( Person,
(CString) name,
(int) age,
...
)
};
void main(void)
{
Person p;
p.name = L"Roger";
p.age = 37;
...
// And here you can convert your class contents into xml form:
CStringW xml = ToXML( &p );
CStringW errors;
People ppl2;
// And here you convert from xml back to class:
FromXml( &ppl2, xml, errors );
CStringA xml2 = ToXML( &ppl2 );
printf( xml2 );
}
REFLECTABLE
define verwendet Klassenname + Feldname mit offsetof
- um festzustellen, an welcher Stelle im Speicher sich ein bestimmtes Feld befindet. Ich habe versucht, die .NET-Terminologie so weit wie möglich zu übernehmen, aber C++ und C# sind unterschiedlich, daher ist es nicht 1 zu 1. Das gesamte C++-Reflexionsmodell befindet sich in TypeInfo
y FieldInfo
Klassen.
Ich habe pugi xml parser verwendet, um Demo-Code in xml zu holen und es zurück von xml wiederherzustellen.
Die Ausgabe des Democodes sieht also wie folgt aus:
<?xml version="1.0" encoding="utf-8"?>
<People groupName="Group1">
<people>
<Person name="Roger" age="37" />
<Person name="Alice" age="27" />
<Person name="Cindy" age="17" />
</people>
</People>
Es ist auch möglich, eine beliebige Klasse/Struktur von Drittanbietern über die TypeTraits-Klasse und eine partielle Template-Spezifikation zu aktivieren - um Ihre eigene TypeTraitsT-Klasse zu definieren, ähnlich wie bei CString oder int - siehe Beispielcode in
https://github.com/tapika/TestCppReflect/blob/master/TypeTraits.h#L195
Diese Lösung ist für Windows / Visual Studio geeignet. Es ist möglich, sie auf andere Betriebssysteme/Compiler zu portieren, aber das habe ich nicht getan. (Fragen Sie mich, wenn Sie wirklich wie Lösung, ich könnte in der Lage sein, Ihnen zu helfen)
Diese Lösung ist für die einmalige Serialisierung einer Klasse mit mehreren Unterklassen geeignet.
Wenn Sie jedoch nach einem Mechanismus suchen, um Klassenteile zu serialisieren oder sogar zu kontrollieren, welche Funktionalität Reflection-Aufrufe erzeugen, können Sie sich die folgende Lösung ansehen:
https://github.com/tapika/cppscriptcore/tree/master/SolutionProjectModel
Ausführlichere Informationen finden Sie in einem youtube-Video:
C++ Laufzeittyp-Reflexion https://youtu.be/TN8tJijkeFE
Ich versuche, etwas genauer zu erklären, wie die C++-Reflexion funktioniert.
Der Beispielcode sieht zum Beispiel so aus:
https://github.com/tapika/cppscriptcore/blob/master/SolutionProjectModel/testCppApp.cpp
c.General.IntDir = LR"(obj\$(ProjectName)_$(Configuration)_$(Platform)\)";
c.General.OutDir = LR"(bin\$(Configuration)_$(Platform)\)";
c.General.UseDebugLibraries = true;
c.General.LinkIncremental = true;
c.CCpp.Optimization = optimization_Disabled;
c.Linker.System.SubSystem = subsystem_Console;
c.Linker.Debugging.GenerateDebugInformation = debuginfo_true;
Aber jeder Schritt hier führt tatsächlich zu einem Funktionsaufruf Verwendung von C++-Eigenschaften mit __declspec(property(get =, put ... )
.
die vollständige Informationen über C++-Datentypen, C++-Eigenschaftsnamen und Klasseninstanzzeiger in Form von Pfaden erhält, und auf der Grundlage dieser Informationen können Sie xml, json erzeugen oder sogar über das Internet serialisieren.
Beispiele für solche virtuellen Callback-Funktionen finden Sie hier:
https://github.com/tapika/cppscriptcore/blob/master/SolutionProjectModel/VCConfiguration.cpp
Siehe Funktionen ReflectCopy
und die virtuelle Funktion ::OnAfterSetProperty
.
Da das Thema jedoch sehr fortgeschritten ist, empfehle ich, sich zuerst das Video anzusehen.
Wenn Sie Verbesserungsvorschläge haben, können Sie mich gerne kontaktieren.
21 Stimmen
Pech gehabt, ohne Makros und andere Vorverarbeitungen geht es nicht, denn die erforderlichen Metadaten gibt es nicht es sei denn, Sie erstellen sie manuell mit Hilfe von Makro-Vorverarbeitungsmagie.
7 Stimmen
Die Informationen, die Sie von RTTI erhalten können, reichen jedoch nicht aus, um die meisten Dinge zu tun, für die Sie eigentlich eine Reflexion benötigen würden. Sie können zum Beispiel nicht über die Mitgliedsfunktionen einer Klasse iterieren.