How to generate automatic properties (get, set) fo

2019-06-14 00:33发布

问题:

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++?

回答1:

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();
}


回答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.



回答3:

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



回答4:

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.



回答5:

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.



回答6:

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.