Sign in to follow this  

[C++] A quick replacement for get()/set() functions?

This topic is 3638 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

So I was bored and I thought about this little utility class. It's usefulness is very limited but maybe someone will still be able to benefit from it or extend it. This class is designed to automatically generate get()/set() like methods for a member variable. Here's the code:
template <class T, class R = T>
class Prop {
public:
	explicit Prop(const T &v = T()):val(v) {}

	R operator()() { return val; }
	void operator()(const T &v) { val = v; }

private:
	T val;
};

The second template parameter allows you change the return type to a const/non-const reference (see the name property in the following example). You can use it like this:
class Player {
public:
	Prop<std::string, const std::string &> name;
	Prop<int> gold;
};

void func() {
    Player player;
    player.name("John");
    player.gold(25);
    int gold = player.gold();
}

Obviously the usefulness of this class is extremely limited, because it's not customizable. For example, in the setter, you may want to check that the parameter is in a specific range. Right now I'm not sure if there's an elegant way to extend it to handle such cases (maybe with policy classes or something similar). I was hoping that maybe someone here would have an idea. Even as it is, it provides at least one benefit to simply making the members public - if you do decide you need to perform a check in the getter, you can replace this class with a custom class like in the example shown here (the URL thing isn't working for some reason): www.kirit.com/C++%20killed%20the%20get%20&%20set%20accessors Any thoughts are appreciated.

Share this post


Link to post
Share on other sites
An overabundance of getters and setters in C++ is often a sign of bad design. Try to think in terms of state and behaviour instead. Taking your example a players name should probably be constant state, so a setter function is likely not appropriate. Equally, rather than getting and setting the gold value it is probably more appropriate to initialise the gold in the constructor and then spend and acquire, although a setter function may be appropriate as well. Doing so makes code more readable and can reduce duplication.

Some classes really are just dumb containers for data. Sometimes a POD type is appropriate in these instances, sometimes a slightly more intelligent class with getters and setters is required. Just don't fall into the trap of making everything a dumb container by default. Encapsulate behaviour as well as state.

Σnigma

Share this post


Link to post
Share on other sites
Quote:
Original post by Enigma
An overabundance of getters and setters in C++ is often a sign of bad design.
That's just baloney. There's firstly nothing that makes getters/setters in C++ different to Java/C#, except that people are not so good at using them. Getters and setters are often the ONLY methods on many bean-type classes, like DTO objects for instance.

Share this post


Link to post
Share on other sites
Personally I use this for my get/set methods, it is more readable I think


struct Foo
{
int m_X;

Foo(int a) : m_X(a) {}

inline int x()
{
return m_X;
}

inline const int& x() const
{
return m_X;
}
};

int main()
{
Foo bar(2);
bar.x() = 12;
std::cout << bar.x() << std::endl;
}



my 2 little cents

Share this post


Link to post
Share on other sites
Quote:
Original post by d000hg
Quote:
Original post by Enigma
An overabundance of getters and setters in C++ is often a sign of bad design.
That's just baloney. There's firstly nothing that makes getters/setters in C++ different to Java/C#,


Indeed, an overabundance of getters and setters in Java and C# is often a sign of bad design, too. Although there is something that makes them different in C#: it has language-level support for actual properties.

Quote:
except that people are not so good at using them.


And they aren't that good at using them in any language (I've seen some horrible abuse in C# for example), which contributes to the design issues.

Quote:
Getters and setters are often the ONLY methods on many bean-type classes, like DTO objects for instance.


I think many people would hold up "bean-type classes" as a shining example of this bad design. :/ Seriously, anything that leads to code monkeys being paid to clone-and-modify get/set pairs, and eventually to the development of code generation tools to replace them, can't really be a good thing. The emperor has no clothes here, folks. This is not real OO.

Free hint about C# property usage: just use a public data member first. Later, you can replace it with a property, without changing the calling code (the *interface* is the same). If the thought of having a public data member bothers you, the get/set pair ought to as well. If you just start out writing a property for every member (the kind of abuse I allude to above), then you (a) lie to yourself about encapsulation, if you aren't making the decision with full consciousness; (b) fall afoul of YAGNI; and (c) start out with publishing an interface that may be sub-optimal, simply because it expects the calling code to think in terms of the *state* of another object.

"DURRRR, they tolded me in teh OOP101 that data is supposed to be private, but I don't get how you're supposed to manipulate an object if you don't have access to its internals... I guess this is what they want you to do. ZOMG this is so much better than procedural programming! I get paid by the line!!!11"

</rant>

Share this post


Link to post
Share on other sites
Gage64:
There are a few cases where get/set is useful, but unfortunately your utility class doesn't cover them:
- You can't have different access specifiers for the get/set (e.g. public get, protected set)
- You can't validate the input to the set operation
- Although you can change the getter to const& via the second template argument, that still doesn't prevent use of the setter to change the value.

d000hg:
It's perfectly good advice.

If you're building a class you should be thinking in terms of state/behavior - if you want a collection of data (like a c-style struct) use a class/struct with all public members.



Share this post


Link to post
Share on other sites
To easily and automatically create get and set functions for your c++ instance variables go to:

http://www.houen.net/codegenerator/index.php?language=2

This site will respond to instance variables with corresponding functions. E.g.

private:
String _email;
int _num_users;

will return

//-------------QUERIES-------------
public: String get_email() {
return _email;
}
public: int get_num_users() {
return _num_users;
}
//-------------COMMANDS------------
public: void set_email(String email) {
_email = email;
}
public: void set_num_users(int num_users) {
_num_users = num_users;
}


Hope you find this useful.
PS: It also works for C#, PHP, Java and Flash actionscript

Share this post


Link to post
Share on other sites
I find the idea of making some variables private, then making public functions that modify those variables directly rather awkward. The words "get" and "set" sound so generic too. Does it not make you raise an eyebrow, however much you try to justify it?

Share this post


Link to post
Share on other sites
Set methods are wonderful if you use them to do validation of the assigned variable, something that isn't really supported by hacked together properly template class thingies. I often use private Set methods for variables that need validation so I don't need to repeat the same code throughout the class. Basic assignments don't get a Set method.

As for Get methods for complex objects, I generally don't like providing anyone with access to modify a class's internals, so const ref Get methods allow me to implement the super-secret idiom of "you can look but you can't touch" ;).

On the whole, I will never provide a get/set pair until I know damned well they are going to be used and there isn't a better solution instead.

Share this post


Link to post
Share on other sites
I think if you need a get AND set, you need neither. If a variable needs validation, then why not create a member function make_variable( input )? Or, only send validated info to the class. If I'm not mistaken, you can CREATE a compiler warning telling the user they've bypassed your function! But, it seems to me, they probably have a reason.

Personally, I wish in C++, you could do something like this:

class a
{
int x;

void a.x = ( type right ) {};
}



...but now that I think of it, if I wanted to do this (really, really badly), I might try a macro.

Share this post


Link to post
Share on other sites
Last I checked, the purpose of having a getter/setter pair at all was to include some sort of data manipulation when a get/set is called. These goofy things that look like this :
private:
int m_var;
public:
int GetVar(){return m_var;}
void SetVar(int var){m_var = var;}
Are utterly useless, and are frankly painful to look at. Yet these sorts of stupid structures appear in countless text books and are taught to learning programmers as 'the way' to do it. Even most semantics that you can shove into these functions actually belong somewhere else. There are some instances where getter/setter functions are actually useful, but they are pretty rare.

Couldn't possibly agree more with Zahlman on this one. I'm so sick of reading other people's source code with these useless getter/setter pairs... Java [especially those beans] or otherwise, it's bad design, and ugly too.

Share this post


Link to post
Share on other sites
Getters and setters are not bad - yes, it's like having public variables, but you can add behavior later if you need it without changing the interface, and you can have individual read/write visibility. The only problem getters/setters have is verbosity.

The verbosity issue is really easy to solve - C# does it in a clumsy, but workable way by introducing a separate concept non-orthogonal to getters/setters, but you could just as easily have property-like syntactic sugar for declaring and using getters/setters.

Share this post


Link to post
Share on other sites
Writing getter/setter functions - even when both are public and do nothing extra - are good programming practice as they make your code more expandable and flexible, and could save you hours of tidying up down the line.

For example, consider a simple square matrix class:

template<int N>
class Matrix
{
public:
float data[N][N];

// ...
};


This is with no getter/setter functions. You write your entire library for multiplying with other matrices, vectors, calculating determinants etc. etc. all the while just accessing data directly using matrix.data[i][j].

It would appear that there would be no difference between using matrix.data[i][j] = val and matrix.set(i, j, val) and up till now there would be no difference. Now let's say that you want to add a method to transpose the entire matrix. Without getter/setter functions, you are forced to write some horrible O(N^2) algorithm like this:

template<int N>
void Matrix<N>::transpose()
{
float temp[N][N];

for(int i=0; i<N; ++i)
for(int j=0; j<N; ++j)
temp[i][j] = data[i][j];

for(int i=0; i<N; ++i)
for(int j=0; j<N; ++j)
data[i][j] = data[j][i];
}


Now, had you used getter setter functions, you could of constructed the transpose functions as follows:

template<int N>
class Matrix
{
public:
void transpose()
{
isTransposed = !isTransposed;
}

float get(int i, int j)
{
if(isTransposed)
return data[j][i];
else
return data[i][j];
}

void set(int i, int j, float val)
{
if(isTransposed)
data[j][i] = val;
else
data[i][j] = val;
}

private:
float data[N][N];
bool isTransposed;
};


This way, you've turned an O(N^2) function into a constant time function with very little effort. Attempting to introduce this functionality without having the getter/setter functions there in the first place would be a nightmare. There are many, many examples of these types of situations that can occur. Like all things in programming, it's better to have it right sooner rather than later.

Share this post


Link to post
Share on other sites
The matrix example is neat, and would save you from actually having to transpose it but it will incurr a performance hit for every access to the matrix because there is the if statement which checks if the matrix is transposed or not. Given the fact that element access is by far more common than the matrix transpose operation your method will actually run slower in the end. This is especially true if the matrices are generally small.

Share this post


Link to post
Share on other sites
Quote:
Original post by Splinter of Chaos
Or, only send validated info to the class.


Opens up a whole world of bugs. As far as I'm concerned, unless a collection of classes is designed to specifically work together (usually when splitting one big class into multiple smaller ones), all variables passed to public member functions get validated. It's just good design. It keeps the validation code where the validation is needed - in the class itself.


Share this post


Link to post
Share on other sites
Quote:
Original post by Trenki
The matrix example is neat, and would save you from actually having to transpose it but it will incurr a performance hit for every access to the matrix because there is the if statement which checks if the matrix is transposed or not. Given the fact that element access is by far more common than the matrix transpose operation your method will actually run slower in the end. This is especially true if the matrices are generally small.


True, but that's not the point I was making :)


Share this post


Link to post
Share on other sites
Testing validity of member variables is a good thing, but shouldnt you verify the class itself after a method. The value of mWeght and mDistance might be valid seperate, but together they might be invalid. A raii object that calls assert(IsValid()) might be a good thing.

Quote:
[edit] Double post, please delete.
edit your post, and check the "Delete? To delete this post, check this box." right above your username and message :)

Share this post


Link to post
Share on other sites
Quote:

private:
int m_var;
public:
int GetVar(){return m_var;}
void SetVar(int var){m_var = var;}


Poita I think you kinda missed the point. Zalhman was likely referring to useless get/set pairs like the above, though I could be wrong.

As for your example, nothing wrong with having methods to set the data but no need for getters if you keep the data public. There is no reason to protect the data in a matrix class honestly.

If/when I use "get/set" functions I do like bibiskuk did. Much easier to read and feels more natural then GetX!!!! and SetX!!! Just X() and X() :) compilers are smart and I can read, saves on typing too.

Share this post


Link to post
Share on other sites
Quote:
Original post by Mike2343
Quote:

private:
int m_var;
public:
int GetVar(){return m_var;}
void SetVar(int var){m_var = var;}


Poita I think you kinda missed the point. Zalhman was likely referring to useless get/set pairs like the above, though I could be wrong.

As for your example, nothing wrong with having methods to set the data but no need for getters if you keep the data public. There is no reason to protect the data in a matrix class honestly.

If/when I use "get/set" functions I do like bibiskuk did. Much easier to read and feels more natural then GetX!!!! and SetX!!! Just X() and X() :) compilers are smart and I can read, saves on typing too.


I think you missed my point :/

I was also referring to "useless" get/set pairs like you said. The point I was making is that although they may be useless at first, when you want to make changes to you program, having them there makes things a hell of a lot easier. For example, there is no easy way to add validation when using public member variables. If you code "useless" get/set functions from the get-go then adding validation will likely be as simple as adding a single if-statement.

Furthermore, having get/set functions gives more flexibility when using derived classes.

The only time you should have public member variables is with VERY trivial classes, such as vectors or complex numbers. If you don't use getter/setter functions then it's very likely that you'll feel it later on. Other than the extra typing time, there's no reason not to. They'll get inlined anyway so there is no real performance loss.


Share this post


Link to post
Share on other sites

This topic is 3638 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this