Click here to Skip to main content
15,888,803 members
Articles / Desktop Programming / MFC
Article

Object properties for C++

Rate me:
Please Sign up or sign in to vote.
4.21/5 (21 votes)
19 May 20052 min read 94.9K   675   30   22
A small library that gives C++ objects the ability to have properties.

Introduction

The purpose of this library is to provide object properties. Instead of coding setter and getter methods, it is better to use properties because it is a more intuitive interface. Unfortunately, C++ does not offer native properties, but they can be emulated using templates and operator overloading, with a small memory overhead.

Installation

In order to use properties, you have to do include the file "property.hpp" in your project, then use the following fragment in your code:

#include "property.hpp"
using namespace cpp::properties;

The library is documented using Doxygen.

Declaring properties

The main class of this library is the class 'property'. It can be used to declare a property member. For example:

class MyClass {
public:
    property<MyClass, int> data;

    MyClass() : data(this, &MyClass::data_changed, 5) {
    }

protected:
    virtual void data_changed() {
    }
};

In the above example, a property 'data' is declared. The property class has two main parameters: the type of owner class (needed in order to make a typesafe callback interface) and the type of the property value.

The property's callback (and optional initial value) must be declared at construction time. It can not be changed afterwards. Callback parameters must not be null, otherwise your application will crash.

Using properties

Usage of properties is like data members. For example:

MyClass obj;
obj.data = 5;
int i = obj.data + 1;
cout << obj.data() << endl;

Advanced options

The default property declaration declares a property that has a read-write value stored inside the property. The type of access (read-write, read-only, write-only) and the type of storage (variable or interface) can be changed by supplying different template parameters.

Interface properties are properties that don't store the value, but they call the owner object for getting and setting the value of the property.

For example, a read-write interface property must be declared like this:

class MyClass {
public:
    property<MyClass, int, read_write, interface> data;

    MyClass() :
        m_data(0),
        data(this, &MyClass::data_get, &MyClass::data_set) {
    }

private:
    int m_data;

    const int &data_get() const {
        return m_data;
    }

    void data_set(const int &value) {
        m_data = value;
    }
};

Usage of interface properties is exactly the same as variable properties. You can do different combinations of read_write, read_only, write_only and variable, interface to provide your own taste of a property.

License

As the included readme.txt explains, it's freeware, i.e. you can do whatever you like with it, except claim it for yours (of course!).

Notes

I have modified the library so that the declaration of different flavors of properties has become simpler. It works under MS VC++ 6.0 and DevCpp 4.9.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer (Senior)
Greece Greece
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 2 Pin
ColdShine24-Nov-08 10:36
ColdShine24-Nov-08 10:36 
GeneralSize increase Pin
Michel Helms22-Nov-06 0:52
Michel Helms22-Nov-06 0:52 
GeneralMSVC versions Pin
Ernesto Savoretti7-Jun-06 15:31
Ernesto Savoretti7-Jun-06 15:31 
GeneralNice, but... Pin
Yevhen Fedin26-May-05 23:11
Yevhen Fedin26-May-05 23:11 
Generalimprovement! Pin
Achilleas Margaritis20-May-05 2:19
Achilleas Margaritis20-May-05 2:19 
GeneralRe: improvement! Pin
ChauJohnthan20-May-05 8:05
ChauJohnthan20-May-05 8:05 
GeneralRe: improvement! Pin
Achilleas Margaritis20-May-05 8:41
Achilleas Margaritis20-May-05 8:41 
GeneralMS specific solution Pin
cmk20-May-05 0:25
cmk20-May-05 0:25 
GeneralNot bad Pin
pshomov19-May-05 13:26
pshomov19-May-05 13:26 
GeneralRe: Not bad Pin
Achilleas Margaritis19-May-05 23:00
Achilleas Margaritis19-May-05 23:00 
GeneralRe: Not bad Pin
pshomov20-May-05 6:29
pshomov20-May-05 6:29 
GeneralRe: Not bad Pin
Achilleas Margaritis20-May-05 8:55
Achilleas Margaritis20-May-05 8:55 
GeneralRe: Not bad Pin
pshomov20-May-05 12:55
pshomov20-May-05 12:55 
GeneralRe: Not bad Pin
Achilleas Margaritis21-May-05 3:43
Achilleas Margaritis21-May-05 3:43 
Petar K. Shomov wrote:
Gotta love the “I know and 've seen it all” attitude

It goes hand-in-hand with the 'cool library, but it's all wrong, and your C++ skills suck, and mine's rock' attitude.

Petar K. Shomov wrote:
Probably your vast C++ experience is the reason you completely restructured your implementation over a night.

You are talking as if you've never changed any code. I knew what I wanted to achieve, I just haven't thought about how to achieve it on MSVC++ 6.0.

Petar K. Shomov wrote:
If you would have checked some of the books I referred to you would have probably realized they are not about using all or fancy C++ features.

But these books refer to various C++ features necessary for following the principles they mention.

Petar K. Shomov wrote:
And these advices come from some of the best C++ gurus, who I am sure have no less experience then you do.

I see no need to read 'books' when I know 100% of what I am doing (and have done before, numerous times).

Petar K. Shomov wrote:
Besides all your "examples" were all rather conveniently centered around using only one out of the 6 combinations of types of properties you were offering. The so called 99% usage.

I have presented one other example: using a read-write interface property. Other examples are reduntant, because all you have to do is replace 'read_write' with 'read_only/write_only' and 'variable' with 'interface'.

Petar K. Shomov wrote:
This one is a serious hit on your C++ guru title. I guess you did not consider the possibility of having designed the library badly. It's gotta be the language wrong.

Well, does the language offer the possibility of inheriting from a class provided as a template parameter, then have the same constructors as the base class automatically? it does not. So I see no fault at the design, especially when usage of wrong constructors ends up in a compile-time error. I also avoid your silly design with typedefs inside a struct which would make the code look ugly.

Petar K. Shomov wrote:
Hint: Don't try suggesting to the C++ committee to "fix" this "limitation". They will not buy it!

Hint: if they are as sm@rtass as you, they will certainly not. Last time I exchanged e-mails with Bjarne Stroustrup though, he did not seem to be like that.

Petar K. Shomov wrote:
the developer should not be event thinking about making them.

How come the developer should be thinking about making them, if the compiler does not allow it? he maybe try once or twice, fail miserably, then know what is going on and never think about trying to call the wrong constructor again. It is more important that the code looks nice in the long run, for maintenance reasons.

Petar K. Shomov wrote:
And by looking at the header file and checking the IntelliSense he may not "sense" right away your vision

So? he may not sense it right away, but he should read the docs nevertheless and not the header file. And the docs explicitely say about how to use each constructor. You're right, it's important in the first 60 seconds though...I guess it is that how long it would take one to completely figure out how it works.

Petar K. Shomov wrote:
I am all confused here ... but again I do not remember exactly what was that you wrote originally because you changed it completely.

If you have checked the new code, you would see that, again, the property class has constructors for all kinds of properties. What I have changed is the way the property is declared: it uses tags and specialization to select the appropriate implementation instead of providing the implementation directly as template parameters.

Here is what went on previously and what goes on now: the property class is a proxy class: it is provided for selecting the proper property implementation. It inherits from that implementation, and so it provides all the constructors for each possible implementation (out of 6 possible).

The constructors are necessary because I want to enforce that property callbacks and property default values are only given once; therefore, they are specified in constructors.

The property class, as a proxy, needs to provide all the constructors of the base class, which is selected by the template parameters. Since C++ does not have 'constructor promotion', there is no other way.

The reason for using the proxy class and not the classes the proxy clas may possibly inherit from is purely syntactic sugar: there is only one class for programmers to know, parameterized at compile time with policy tags. It's the same tactic used with boost::smart_ptr and other high-quality libraries. I could have had 'read_write_variable_property<c, t="">', 'read_write_interface_property<c, t="">', 'read_only_variable_property<c, t="">' etc but it would look and feel UGLY.

Petar K. Shomov wrote:
Your understanding of "syntactic sugar" is quite strange.

Not at all. Syntactic sugar is when the code is made prettier to look at, easier to write for, and consequently easier to document and maintain.

Petar K. Shomov wrote:
A typedef can be considered syntactic sugar.

Not in every case. For example, if you have 6 different typedefs as a result of a combination of 2x3 options, it's is bad to use typedefs. It is better to use tags and selectors.

Petar K. Shomov wrote:
Creating a class deriving from another one is most definitely not syntactic sugar. Syntactic sugar was what I offered in my original post: to create typedefs for the 6 different combinations of classes.

He he I replied to the comment above before I read it. What you offered was not syntactic sugar, it was syntactic hell: you introduced 6 new words for the programmer to remember, plus the 'property' one. My solution has 5 words.

Furthermore, your identifiers where ugly: rwi, roi, rwv etc. What the heck are those? it's not clear from when looking immediately at it.

Finally, there is a big problem with your solution: imagine if one more option was introduced! Let's say that there is a new property storage type called 'remote' which sends a message across the network each time the property is changed. Then your naming (rwi, roi, rwv) whould be invalid, and you would have to provide 9 typedefs, where I would only have to provide one more keyword!

Petar K. Shomov wrote:
I have to admit by looking at your code you definitely have C++ skills.

Thanks.

Petar K. Shomov wrote:
But you really have to work on the attitude.

No, it was your attitude that was rude. You came on to me, saying that all I have done is wrong, and I would probably should educate myself, without giving any concrete argument on why I should do so or why my approach is wrong.
GeneralRe: Not bad Pin
pshomov22-May-05 8:05
pshomov22-May-05 8:05 
GeneralRe: Not bad Pin
Achilleas Margaritis23-May-05 6:18
Achilleas Margaritis23-May-05 6:18 
GeneralRe: Not bad Pin
Corneliu Tusnea24-May-05 13:26
Corneliu Tusnea24-May-05 13:26 
GeneralRe: Not bad Pin
barok25-May-05 20:52
barok25-May-05 20:52 
GeneralRe: Not bad Pin
Achilleas Margaritis26-May-05 2:03
Achilleas Margaritis26-May-05 2:03 
GeneralRe: Not bad Pin
Achilleas Margaritis26-May-05 1:59
Achilleas Margaritis26-May-05 1:59 
GeneralRe: Not bad Pin
Anonymous14-Jul-05 14:53
Anonymous14-Jul-05 14:53 
GeneralNice Pin
Anonymous19-May-05 5:49
Anonymous19-May-05 5:49 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.