<

Object Properties in C++

Published on
19,685 Points
9,085 Views
6 Endorsements
Last Modified:
Awarded
DanRollins
Many modern programming languages support the concept of a property -- a class member that combines characteristics of both a data member and a method.  These are sometimes called "smart fields" because you can add logic that is applied automatically each time the field/variable is used.  Alas, standard C++ does not directly support such a concept, but this article discusses some options you can use to implement properties in your C++ objects.

Properties are a first-class language element of C#, Visual Basic, Delphi, Python and other languages.  Over the years, proposals have been submitted to C++ standards committee to add the feature to our favorite programming language, but it's never quite made it into an official standard.


Why Properties?

What's the point?  Why use properties?  

The main idea is based on something that programmers have been struggling with probably ever since Lady Lovelace wrote the first computer algorithm -- data encapsulation.  You want to manage and limit direct access to data elements so that only those parts of the program that need it can get to it.  But the usefulness of properties goes well beyond that.  Here are some things you can do with properties and some examples:
 
Data encapsulation, data hiding.  Prevent direct manipulation of data elements.  Avoid programming errors related to changing a data value incorrectly or at the wrong time.

Example: Protecting list integrity in a multi-threaded program; e.g., transparently apply a lock or a critical section around code that manipulates the list.
Data validation; data value enforcement.  It's a way for you to make your object self-correcting.

Examples: Forcibly "pin" a data value so that it is guaranteed to be within a certain range of valid values.  For instance, ensuring that a "percentage" variable will be between 0 and 100, inclusive.  Make sure that a ZIP Code is exactly five or nine digits.

Transparent data manipulation.  The data itself might be stored in a form that is inconvenient for other parts of the program to use.  The property logic does a conversion transparently.

Examples:  Encrypt a password, Social Security Number, or other sensitive data when stored but have the clear-text value at hand when used in the program.  Provide normalized handling for database NULL values.  Transparently "escape" and "unescape" text that is to be displayed in an HTML page or used in an SQL query.
Data source transparency.  The programmer (and the rest of the system) does not need to know exactly how or from where the data was obtained.  He just needs the value.

Example:  The value is obtained through a COM-object method that might, in turn, access a database hosted on a remote system.  But it looks like a local memory variable in the program code.

Invoke a function call to get or set the data by using simple assignment semantics.  Hide the "dirty" low-level implementation.  This is possibly the most commonly-cited value of properties.

Examples:  Instead of calling MoveWindow(...), you can just set oWin.rPos=r;  Instead of calling ShowWindow(h,SW_HIDE) just set oWin.fIsVisible=false; Rather than calling SetPixel(x,y,rgbColor) just use Canvas[y][x]=rgbColor;  Instead of calling GetPrivateProfileString() for a user-settings option value, just use sUser=oSettings.sUserName;

Accessors: getters and putters

If you recognized any of the above scenarios (that is, if you have done much C++ coding), you have probably written your share of getXxxx() and putXxxx() member functions in your class objects.  And you have run into the problem:  Using accessor methods can be syntactically awkward:
oList.putElement( n, oList.getElement(n)+1 ); // thread-safe getter+putter
oAddr.putZIP( sZip );   // range-enforcement putter
oWin.putPosition( r );  // hidden-details putter

Open in new window

...instead of simply:
oList[n]++;            // could use thread-locking logic 
oAddr.sZipCode= sZip;  // could enforce valid content (5 or 9 digits)
oWin.Position= r       // calls MoveWindow()

Open in new window


In short, that's what this is all about:  Anything that you can do with a property can be done with a pair of get/put member functions, but the programming is not as convenient.  Why should VB and C# programmers have all of that heavenly convenience while we poor C++ programmers are damned to spend eternity in a get-and-put purgatory?

Well, we are not.  First, several popular C++ compilers provide non-standard support for properties.  But even lacking direct support, the C++ language boasts the ability to write operator overrides... and that means that it is possible to implement property semantics.


C++ Property Implementations

Several compilers provide non-standard extensions, and there are a number of ways to attack the problem using templates and/or macros.  Let's look at the options.

Non-Standard Extensions

For many of us, the first and most obvious place to look is in our compiler's documentation.  If it provides a non-standard extension with support for properties, then unless you intend to port the code to a different compiler, why not use it?

Microsoft's Visual C++ has supported such a non-standard extension since (at least) the 2003 release.  It works perfectly and is easy to use.  You just add...
 
      __declspec( property( get=YourGetFn, put=YourPutFn ) ) int yourPropVarName;

... in your class declaration.  Code up the YourGetFn and YourPutFn and add the private variable that they will access, and you are done.

// Range-check and "correct" a percentage value
//
class PollData {
private:
    int mp_nPrivateValue;
public:
    void putPct(int n) {              // enforces a specific range of values
        mp_nPrivateValue= n;
        if (n>100) mp_nPrivateValue= 100;
        if (n<0)   mp_nPrivateValue= 0;
    }
    int getPct() {
        return mp_nPrivateValue;
    }
    __declspec(property(get= getPct, put= putPct)) int nPct; // <<-- property name
};
void main() {
    PollData rPD;
    rPD.nPct= 200;  // pinned to 100
    rPD.nPct= -10;  // pinned to 0
    rPD.nPct++;     // internally calls getPct and putPct
   // r.mp_nPrivateValue=50; // Compile error: "cannot access private member"
}

Open in new window

That works whether you are programming native or using CLI (incidentally, the ECMA C++/CLI standard elevates property to first class status and you don't need to use the somewhat awkward _declspec syntax in the declaration when doing .NET progamming).

Note that the semantics are perfect -- property variables work transparently to the code that uses them.  For instance, you can use syntax like propVar++ and it will correctly do a get, add 1, and then do the put.

Borland's (now Embarcadero's) C++ Builder supports this using the __property keyword.  There is an example of use here (midway down the page).

For Apple programmers, Objective C++ provides non-standard support using the @property directive.  See an example here.

Support using only Standard C++

In researching this article, I found a number of "solutions" to the C++ property "problem."  I also found many vociferous opinions.  A lot of people think that C++ has no need to be more "VB-like," while others embrace the idea wholeheartedly.  Anyway, here are of few of the Standard C++ implementations that I found.
 
This CodeGuru article uses a template and operator overloads to accomplish the goal.  It also includes the ability to make a property that is read-only or write-only:

    Implementing a Property in C++
    http://www.codeguru.com/Cpp/Cpp/cpp_mfc/article.php/c4031
This CodeProject article uses a template and creates an object for each property variable.  That's an innovative idea, but the added overhead makes it rather inefficient.

    Implementing Properties In C++
    http://www.codeproject.com/KB/cpp/cppproperties.aspx
This CodeProject article uses a complex set of macros to do the trick, but also includes support for using the Microsoft extension if desired.  You might also want to read some of the user comments, which describe and illustrate some alternative techniques.

    Generic C++ Properties
    http://www.codeproject.com/KB/cpp/genericproperty.aspx
The following article is a full-featured implementation, with a great description of the internal workings of its ultra-complex system of typedefs, templates, and operator overloads.

    C++ implementation of the C# Property and Indexer with Accessor-Modifiers
    http://www.codeproject.com/KB/cpp/cpp_property_indexer.aspx
A user comment added to this article includes a simpler, but less versatile template-based system:

    Defining Properties in C++ similar to C#
    http://www.cplusplus.com/forum/general/8147/
EE's own evilrix has published an article for Standards-bound C++ coders.  It uses a set of macros, including token-pasting to create the get/put functions and the friend functions for operator overrides.  As with most similar implementations I've seen, it lacks semantic support for ++ and += and other often-used operators.

    How to add properties to standard C++ classes
    http://www.experts-exchange.com/A_3843-How-to-add-properties-to-standard-C-classes.html
This whitepaper by Lois Goldwaite proposes that property support be made available as a part of the standard C++ library. The first part of the article is an excellent introduction to the issues.  And, the article includes a template-based implementation.

    C++ Properties -- a Library Solution
    http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1615.pdf

Conclusion

I mostly agree with Lois Goldwaite that the whole issue of properties amounts to "syntactic saccharine" -- a sugar coating over the underlying nougat.  I'd generally rather just add getXxxx and a putXxxx functions (and do all of the "hard work" of using them when I access certain fields) than apply a complex set of templates and macros.

However, I disagree that it should never be part of the C++ standard.  If property were elevated into a first class language keyword, I'd probably use it all of the time.   My advice is that if you don't mind stepping outside of the official C++ standard, and if your compiler supports the feature (even as a non-standard extension)... use it!

The usefulness of "smart fields" cannot be questioned.  Data validation, source transparency, true encapsulation, and the value of hiding (and being able to change) implementation details such as OS/GUI-related API calls --- all covered with a "syntactic sucralose" to make it easy to use... sounds sweeeeet to me!

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
If you liked this article and want to see more from this author, please click the Yes button near the:
      Was this article helpful?
label that is just below and to the right of this text.   Thanks!
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6
Comment
Author:DanRollins
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
6 Comments
 
LVL 15

Expert Comment

by:ericpete
DanRollins,

I was asked to look at this in my capacity as the newsletter editor (it had better NOT be because of my programming skills). As you know, I'm not qualified to evaluate the code you have posted, so you can take my comments with a grain of salt if you wish.

Having said that, what I like about this article is that to someone who isn't a C++ programmer you have laid out the discussion very cleanly. It is unfortunate that it is about a subject that people with my limited experience would probably skip over in a list of articles for fear of having their eyes glaze over; the word "unfortunate" is used deliberately, because I do understand a little more about why people choose to program in the languages they do.

One question, though. In referring to the Goldwaite paper, you suggest that she wants the property support to be part of the C++ standard. You then disagree with her, saying that it should be part of the standard. Or am I missing the nature of your disagreement with her?

Nonetheless, a nice overview, and a yes vote.

ep
0
 
LVL 49

Author Comment

by:DanRollins
The way I read it... She wanted the support to be incorporated into the standard library (or to be supported only by additional template/macro code), not become an integral part of the language.  For instance, C++ programmers use the data type, string, almost as if it were a first-class keyword (like int or char), but it is actually a construct of whatever STL implementation that the programmer is using.  Likewise, her template-based system for property would not be incorportated into the language itself, but  would instead be part of an add-on toolkit (albeit a capital ess Standard one :-)
0
 
LVL 31

Expert Comment

by:Zoppo
Hi DanRollins,

IMO that's a good article and I think I'll use properties more often in the future ...

But I would like to mention that properties even can lead to unexpected problems in some cases because a programmer probably use them as if they were member variables without paying attention that in fact it's a function call.

I once had the case that I used the .NET class 'System::IO::FileInfo' to find out the size of a file like:

> System::IO::FileInfo^ f = ...;
> ...
> int len = f->Length;

As this was the first time I used a property I wasn't aware that a funcion is called, so I forgot to put a 'try/catch' around the second line and so the application terminated with an exception thrown from 'f->Length' because the file was deleted before this code was called.

So, as a conclusion, I would like to see a hint here that using properties require exact knowledge about if they can throw exceptions.

ZOPPO
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 49

Author Comment

by:DanRollins
Excellent point.  Any access to a property results in program code being executed and that means that errors and exceptions can occur.  It's probably wise to avoid using complex coding in the handling whenever possible.

I suppose that the getter/putter could provide local exception handling and, for instance, return -1 instead of throwing an exception.  I'm sure that would raise its own set of problems...

I saw a presentation on the next generation of Visual Studios and I believe I saw that syntax/semantic coloring of the source code text recognizes such things as property vs. simple data member.   That might help a programmer to avoid the specific problem that you mentioned.  It was cool to see local variables colored differently from same-named globals...

-- Dan
0
 

Expert Comment

by:Baldrick2
0
 
LVL 40

Expert Comment

by:evilrix
Hi Baldrick2.

I'm not really sure I understand the relevance of the link you've posted. For the sake of informing myself and others could you just clarify?

Thanks.
0

Featured Post

Enroll in May's Course of the Month

May’s Course of the Month is now available! Experts Exchange’s Premium Members and Team Accounts have access to a complimentary course each month as part of their membership—an extra way to increase training and boost professional development.

Join & Write a Comment

The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.
Next Article:

Keep in touch with Experts Exchange

Tech news and trends delivered to your inbox every month