I'm really new to C++ and one of the first things that has me really stumped is how to write a getter/setter that can use dot notation to get at a property.
For instance, instead of:
myObj.getAlpha();
it would be
myObj.alpha;
Is using dot notation like this frowned upon in C++ or is it just a pain to setup? I've had a hard time tracking down examples that weren't totally over my head so any guidance is much appreciated!
"Properties" in other programming languages are mostly a quick shorthand - a superficial shorthand for a pair of function calls. The other benefits (like metadata) don't really exist in C++. You have the following options:
getProperty()
and setProperty()
pair of functions. I would suggest going with the simplest option for you, without giving up type safety & encapsulation. As long as the compiler still prevents external classes from messing things up in your class, public member variables are fine.
You can actually implement a getter and setter to a field like
myObj.alpha
but that is hard to setup and requires a proxy class.
The way for doing this is:
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) { }
}
Consider accessing the property using the proposed notation.
alpha
is obviously a member of the class, let's say of type member_t
. Let's also say that the property you intend to add is of type prop_t
. Now if member_t
is the same as prop_t
you haven't really made a property because you have provided free access to the underlying member, so let's assume that member_t
is different from prop_t
.
It then follows that member_t
must have an implicit conversion to prop_t
(which is doable, but usually frowned upon).
It also means that member_t
must override the assignment operator to store the value provided to it when you set it.
Finally, you have to add getter and setter methods to the class which implement the get/set logic, and have member_t
aggregate pointers to these functions as members (so that it can call the getter inside the implicit conversion to prop_t
and call the setter inside the overridden assignment operator).
All of the above is certainly doable, but why would you want to write all this code? There is no tangible benefit at all, and doing it just for the sake of making C++ look like a language it is not won't earn you much support.
The easiest way is to have alpha
as just an accessible (probably public
) attribute of the class
, or a variable !
class Obj
{
public:
char alpha;
Obj()
:alpha('a')
{
}
};
int main()
{
Obj myObj;
char letter = myObj.alpha;
// [...]
}
C++ doesn't have the "properties" that you are looking for.
If alpha
is a public property of the class - you can do that. Nothing special to write for that, its built in.
You would use getters/setters for protected/private properties, because they're not directly accessible from outside (because, well, they're protected/private).
(by property I mean a class data member/variable, that's how its called in C++ usually).
You could declare your member variables public, then you don't need a function to access them. However this is normally not good practice.
Personally, I strongly agree with get\\set accessors - others may argue otherwise, and they are entitled to their own opinion.
With C++, there is no official way to create a property, however there are some compiler-specific methods that you can use to expose properties as you would in, for example, C#.
With Microsoft Visual C++, you can use the properties as is described here: http://msdn.microsoft.com/en-us/library/yhfk0thd%28v=vs.80%29.aspx and I'm sure there are other methods of performing the same task on other compilers. Most of my code is written on and for the windows platform so I can exercise this luxury, if you are planning on working with a different compiler, you should avoid using this for obvious reasons.
There may be some sort of BOOST implementation that allows you to do it more safely, but don't quote me on that. - I know boost can do some pretty cool things though.
As to why people use getters and setters, well. To start, directly accessing an object's data sounds messy, but it also removes a lot of flexibility.
Consider with get\\set accessors you can:
-More easily detect what is accessing your objects data
-Implement 'virtual variables' or rather, variables that contain data that must be generated per call.
-Redesign your object and possibly remove\\redesign variables without having to worry about backwards compatibility
-Override the get\\set accessors or implement them form an inherited interface.
I'm probably missing a couple reasons as well.
I posted on the my Italian blog a post where I explain a way to emulate the property construct of the CBuilder in the C++ standard. Just as reference here I report a class declaration called CPanel using the CBuilder syntax for property definition:
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};
}
As you see the the syntax is very simple, you can define the private members m_Height and m_Width, the protected setter and getter methods and finally you can define your properties using the special keyword called __property. The following code shows you how to use the properties in your main function:
int main()
{
CPanel Panel;
Panel.Width = 10;
Panel.Height = 10;
int TmpWidth = Panel.Width;
int TmpHeight = Panel.Height;
}
We can emulate the same syntax defining a template class for our generic property, the following code shows a definition of a template class for this purpose:
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;
}
Thanks the above template we can redefine our CPanel class using the standard c++ language:
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;
}
As you can see the syntax is very similar, but now it is standard. You can use the new CPanel class like previous main function:
int main()
{
CPanel Panel;
Panel.Width = 10;
Panel.Height = 10;
int TmpWidth = Panel.Width;
int TmpHeight = Panel.Height;
}
Here is a link to the full post (in Italian language)
I believe you are coming from objective C?
In C++, getters and setters are just methods, and functions invokation always requires ()
.
You can make the property public, and use myObj.alpha
to access it, although what you want is direct access, not a getter method.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.