000
30.07.2005, 10:55 Uhr
(un)wissender
Niveauwart
|
Wenn jemand das Property-Konzept in C# kennt, dann weiß er, was ich versuche, in C++ zu implementieren. Ein erster Ansatz sieht so aus:
Um Werte auszulesen und zuzuweisen, gibt es einen Accessor. Der kann als template-Argument angepasst werden, damit der Benutzer des Property eigene Logik zum setzen und auslesen der Variable, die das Property kapselt, hinzufügen kann. Der DefaultAccessor tut nichts, außer den Wert zu liefern oder ihn zu setzen.
C++: |
/Für getter und setter die mehr Logik haben, default wird nichts extra getan. template<typename T> class DefaultAccessor { public: //getter const T operator()(const T value) const { return value; } //setter void operator()(T & value, const T assignValue) { value = assignValue; } };
|
So sieht die Signatur eines Property aus. ValueType ist der Varibalentyp, bspw ein int. HasSetter sagt aus, ob der Wert der Variablen nur gelesen oder auch gesetzt werden kann. Der Accessor sollte klar sein.
C++: |
//Die Signatur der property-Klasse. template < typename ValueType, bool HasSetter = true, template <typename T> class Accessor = DefaultAccessor > class property { };
|
Spezialisieren von property für HasSetter=true.
C++: |
template <typename ValueType, template <typename T> class Accessor> class property<ValueType, true, Accessor> { public: explicit property(const ValueType value) : m_value(value) { } //setter property operator=(const ValueType value) { Accessor<ValueType>()(m_value, value); return *this; } //getter operator const ValueType() const { return Accessor<ValueType>()(m_value); } private: ValueType m_value; };
|
Spezialisieren von property für HasSetter=false.
C++: |
template <typename ValueType, template <typename T> class Accessor> class property<ValueType, false, Accessor> { public: explicit property(const ValueType value) : m_value(value) { } //getter operator const ValueType() const { return Accessor<ValueType>()(m_value); } private: ValueType m_value; };
|
Eine Kleine Testklasse mit einem einfach int-Property:
C++: |
class PropertyTest { public: PropertyTest(int test) : Test0(test) { } property<int> Test0; };
|
Die main zum testen:
C++: |
int main() { PropertyTest test(9); std::cout << "\nTest0 (Primitive with setter and without accessor):\n"; std::cout << test.Test0 << '\n'; test.Test0 = 7; std::cout << test.Test0 <<'\n';
|
Was meint ihr dazu? Habt ihr Verbesserungsvorschläge, Ideen oder glaubt ihr, dass ist alles überflüssig? Ein Problem stellen noch die komplexen Datentypen dar, die zu oft kopiert werden. Da müßte man wohl noch weitere template-Spezialisierungen einführen, vermutet ich mal.
Ich finde das Konzept toll, weil man sehr schnell Variablen dekarieren kann, ohne ewig getter und setter schreiben zu müssen. Die Benutzung ist auch einfacher als immer setter und getter aufrufen zu müssen.
Speichertechnisch gibt es keinen Overhead und Performanz sollte auch optimal sein (für primitive Datentypen). -- Wer früher stirbt ist länger tot. Dieser Post wurde am 30.07.2005 um 11:00 Uhr von (un)wissender editiert. |