Implementing a Property in C++
Abstract
This project tries to simulate the property behavior that exists in C# (and other languages...) in C++, without using any extensions. Most libraries or compilers that implement properties in C++ use extensions, as in Managed C++ or C++ Builder, or they use the set and get methods that look like normal methods, not properties.
Details
Let's first see what a property is. A property acts like a field or member variable, in that is uses the library, but it accesses the underlying variable through the read or write methods or the set or get methods.
For example, if I have class A and property Count, I can write the following code:
A foo; cout << foo.Count;
The Count actualy calls the get function that returns the value of the required variable. One of the main advantages of using a property instead of directly using the variable is that you can set the property as read-only (you are allowed only to read the variable without changing it), write-only, or both read and write. So, let's begin implementing it:
We need to be able to do the following:
int i = foo.Count; //-- Will call the get function to
// get the underlying value --
foo.Count = i; //-- Will call the set function to set
// the value --
So, it obvious that we need to overload the '=' sign to set the variable, and also the return type (which we will now have later).
We will implement a class called property, which will act exactly like a property, as in the following:
template<typename Container, typename ValueType, int nPropType>
class property {}
This Template class will represent our property. The Container is the type of class that will contain the variable, the set & get methods, and the property. ValueType is the type of the internal variable itself, and nPropType is the access type of the property read-only, write-only, or read/write.
Now we need to set a pointer to the set and get methods from the container class to the property and also override the '=' operator so that the property will act like the variable. So, let's see the full listing of the property class:
#define READ_ONLY 1
#define WRITE_ONLY 2
#define READ_WRITE 3
template <typename Container, typename ValueType, int nPropType>
class property
{
public:
property()
{
m_cObject = NULL;
Set = NULL;
Get = NULL;
}
//-- This to set a pointer to the class that contain the
// property --
void setContainer(Container* cObject)
{
m_cObject = cObject;
}
//-- Set the set member function that will change the value --
void setter(void (Container::*pSet)(ValueType value))
{
if((nPropType == WRITE_ONLY) || (nPropType == READ_WRITE))
Set = pSet;
else
Set = NULL;
}
//-- Set the get member function that will retrieve the value --
void getter(ValueType (Container::*pGet)())
{
if((nPropType == READ_ONLY) || (nPropType == READ_WRITE))
Get = pGet;
else
Get = NULL;
}
//-- Overload the '=' sign to set the value using the set
// member --
ValueType operator =(const ValueType& value)
{
assert(m_cObject != NULL);
assert(Set != NULL);
(m_cObject->*Set)(value);
return value;
}
//-- To make possible to cast the property class to the
// internal type --
operator ValueType()
{
assert(m_cObject != NULL);
assert(Get != NULL);
return (m_cObject->*Get)();
}
private:
Container* m_cObject; //-- Pointer to the module that
// contains the property --
void (Container::*Set)(ValueType value);
//-- Pointer to set member function --
ValueType (Container::*Get)();
//-- Pointer to get member function --
};
So, now let's see it piece by piece:
In the following code, just set the Container pointer to a valid instance that will have the property:
void setContainer(Container* cObject)
{
m_cObject = cObject;
}
In the following code, set a pointer to the get and set member functions of the container class. The only restriction is that the set must have a single parameter and return void and the get no paramter, but return the value type:
//-- Set the set member function that will change the value -- void setter(void (Container::*pSet)(ValueType value)) { if((nPropType == WRITE_ONLY) || (nPropType == READ_WRITE)) Set = pSet; else Set = NULL; } //-- Set the get member function that will retrieve the value -- void getter(ValueType (Container::*pGet)()) { if((nPropType == READ_ONLY) || (nPropType == READ_WRITE)) Get = pGet; else Get = NULL; }
In the following code, the first operator is the '='; it calls the set member of the container and gives it the value. The second part is to make the entire property class act as the ValueType so it returns the return of the get function:
//-- Overload the '=' sign to set the value using the set member -- ValueType operator =(const ValueType& value) { assert(m_cObject != NULL); assert(Set != NULL); (m_cObject->*Set)(value); return value; } //-- To make possible to cast the property class to the // internal type -- operator ValueType() { assert(m_cObject != NULL); assert(Get != NULL); return (m_cObject->*Get)(); }
So, let's see how to use it now:
As shown below, the PropTest class implements a simple property called Count. The actual value will be stored and retrieved from the private member variable "m_nCount", through the get and set methods. The get and set methods can have any name as long as their address is passed to the property class as shown in the constructor of the PropTest, in the line "property<PropTest,int,READ_WRITE> Count; " that we have a read & write property of type integer in class PropTest called Count. Now you can call Count as a normal member variable, but in fact you call the set and get methods indirectly.
The initialization shown in the constructor of the PropTest class is necessary for the property class to work.
class PropTest
{
public:
PropTest()
{
Count.setContainer(this);
Count.setter(&PropTest::setCount);
Count.getter(&PropTest::getCount);
}
int getCount()
{
return m_nCount;
}
void setCount(int nCount)
{
m_nCount = nCount;
}
property<PropTest,int,READ_WRITE> Count;
private:
int m_nCount;
};
As shown below, you use the Count property as if it were a normal variable.
int i = 5,j; PropTest test; test.Count = i; //-- call the set method -- j= test.Count; //-- call the get method --
For read-only, you create an instance for the property as follows:
property<PropTest,int,READ_ONLY > Count;
For write-only, you create an instance for the property as follows:
property<PropTest,int,WRITE_ONLY > Count;
Note: If you set the property to read-only and you try to write to it, it will cause an assertion. The same will occur if you set the property to write-only and you try to read it.
Conclusion
This article showed you how to implement a property in C++, using standard C++ without any extension. Of course, directly using the set and get methods is more efficient because with this method you have a new instance of the property class per each property.

Comments
Another solution ...
Posted by Loic on 05/14/2012 08:11amA simpler way is to defines both get/set functions as a Property function like : Class Y{ inline const std::string & Prop(){return m_value;}; inline void Prop(const std::string value){m_prop = value;}; }; Using one or the other provide the same functionality, except it's a function call i.e. : int main(int argc, char ** argv) { Y y; y.Prop() = value; // Setter cout
ReplyYet a simple way to implement properties in C++
Posted by anand_chavali on 12/21/2006 11:58pm/* Please read "less than or greater than" symbols for "( and )" where ever appropriate */ #include (tchar.h) #include (conio.h) #include (iostream) #include (string) #include (vector) using namespace std; template(typename T, char PropertyType) class Property { private: T myVar; public: Property() { if ( PropertyType != 'r' && PropertyType != 'w' && PropertyType != 'b' ) { throw "Invalid PropertyType. PropertyTypes allowed are :: \n\tr ->Read , w -> Write , b -> Both Read and Write."; } } operator T() { return GetValue(); } void operator = ( T theVar ) { SetValue(theVar); } virtual T GetValue() { if ( PropertyType == 'w' ) { throw "Cannot read from a write-only property"; } return myVar; } virtual void SetValue(T theVar) { if ( PropertyType == 'r' ) { throw "Cannot write to a read-only property"; } myVar = theVar; } }; class PropertyUser { public: Property(int, 'b') IntProperty; void Display() { cout << "\nPropertyUser::Display() --> Displaying IntProperty :: " << IntProperty; } }; int _tmain(int argc, _TCHAR* argv[]) { try { Property(string ,'b') aStringProperty; aStringProperty = "Anand"; string aStrProp = aStringProperty; cout << "Previosly assigned :: " << "Anand " << "Retrived from property :: " << aStrProp; Property , 'b'> aVectorProperty;
vector aVector;
aVector.push_back(1);aVector.push_back(2);aVector.push_back(3);aVector.push_back(4);aVector.push_back(5);
aVectorProperty = aVector;
cout << "\n\nInitialised vector with values 1,2,3,4,5. Retrieving from vector property ::\n";
for ( int i = 0 ; i < 5 ; i++ ) {
cout << aVectorProperty.GetValue() [ i ] << endl;
}
cout << "\n\nNow Testing with class : \n";
PropertyUser aUser;
aUser.IntProperty = 10;
aUser.Display();
cout << "\nDisplaying PropertyUser's IntProperty in main :: " << aUser.IntProperty;
} catch( char* theException ) {
cout << "\n\nException Occured : \n--------------------\n Message : " << theException ;
}
_getch();
return 0;
} -
Reply
Replyproperties in another simple way
Posted by guenter68 on 09/21/2009 10:32amImportant question
Posted by Ali Imran on 06/20/2005 04:22pmThe property is not returning right values when it is used directly within a statement (if it is not typecasted). printf ("%d",test.Count); //returns invalid value (some garbage) printf ("%d",(int)test.Count); //now is fine after typecast I want printf ("%d",test.Count); to work fine so that I don't have to typecast each and every kind of property (especially without assigning it to some other variable). can you please fix it? regards
ReplyIndeed outstanding - really helpful
Posted by Ali Imran on 06/20/2005 01:41amThis is the most valuable aticle atleast for me. For me, it is much more better than http://www.codeproject.com/cpp/genericproperty.asp I do not say that the other article is not good, but it is perfect for newbies. regards
Replywhy?
Posted by Mr.Prakash on 03/03/2004 08:52amif you make a member variable of a class public you get the same result. simulating the same effect differently is not what any one expects in their project. obviously you have not read about property keyword in vc++
-
Reply
-
ReplyExactly
Posted by Ali Imran on 06/20/2005 01:47amRe: Why?
Posted by ebarsoum on 03/03/2004 12:29pmI read about property keyword in VC++, C++Builder and in other languages like C#, VB and Delphi,and it is not the same effect because in my implementation you can write only get (to be only read access) or only set, but for public variables it will always have full access (read and write). also you can add any code validation or conversion or trigger any method, which you can't do in normal public variable. and I didn't use the one that come with VC because it is not portable across C++ compiler. I want to make a C++ property implementation that work in all standard compiler. Regards, Emad Barsoum
ReplyThat's really nice.
Posted by Legacy on 11/10/2003 12:00amOriginally posted by: AM
With no doubt the best approach I've seen so far. Really nice.
ReplyAssignment of properties
Posted by Legacy on 07/10/2003 12:00amOriginally posted by: Roeland Bekker
-
Replygcc does not seem to compile it
Posted by Ali Imran on 09/03/2006 04:17amgcc / mingw doesnto seem to compile 'friend property;' regards
ReplyAnother way...
Posted by Legacy on 04/02/2003 12:00amOriginally posted by: Jason King
Another way to do this can be found here:
http://www.codeproject.com/cpp/genericproperty.asp
It's an article I wrote to do the same thing. Good work coming up with another approach.
Jason King
The Collective
- If it walks like a duck and talks like a duck and it's hunting season, then it better duck
Reply