Подтвердить что ты не робот

С# -подобные свойства на языке С++?

В С#/.NET вы можете сделать что-то вроде этого:

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

Однако вышеупомянутый код фактически не взаимодействует с текстом someThing напрямую, он использует свойство get и set. Точно так же можно использовать свойства только для чтения.

Есть ли способ сделать что-то подобное в native C++? (не С++.NET)

4b9b3361

Ответ 1

В .NET свойствах синтаксический сахар для реальных get и set функций, которые испускаются за кулисами (на самом деле они больше, чем синтаксический сахар, потому что свойства испускаются в результате ИЛ и могут быть использованы с Reflection). Поэтому в С++ вам нужно будет явно писать эти функции, поскольку нет такого понятия, как свойство.

Ответ 2

ПРЕДУПРЕЖДЕНИЕ: Это ответ в уши и ужасно!

Да, это возможно:)

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 ()
};

Затем объявите свой класс, объявив свойства для своих членов:

class Test
{
private:
    std::string _label;
    int         _width;

public:
    Test() : Label(_label)
           , Width(_width)
    {
    };

    Property<std::string> Label;
    Property<int>         Width;
};

И вызовите стиль С#!

Test a;
a.Label = "blah";
a.Width = 5;

std::string label = a.Label;
int width = a.Width;

Ответ 3

Я предупреждаю вас: это не родной С++; это только для Microsoft. Но вы можете использовать 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 (свойство).

Ответ 4

Ответ Moo-Juice выглядит очень круто, но имеет недостаток: вы не можете использовать эти свойства, как обычные выражения типа T, как вы можете в С#.

Например,

  • a.text.c_str() не будет компилироваться (‘class Property<std::basic_string<char> >’ has no member named ‘c_str’)
  • std::cout << a.text не будет компилироваться либо (template argument deduction/substitution failed)

Я бы предложил следующее улучшение template<typename T> class Property:

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

Затем вы можете получить доступ к элементам свойств с помощью (), например:

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

И вы можете использовать свойство в выражениях, где должен быть выведен тип:

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

Ответ 5

Свойство в .NET связано с функцией члена get и/или set, поэтому оно действительно просто синтаксическое сахар. Ближе всего вы можете использовать С++, чтобы использовать перегрузку, чтобы дать получателю и настройщику одно и то же имя:

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

Очевидно, вам все равно придется указывать скобки для вызова:

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

Ответ 6

Да, но это конкретный поставщик. У Microsoft есть declspec (свойство). Реализация С++ Builder немного более продвинута (через ключевое слово __property для конкретного поставщика), в котором вы могли бы индексировать аксессоры (которые могут быть любого типа, которые вы хотите).

Также проверьте это (не полагаясь на ключевые слова поставщика): http://www.codeproject.com/KB/cpp/cpp_property_indexer.aspx

Ответ 7

#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;
}

// ------------------------------------------------------------------

Ответ 8

Нет, нет. Вы просто создадите функции getter и setter:

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

Ответ 9

Почему бы не использовать язык С# вместо С++ для собственной разработки? Для этого вы можете использовать утилиту IL2BC для генерации собственного кода из источника С# и/или байт-кода MSIL?

IL2BC можно найти на этом сайте

http://csnative.codeplex.com