ejemplos descargar definicion compiler caracteristicas c++

descargar - ¿Las propiedades similares a C#en C++ nativo?



c++ manual (10)

En C# / .NET puedes hacer algo como esto:

someThing.text = "blah"; String blah = someThing.text;

Sin embargo, el código anterior no interactúa con la cadena de texto de someThing directamente, usa una propiedad de obtener y establecer. Del mismo modo, se pueden utilizar propiedades de solo lectura.

¿Hay una manera de hacer algo similar en C++ nativo? (no C ++ .NET)


¿Por qué no usar el lenguaje C # en lugar de C ++ para el desarrollo nativo? ¿Para eso puede usar la utilidad IL2BC para generar código nativo de código fuente de C # y / o código de MSIL?

IL2BC se puede encontrar en este sitio

http://csnative.codeplex.com


En .NET, las propiedades son azúcar sintáctica para las funciones reales de get y set que se emiten detrás de escena (de hecho, son más que azúcar sintáctica porque las propiedades se emiten en la IL resultante y podrían usarse con Reflexión). Así que en C ++ necesitaría escribir explícitamente esas funciones ya que no existe una noción como propiedad.


La respuesta de Moo-Juice parece realmente genial, pero tiene un inconveniente: no puede usar estas propiedades como expresiones normales de tipo T , como puede hacerlo en C #.

Por ejemplo,

  • a.text.c_str() no compilará ( ''class Property<std::basic_string<char> >'' has no member named ''c_str'' )
  • std::cout << a.text tampoco se compilará ( template argument deduction/substitution failed )

Yo sugeriría la siguiente mejora a la template<typename T> class Property :

T& operator() () { return _value; } T const& operator() () const { return _value; }

Luego puede acceder a los miembros de la propiedad con () , como por ejemplo:

char const *p = a.text().c_str();

Y puede usar la propiedad en expresiones donde se debe deducir el tipo:

std::cout << a.text();


No no hay. Solo crearías funciones de getter y setter:

someThing.setText("blah"); std::string blah = someThing.getText();


Probablemente, la mejor opción actualmente es usar el __declspec( property( get=get_func_name, put=put_func_name ) ) PropertyType PropertyName .

  • también es apoyado por clang,
  • se convierte en su getter / setter cuando se compila (no agregará ninguna nueva variable),
  • en uso, es lo más cercano a una propiedad real (puede acceder a la propiedad de una propiedad ...).

Pero si estás usando otros compiladores, podrías usar macros:

#define PROPERTY_GEN(Class, Type, Name, GetMethod, SetMethod) / class Property_##Name { / public: / Property_##Name(Class* parent) : _parent(parent) { } / Type operator = (Type value) / { / _parent->SetMethod(value); / return _parent->GetMethod(); / } / operator Type() const / { / return static_cast<const Class*>(_parent)->GetMethod(); / } / Property_##Name& operator =(const Property_##Name& other) / { / operator=(other._parent->GetMethod()); return *this; / }; / Property_##Name(const Property_##Name& other) = delete; / private: / Class* _parent; / } Name { this }; // PROPERTY - Declares a property with the default getter/setter method names. #define PROPERTY(Class, Type, Name) / PROPERTY_GEN(Class, Type, Name, get_##Name, set_##Name)

Entonces úsalos como:

class SomeClass { public: PROPERTY(SomeClass, int, Value) int get_Value() const { return _value; } void set_Value(int value) { _value = value; } private: int _value = 0; }; int main() { SomeClass s, c; s.Value = 5; c.Value = 3 * s.Value; s.Value = c.Value; }

También puede agregar otras variantes de macro para propiedades de solo lectura, de solo escritura y de no constantes de solo lectura. Para poder acceder a las sub-propiedades a través de ->, puede agregar operadores-> sobrecargas a la macro.

En comparación con __declspec (propiedad (...)) de microsoft, los métodos getter y setter pueden hacerse privados, pero esto no es una ventaja real, ya que el cliente puede necesitar la dirección de un getter / setter a veces. También hay una desventaja de tener una variable _parent adicional para cada propiedad, y tendría que definir explícitamente los constructores de copia para las clases primarias si se usan.


Sí, pero es específico del vendedor. Microsoft tiene declspec (propiedad). La implementación de C ++ Builder es un poco más avanzada (a través de la palabra clave __property específica del proveedor) en cuanto a que podría tener indexadores de acceso (que pueden ser de cualquier tipo que desee).

También revise esto (sin depender de palabras clave específicas del proveedor): http://www.codeproject.com/KB/cpp/cpp_property_indexer.aspx


Te advierto: no es C ++ nativo; es específico de Microsoft solamente . Pero puedes usar declspec(property) :

struct S { int i; void putprop(int j) { i = j; } int getprop() { return i; } __declspec(property(get = getprop, put = putprop)) int the_prop; }; int main() { S s; s.the_prop = 5; // THERE YOU GO return s.the_prop; }

cf MSDN, declspec (propiedad) .


Una propiedad en .NET está asociada con una función de get y / o set un miembro, por lo que en realidad es solo azúcar sintáctica. Lo más cercano que puedes conseguir con C ++ es usar la sobrecarga para dar el mismo nombre al captador y al configurador:

const std::string &test() const { return text_; } void test(const std::string &value) { text_ = value; }

Obviamente, todavía tendrá que proporcionar paréntesis para la llamada:

someThing.text("blah"); String blah = someThing.text();


ADVERTENCIA: ¡Esta es una respuesta irónica y es terrible!

Sí, es algo posible :)

template<typename T> class Property { private: T& _value; public: Property(T& value) : _value(value) { } // eo ctor Property<T>& operator = (const T& val) { _value = val; return *this; }; // eo operator = operator const T&() const { return _value; }; // eo operator () };

Luego declara tu clase, declarando propiedades para tus miembros:

class Test { private: std::string _label; int _width; public: Test() : Label(_label) , Width(_width) { }; Property<std::string> Label; Property<int> Width; };

¡Y llame al estilo C #!

Test a; a.Label = "blah"; a.Width = 5; std::string label = a.Label; int width = a.Width;


#include <iostream> #include <string> using namespace std; // ------------------------------------------------------------------ #define PROPERTY_GET_SET(CLASS, NAME, TYPE) GetSetProperty<CLASS, TYPE> NAME() { return GetSetProperty<CLASS, TYPE>(this, &CLASS::get_##NAME, &CLASS::set_##NAME); } #define PROPERTY_GET(CLASS, NAME, TYPE) GetProperty<CLASS, TYPE> NAME() { return GetProperty<CLASS, TYPE>(this, &CLASS::get_##NAME); } #define PROPERTY_SET(CLASS, NAME, TYPE) SetProperty<CLASS, TYPE> NAME() { return SetProperty<CLASS, TYPE>(this, &CLASS::set_##NAME); } template <typename CLASS, typename TYPE> struct GetSetProperty { typedef TYPE (CLASS::*Getter_t)() const; typedef void (CLASS::*Setter_t)(TYPE); GetSetProperty(CLASS* instance, Getter_t getter, Setter_t setter) : m_instance(instance), m_getter(getter), m_setter(setter) {} operator TYPE() const { return (this->m_instance->*this->m_getter)(); } GetSetProperty<CLASS, TYPE>& operator=(TYPE value) { (this->m_instance->*this->m_setter)(value); return *this; } CLASS* const m_instance; const Getter_t m_getter; const Setter_t m_setter; }; template <typename CLASS, typename TYPE> struct GetProperty { typedef TYPE (CLASS::*Getter_t)() const; GetProperty(CLASS* instance, Getter_t getter) : m_instance(instance), m_getter(getter) {} operator TYPE() const { return (this->m_instance->*this->m_getter)(); } CLASS* const m_instance; const Getter_t m_getter; }; template <typename CLASS, typename TYPE> struct SetProperty { typedef void (CLASS::*Setter_t)(TYPE); SetProperty(CLASS* instance, Setter_t setter) : m_instance(instance), m_setter(setter) {} SetProperty<CLASS, TYPE>& operator=(TYPE value) { (this->m_instance->*this->m_setter)(value); return *this; } CLASS* const m_instance; const Setter_t m_setter; }; template <typename CLASS, typename TYPE> ostream& operator<<(ostream& ostr, const GetSetProperty<CLASS, TYPE>& p) { ostr << (p.m_instance->*p.m_getter)(); return ostr; } template <typename CLASS, typename TYPE> ostream& operator<<(ostream& ostr, const GetProperty<CLASS, TYPE>& p) { ostr << (p.m_instance->*p.m_getter)(); return ostr; } // ------------------------------------------------------------------ class Dummy { public: Dummy() : m_value1(42) {} PROPERTY_GET_SET(Dummy, Value1, int); PROPERTY_GET_SET(Dummy, Value2, const string&); protected: virtual int get_Value1() const { return this->m_value1; } virtual void set_Value1(int value) { this->m_value1 = value; } virtual const string& get_Value2() const { return this->m_value2; } virtual void set_Value2(const string& value) { this->m_value2 = value; } private: int m_value1; string m_value2; }; int main(int argc, char* argv[]) { Dummy d; cout << d.Value1() << endl; d.Value1() = 3; cout << d.Value1() << endl; cout << d.Value2() << endl; d.Value2() = "test"; cout << d.Value2() << endl; return 0; } // ------------------------------------------------------------------