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