1

Having read this question on generating getters and setters in Visual Studio and tried (somewhat) the techniques described, I have failed miserably to graduate beyond the longhand way of writing Getters and Setters.

While I recognize the conceptual advantage of encapsulation (private members of a class in this case), writing 25 getters and setters is a waste of space and my time.

Why 25? Well apart form the exageration factor (approx 2.5) I just don't know at what point I will need access to that one variable in the future. I guess I could write a function that returns all of them and fish out the one I need, but if I add more members (often do) then the function must be changed throughout the code.

I like the form suggested here for VS 2008:

string sName { get; set; }

But it won't compile in C++. Is this just for .NET and C#?

Is there some tidy way to simulate this in C++?

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
Mike Trader
  • 8,564
  • 13
  • 55
  • 66
  • 9
    Please consider changing ".NOT" to ".NET" - I don't know about others, but I regard that sort of deliberate misnaming (like M$ for Microsoft) as pretty childish. – Jon Skeet Oct 25 '09 at 22:41
  • There is a recent project in Boost, which tries to implement properties in C++. but I don't think its mature or overhead free. NB: More Power to templates!! – Christopher Oct 25 '09 at 22:43
  • 1
    Thank you for your opinion, and as the most popular person on this forum, I respect that. UNfortunatly, I object to the very concept of .NET and managed code on so many levels I couldn't possibly do it justice in this reply. I understand this is not a popular position with the evangelists, but I reserve the right to express my opinion in this very simple way, even if some people do not like it. I would love the opportunity to debate this, but my experience here is that a thread like that would be shut down immediately, effectively silencing me. I hope that explanation gives you some context. – Mike Trader Oct 25 '09 at 22:50
  • 5
    There are people that passionately object to C++ but they still manage to call it C++... –  Oct 25 '09 at 23:15
  • You could probably have written at least 10 of them in the time you used to write this post, and probably the other 15 in the time you use to read the answers. – erikkallen Oct 25 '09 at 23:27
  • 1
    Mike: Life is too short to be offended by managed code to the extent that you post unprofessionally to a place where your next employer may come to read up about you. It's not worth it. You would post here that you oppose a certain religion or race. And you know people treat programming languages/paradigms with the same respect they do religions. In short, don't go there. – jmucchiello Oct 25 '09 at 23:29
  • Yeah, I figured this was going to offend the people that think 60MB of required run time "frameworks" (v1, 2, 3, 3.5 ...) is in any way acceptable. The fact that you feel the need to resort to petty threats is just another indication of the level of insecurity you have about the elephant in the living room that no one wants to talk about. As for objections to C++, please do share. I welcome constructive criticism/debate and respect the peoples right to express their opinions even when I disagree. – Mike Trader Oct 25 '09 at 23:39
  • 1
    @Mike: I'm not offended, and I don't object to people disliking .NET. I just think that expressing that dislike by mutating a name in that way is childish. I have no insecurity about choice of language, and I welcome *constructive* criticism/debate - but name-calling doesn't come under that heading IMO. It's also much less likely to *generate* constructive criticism/debate. – Jon Skeet Oct 26 '09 at 02:49
  • John, lets be pragmatic for a moment. .NOT is a succinct mnemonic device designed to express my objection to the philosophical assumptions made by the designers. Think of it as a bumper sticker. In three letters I have stated my objection in subtle way just as those that choose to call Microsoft did with M$. I am not sure I want to "bash" .NET or C#, but I do want to express my feelings about its assumptions. This seems to be a way to do that without being too "in your face about it". I understand you don't like it, but asking me to change it is crossing the line of freedom of expression. – Mike Trader Oct 26 '09 at 03:10
  • 1
    Yup, you should *absolutely* feel free to look childish. Just don't expect to get as positive results from that manner of expression as from writing a simple sentence explaining that you don't want to use managed code. If you're not sure you want to "bash" .NET or C#, then using a derogatory expression such as ".NOT" seems like a bad idea to me - especially if you want to engage in discussion with .NET developers. But as I say, if you want to do that, go ahead. – Jon Skeet Oct 26 '09 at 08:50
  • John, you are still young. When you get to my age, being silly is a refreshing change from taking life and yourself so darn seriously. Is Python to be deemed silly and childish for using "spam" and "Eggs" instead of "Foo" and "Bar"? Please try and get beyond this need to make the world fit into your conception of correctness. In my experience, its a fruitless exercise. – Mike Trader Oct 26 '09 at 16:36
  • 4
    There's a huge difference between being silly and being childish. As for what's fruitful and what's fruitless... I think I'll keep my own counsel as to what sort of communication leads to fruitful discussion and what doesn't. My experience is that this sort of name-calling is never helpful. – Jon Skeet Oct 27 '09 at 06:48

6 Answers6

6

Thanks @Dan for pointing out this trick in Microsoft Compiler (non-portable)

Here is the way:

struct person
{
    std::string m_name;
    void setName(const std::string& p_name)
    {
        m_name = p_name;
    }
    const std::string& getName() const
    {
        return m_name;
    }
    // Here is the name of the property and the get, set(put) functions
    __declspec(property(get = getName, put = setName)) std::string name;
};
int main()
{
    person p;

    p.name = "Hello World!"; // setName(...)
    std::cout << p.name;     // getName(...)
}

After creating your member variables plus the getters and setters of these member variables, you create a property for each getter/setter pair. You can call it whatever you want, because you have to specify the getter and setter for this property.


Just for fun :)

#define property(Type, Variable) private: Type Variable; \
      public: const Type##& get##Variable() const { return Variable; }; \
      void set##Variable(const Type& Variable##_) { Variable = Variable##_;}


 struct Test
 {
     property(int, x); property(int, y);
     property(std::string, text);
 };

int main()
{
    Test t;

    t.setx(10);
    t.sety(10);
    t.settext("Hello World at: ");
    std::cout << t.gettext() << " " << t.getx() << ", " << t.gety();
}
Khaled Alshaya
  • 94,250
  • 39
  • 176
  • 234
2

Automatically implemented properties are indeed a feature of C#. As far as I'm aware, they're not available in C++. I believe they're coming in VB 10, but I don't know if they'll be introduced into C++/CLI.

There are lots of language features which are part of C# but not C++ (and vice versa, of course). You shouldn't expect to just be able to use the syntax of one language in another.

I would caution against writing properties "just in case" though. If you're going to basically give complete access to everything in your type via a property, even though you don't know whether you'll need it, that hasn't encapsulated much. Adding read-only properties is somewhat better, but it's nicer to avoid tying your higher-level abstraction to the variables you happen to be using now. If these properties are part of the intrinsic nature of the type (i.e. you'd expect any implementation of the same concept to expose the same properties) then that's a slightly different matter.

EDIT: As you don't want to use managed code, you won't even be using C++/CLI, which makes it even less likely that you'll be able to use C# features.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    I think it's better to learn the language you're *actually* using thoroughly, instead of even *hoping* to be able to just use syntax from other languages. – Jon Skeet Oct 25 '09 at 22:44
  • You got no argument about learning a language, but isn't the whole point of refactoring to reduce bloat and make code more readable? Why do I need to wade through 25 trivial GET and SET's before I arrive at the first thing of real interest to anyone reading the code? As you may have gathered, I like tight "to the point" code that is readable and easy on the eye. It's just so much more productive to work with. – Mike Trader Oct 25 '09 at 22:58
  • 1
    @Mike: In that case you should use a language which is more productive to work with than C++... – Jon Skeet Oct 26 '09 at 02:43
1

Refactor! by DevExpress has some pretty nice features for C++, one of which is encapsulating fields like C#.

The plugin uses DirectX overlays in the text editor to offer a list of available actions for whatever you've typed. so if you type:

float id;

the plugin will animate an indicator to show options such as Encapsulate Field, which will add:

property float Id
{
    void set(float value)
    {
        this->_id = value;
    }
    float get()
    {
        return this->_id;
    }
};

If installing a plugin really isn't your thing, consider using macros.

Personally, I prefer using macros. Once you get the hang of them, they're really easy. I've used both, but we're stuck in Visual Studio 2003 (C#) until December, and DevExpress plugins don't work.

The way I usually use macros is to start at the beginning of a line, hit CTRL+SHIFT+R to begin recording. Then, type, copy, and paste the steps I'd like to recreate. When finished, hit CTRL+SHIFT+R to stop recording. Then, CTRL+SHIFT+P will playback the last recording. You can also go into Macro Explorer and save/edit your macros. Then, you can just double click macros to run them.

Joseph Yaduvanshi
  • 20,241
  • 5
  • 61
  • 69
  • Thank you for the first real answer! Could you elaborate a little pls. Have you used both? Which do you prefer and why? How are the fields encapsulated (code example would be great) – Mike Trader Oct 25 '09 at 23:09
  • Thanks, Mike. I edited my answer a little to elaborate. I used Refactor! for my C++ class in school. It was very useful. I like macros because I can do exactly what I want very quickly. – Joseph Yaduvanshi Oct 25 '09 at 23:22
1

C++/CLI supports automatically implemented properties - it calls them "Trivial Properties" 1

user200783
  • 13,722
  • 12
  • 69
  • 135
  • Do these still exist in .NET 3.5? I tried them before, but they didn't work (compiler complained about missing get/set or something similar) – Joseph Yaduvanshi Oct 25 '09 at 23:30
1

Why 25? Well apart form the exageration factor (approx 2.5) I just don't know at what point I will need access to that one variable in the future.

You realize this means you really haven't thought your design through much. Instead of finding ways to add properties to C++ (it doesn't need them). Should I call them "properduhs" to explain the extent of my dislike for them?

You should be spending time creating a design for your class so that you know what parts should be visible to the class's user (and therefore need some form of getter), which parts might need to updated (and therefore some form of action method would be needed) and which are truly internal. Notice I said nothing about setters. Setters are lazy constructs that allow you to not plan your class. Methods should do things. By do things I mean actual work should take place not just some number is updated somewhere. If something is just a number, make it public. If there might be side effects, make a method that gives you a clue as to what is being done (both the value changing and the side effect as well). If you don't know if there might be a side effect, go back to the design table and find out.

I realize this goes against the "rule of thumb" that data should be encapsulated privately with getters and setters so that if the design of the class changes, users of the class are immune to the changes. Well, to heck with that. Get it right the first time and spend less time fussing about it later. My approach is give the class user access to NOTHING but a small set of methods and then if you find it important to allow them access to some private value later you can add a getter() later. When I said "just make it public" it should be understood that means "after exhaustive consideration I know it is absolutely safe to make this public because I have fully and completely designed my class with all use cases in mind."

Okay, now go ahead an ding this answer because it answers the heart of the question rather than the letter of the question. I expect it.

jmucchiello
  • 18,754
  • 7
  • 41
  • 61
  • Oh don't be afraid of the dings... this is EXACTLY the core issue. Please help me frame a question I can ask that will a) not start a major war and b) solicit a fruitful debate on this issue. I have the code example ready to go! – Mike Trader Oct 26 '09 at 00:01
  • You've already received advice for writing a question in a more fruitful way: don't refer to platforms/languages/etc in a distractingly childish way. You're ignoring that advice though... – Jon Skeet Oct 26 '09 at 02:48
  • The problem is stackoverflow is not a place for debate. It is a places for answers to questions. What are you trying to ask? Do you want help designing your class? Post a question like "how can I improve this?" Of course, stackoverflow is also not a place for design critiques. It is supposed to be a place for specific answers to specific questions but questions that someone else might ask as well. Still, the best way not to start a war is not to slap someone in the face saying .NOT to them. – jmucchiello Oct 26 '09 at 02:48
  • Shelving a popular development language like VB (that many have a large $$ investment in) REQUIRING a costly migration to something new, is what many have called a big slap in the face. Moving on, every thread on stack overflow is by definition a debate. Joe asserts x, Bill asserts y. You raise a controversial issue in your answer "Get it right the first time..." (which flies in the face of Agile concepts) let alone making data public. It sees like this IS the place to explore those ideas, hence the suggestion to do so in another thread. The question in this thread has been answered. – Mike Trader Oct 26 '09 at 05:48
  • Yes, I do. But that doesn't mean it is stackoverflow is "about". The answers to a question should be a discussion, not a debate. Regardless, while the short version of my answer is indeed "get it right the first time", in the long view all I'm saying is "don't just sit down and code." The old carpenters' saying, "measure twice, cut once" is apropos. The more time you can spend when the code size if zero the less time you need to spend refactoring that code later. – jmucchiello Oct 26 '09 at 06:01
  • Oh no argument there, but I am eager to learn more about design & using objects that contain private data. In all the years I have been coding I can count the number of times I really needed to use encapsulated data on one hand, but then I don't work with people that don't get the big picture much. You obviously know a lot about this and have carefully formed opinions about how to implement. I would like to hear more and discuss this (I think we got stuck on the word debate) How would you suggest we accomplish that? – Mike Trader Oct 26 '09 at 06:21
0

Properties originated (I believe) in Delphi and migrated to other languages, most notably C#. There's no built-in support for them in C++ (though I could be wrong in the case of C++.NET - haven't checked lately).

I found this article on simulating properties, which looks complex but might solve your problem. Also, consider using C# if it suits your application -ie, you're not writing a device driver. It's got an amazing object model and lots of other benefits. It doesn't replace C++ in every aspect, but is great for most applications. As a very smart friend of mine said, use the highest-level language that makes sense for your project.

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
3Dave
  • 28,657
  • 18
  • 88
  • 151