C++ 本机C++;?

C++ 本机C++;?,c++,C++,在/中,您可以执行以下操作: someThing.text = "blah"; String blah = someThing.text; 然而,上面的代码实际上并没有直接和某物的文本字符串交互,它使用get和set属性。同样,也可以使用只读属性 有没有一种方法可以在本机中执行类似的操作?(C++中没有.c+.net) in .NET属性是实际的代码糖,用于实际的代码>获取 >和>代码> SET/COD>函数,这些函数是在场景后面发射的(实际上它们不仅仅是语法糖,因为属性是在所得的IL中发射的

在/中,您可以执行以下操作:

someThing.text = "blah";
String blah = someThing.text;
然而,上面的代码实际上并没有直接和某物的文本字符串交互,它使用get和set属性。同样,也可以使用只读属性


有没有一种方法可以在本机中执行类似的操作?(C++中没有.c+.net)

in .NET属性是实际的代码糖,用于实际的代码>获取<代码> >和>代码> SET/COD>函数,这些函数是在场景后面发射的(实际上它们不仅仅是语法糖,因为属性是在所得的IL中发射的,并且可以用于反射)。所以在C++中,你需要显式地写这些函数,因为没有这样的属性。

不,没有。您只需创建getter和setter函数:

someThing.setText("blah");
std::string blah = someThing.getText();
中的属性与
get
和/或
set
成员函数相关联,因此它实际上只是一种语法糖。与C++最接近的是使用重载给GETER和SETER同名:

const std::string &test() const { return text_; }
void test(const std::string &value) { text_ = value; }
显然,您仍然需要为调用提供括号:

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

我警告你,它不是完全兼容的本地C++:微软专用C++。p> Microsoft编译器允许您通过以下方式使用
declspec(属性)

struct S {
   int i;
   void putprop(int j) { 
      i = j;
   }

   int getprop() {
      return i;
   }

   // here you define the property and the functions to call for it
   __declspec(property(get = getprop, put = putprop)) int the_prop;
};

int main() {
   S s;
   s.the_prop = 5;    // THERE YOU GO
   return s.the_prop;
}

有关更多详细信息,请参阅Microsoft文档:。

警告:这是一个开玩笑的回答,非常糟糕

是的,有点可能:)


是的,但这是特定于供应商的。Microsoft已删除了declspec(属性)。 C++Builder的实现更高级一些(通过特定于供应商的_属性关键字),因为您可以有索引访问器(可以是您想要的任何类型)

还可以查看此信息(不依赖供应商特定的关键字):

\include
#包括
使用名称空间std;
// ------------------------------------------------------------------
#定义属性(类、名称、类型)GetSetProperty NAME(){return GetSetProperty(this,&CLASS::GET###NAME,&CLASS::SET##NAME);}
#定义属性(类、名称、类型)GetProperty NAME(){return GetProperty(this,&CLASS::GET_35;#NAME);}
#定义属性集(类、名称、类型)SetProperty NAME(){return SetProperty(this,&CLASS::SET_35;#NAME);}
模板
结构GetSetProperty{
typedef类型(类::*Getter_t)()常量;
typedef void(类::*Setter_t)(类型);
GetSetProperty(类*实例,Getter\u t Getter,Setter\u t Setter):m_实例(实例),m_Getter(Getter),m_Setter(Setter){}
运算符类型()常量{return(this->m_实例->*this->m_getter)(;}
GetSetProperty&operator=(类型值){(this->m_实例->*this->m_setter)(值);返回*this;}
类*常量m_实例;
常量Getter\u t m\u Getter;
常数设定器;
};
模板
结构GetProperty{
typedef类型(类::*Getter_t)()常量;
GetProperty(类*实例,Getter\u t Getter):m_实例(实例),m_Getter(Getter){}
运算符类型()常量{return(this->m_实例->*this->m_getter)(;}
类*常量m_实例;
常量Getter\u t m\u Getter;
};
模板
结构集合属性{
typedef void(类::*Setter_t)(类型);
SetProperty(类*实例,Setter\u t Setter):m_实例(实例),m_Setter(Setter){}
SetProperty&operator=(类型值){(this->m_实例->*this->m_setter)(值);返回*this;}
类*常量m_实例;
常数设定器;
};
模板
ostream&operatorm_value2=value;}
私人:
int m_值1;
字符串m_值2;
};
int main(int argc,char*argv[]){
虚拟d;

coutMoo Juice的答案看起来很酷,但有一个缺点:不能像在C#中那样使用
t
类型的正规表达式那样使用这些属性

比如说,

  • a.text.c_str()
    不会编译(
    'class Property'没有名为'c_str'的成员

  • std::cout目前最好的选择可能是使用微软的
    declspec(property(get=get\u func\u name,put=put\u func\u name))PropertyType PropertyName
    属性

    • 它也得到了叮当声的支持
    • 编译时,它会转换为getter/setter(不会添加任何新变量)
    • 在使用中,它是最接近不动产的东西(可以访问不动产的不动产…)
    但如果使用其他编译器,则可以使用宏:

    #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)
    
    您还可以为只读、只读属性和只读非常量getter添加其他宏变量。为了能够通过->访问子属性,您可以向宏添加运算符->重载

    与microsoft的_declspec(property(…))相比,getter和setter方法可以私有化,但这并不是真正的优势,因为客户端有时可能需要获取getter/setter的地址。
    还有一个缺点是,每个属性都有一个额外的_parent变量,如果使用父类,则需要显式定义它们的复制构造函数。

    通过使用std::function,您可以获得非常接近的结果

    首先创建模板化属性类:

    #include <functional>
    
    template<class T>
    class Property
    {
        std::function<T (void)> _get;
        std::function<void(const T&)> _set;
    public:
        Property(
            std::function<T (void)> get,
            std::function<void(const T&)> set)
            : _get(get),
              _set(set)
        { }
    
        Property(
            std::function<T(void)> get)
            : _get(get),
              _set([](const unsigned int&){})
        { }
    
        operator T () const { return _get(); }
        void operator = (const T& t) { _set(t); }
    };
    

    我认为这是一个语法糖衣,就像你在C++中得到的那样:

    但是它如何知道用户想要获取还是设置?需要操作符重载吗?当它在赋值操作符的左手边时(<代码>=< /代码>)你正在设置,当它在你得到的右边时,编译器足够聪明来解决这个问题。在上面写两个函数将返回一个引用,一个函数将返回一个常量引用是非常有用的,编译器将确定何时调用哪个。但这将允许在任何地方进行这些调用- 1,如“在C++中,你需要明确地写出那些函数,因为没有这样的属性”是简单的,直接错误的。而且还有其他方法来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;
    }
    
    // ------------------------------------------------------------------
    
    T& operator() ()
    {
        return _value;
    }
    T const& operator() () const
    {
        return _value;
    }
    
     char const *p = a.text().c_str();
    
    std::cout << a.text();
    
    #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)
    
    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;
    }
    
    #include <functional>
    
    template<class T>
    class Property
    {
        std::function<T (void)> _get;
        std::function<void(const T&)> _set;
    public:
        Property(
            std::function<T (void)> get,
            std::function<void(const T&)> set)
            : _get(get),
              _set(set)
        { }
    
        Property(
            std::function<T(void)> get)
            : _get(get),
              _set([](const unsigned int&){})
        { }
    
        operator T () const { return _get(); }
        void operator = (const T& t) { _set(t); }
    };
    
    class Test
    {
    private:
        std::string  _label;
    
    public:
        Property<std::string> Label = Property<std::string>
        (
            [this]()->std::string
            {
                return this->_label;
            },
            [this](const std::string& value)
            {
                this->_label = value;
            }
        );
        Property<unsigned int> LabelSize = Property<unsigned int>
        (
            [this]()->unsigned int
            {
                return this->_label.size();
            }
        );
    };
    
    Test test;
    test.Label = "std functional";
    
    std::cout << "label      = " << std::string(test.Label) << std::endl
              << "label size = " << int(test.LabelSize) << std::endl;
    
    label      = std functional
    label size = 14