我是C ++的新手,我真正难倒的第一件事就是如何编写一个可以使用点符号来获取属性的getter / setter。
例如,而不是:
myObj.getAlpha();
它将是
myObj.alpha;
在C ++中使用像点这样的点符号还是设置起来很痛苦?我很难跟踪那些并非完全超出我头脑的例子,所以非常感谢任何指导!
答案 0 :(得分:5)
其他编程语言中的“属性”大多是快速简写 - 一对函数调用的表面简写。其他好处(如元数据)在C ++中并不存在。您有以下选择:
getProperty()
和setProperty()
对功能。我建议你选择最简单的选项,不要放弃类型安全&封装。只要编译器仍然阻止外部类在您的类中搞乱,公共成员变量就可以了。
答案 1 :(得分:4)
您实际上可以将getter和setter实现为
之类的字段myObj.alpha
但这很难设置,需要代理类 这样做的方法是:
template<typename T>
class SetterProxy
{
T *m_T;
public:
SetterProxy(T &property) : m_T(&property) { }
SetterProxy(const SetterProxy&) = delete;
SetterProxy operator =(const SetterProxy&) = delete;
operator T&()
{
return *m_T;
}
T &operator =(T &other)
{
*m_T = other;
return *m_T;
}
}
class MyClass
{
int m_alpha;
public:
SetterProxy<int> alpha;
MyClass() : alpha(m_alpha) { }
}
答案 2 :(得分:4)
考虑使用建议的表示法访问该属性。
alpha
显然是该类的成员,比方说member_t
类型。我们还要说明您要添加的属性是prop_t
类型。现在,如果member_t
与prop_t
相同,那么您还没有真正建立属性,因为您已经提供了对基础成员的免费访问权限,所以我们假设member_t
与{{1}不同}}
然后,prop_t
必须隐式转换为member_t
(这是可行的,但通常不赞成)。
这也意味着prop_t
必须覆盖赋值运算符,以便在设置时存储提供给它的值。
最后,您必须将getter和setter方法添加到实现get / set逻辑的类中,并将member_t
聚合指向这些函数的指针作为成员(以便它可以在隐式转换中调用getter)到member_t
并在重写的赋值运算符中调用setter。
以上所有内容当然是可行的,但是为什么要编写所有这些代码呢?根本没有任何实际好处,只是为了让C ++看起来像一个语言并不会为你赢得太多支持。
答案 3 :(得分:2)
最简单的方法是将alpha
仅作为public
的可访问(可能class
)属性,或变量!
class Obj
{
public:
char alpha;
Obj()
:alpha('a')
{
}
};
int main()
{
Obj myObj;
char letter = myObj.alpha;
// [...]
}
C ++没有您正在寻找的“属性”。
答案 4 :(得分:1)
如果alpha
是该类的公开属性,则可以执行此操作。没有什么特别的东西可以写,内置它。
您可以将getters / setter用于受保护/私有属性,因为它们不能直接从外部访问(因为它们受保护/私有)。
(通过属性我的意思是一个类数据成员/变量,这通常是在C ++中调用的方式)。
答案 5 :(得分:1)
您可以将您的成员变量声明为public,然后您不需要函数来访问它们。然而,这通常不是好的做法。
答案 6 :(得分:1)
就我个人而言,我非常同意get \ set accessors - 其他人可能会反驳,他们有权发表自己的意见。
使用C ++,没有正式的方法来创建属性,但是有一些特定于编译器的方法可用于公开属性,例如C#。
使用Microsoft Visual C ++,您可以使用此处描述的属性:http://msdn.microsoft.com/en-us/library/yhfk0thd%28v=vs.80%29.aspx,我确信还有其他方法可以在其他编译器上执行相同的任务。我的大多数代码都是针对Windows平台编写的,所以我可以练习这种奢侈,如果你打算使用不同的编译器,你应该避免使用它,原因很明显。
可能有某种BOOST实现允许您更安全地执行它,但不要引用我的话。 - 我知道提升可以做一些非常酷的事情。
至于为什么人们会使用吸气剂和固定剂。首先,直接访问对象的数据听起来很混乱,但它也消除了很多灵活性。
考虑使用get \ set访问器,您可以:
- 更容易检测正在访问对象数据的内容
- 实现'虚拟变量'或更确切地说,包含每次调用必须生成的数据的变量。
- 重新设计您的对象,并可能删除\ redesign变量,而不必担心向后兼容性
- 取消get \ set访问器或从继承接口实现它们。
我可能也错过了几个原因。
答案 7 :(得分:0)
我相信你是来自客观的C?
在C ++中,getter和setter只是方法,函数invokation总是需要()
。
您可以将该属性设为公开,并使用myObj.alpha
来访问该属性,但您需要的是直接访问,而不是getter方法。
答案 8 :(得分:0)
我在我的意大利博客上发布了一篇帖子,其中我解释了一种模仿C ++标准中CBuilder的属性结构的方法。就像这里引用一样,我使用CBuilder属性定义语法报告一个名为CPanel的类声明:
class CPanel
{
private:
int m_Width; // Private member for Width property
int m_Height; // Private member for Height property
protected:
void __fastcall SetWidth(int AValue); // Set the Width property
int __fastcall GetWidth(); // Get the Width property
void __fastcall SetHeight(int AValue);// Set the Height property
int __fastcall GetHeight(); // Get the Height property
public:
CPanel()
{
}
__property int Width = {read=GetWidth, write=SetWidth};
__property int Height = {read=GetHeight, write=SetHeight};
}
如您所见,语法非常简单,您可以定义私有成员m_Height和m_Width,受保护的setter和getter方法,最后您可以使用名为__property的特殊关键字定义属性。以下代码显示如何使用main函数中的属性:
int main()
{
CPanel Panel;
Panel.Width = 10;
Panel.Height = 10;
int TmpWidth = Panel.Width;
int TmpHeight = Panel.Height;
}
我们可以模拟为通用属性定义模板类的相同语法,以下代码为此目的显示模板类的定义:
template<typename owner_t,
typename prop_t,
void (owner_t::*setter)(prop_t),
prop_t (owner_t::*getter)()>
class CProperty
{
public:
// Constructor
CProperty(owner_t* owner){m_owner = owner;}
// op = overloading
void operator=(prop_t value)
{
return (m_owner->*setter)(value);
}
// op type overloading
operator prop_t()
{
return (m_owner->*getter)();
}
private:
prop_t* m_owner;
}
感谢上面的模板,我们可以使用标准的c ++语言重新定义我们的CPanel类:
class CPanel
{
private:
int m_Width; // Private member for Width property
int m_Height; // Private member for Height property
protected:
void SetWidth(int AValue); // Set the Width property
int GetWidth(); // Get the Width property
void SetHeight(int AValue);// Set the Height property
int GetHeight(); // Get the Height property
public:
CPanel()
:Width(this), Height(this)
{
}
CProperty<CPanel, int, SetWidth, GetWidth> Width;
CProperty<CPanel, int, SetHeight, GetHeight> Height;
}
正如您所看到的语法非常相似,但现在它是标准的。您可以像以前的主要功能一样使用新的CPanel类:
int main()
{
CPanel Panel;
Panel.Width = 10;
Panel.Height = 10;
int TmpWidth = Panel.Width;
int TmpHeight = Panel.Height;
}
以下是完整帖子的link(意大利语)