Whole Tomato Software Forums
Whole Tomato Software Forums
Main Site | Profile | Register | Active Topics | Members | Search | FAQ
 All Forums
 Visual Assist
 Technical Support
 C++ - Encapsulating a class data member

You must be registered to post a reply.
Click here to register.

Screensize:
UserName:
Password:
Format: BoldItalicizeUnderlineStrikethrough Align leftCenterAlign right Insert horizontal ruleUpload and insert imageInsert hyperlinkInsert email addressInsert codeInsert quoted textInsert listInsert Emoji
   
Message:

Forum code is on.
Html is off.

 
Check to subscribe to this topic.
   

T O P I C    R E V I E W
John Dexter Posted - Dec 31 2010 : 08:49:42 AM
If I have a class member like int m_Name and I select to encapsulate it, VA simply puts two methods right next to it in the header, named automatically e.g

private:
 string m_name;
 std::string Name() const { return m_name; }
 void Name(std::string val) { m_name = val; }
But:

  • What if I want the names to be get/setName, which is more common?

  • What if these should be public, as most encapsulated methods tend to be?



It doesn't seem a very useful feature, unless there are some options to control it? I looked in the config settings but couldn't see anything.
26   L A T E S T    R E P L I E S    (Newest First)
feline Posted - Jan 15 2019 : 06:57:43 AM
Thank you for the update. It looked good here, but it is always good to know that things have worked as expected and intended
FlawedLogic Posted - Jan 14 2019 : 4:07:31 PM
That works a treat, thanks.
feline Posted - Jan 14 2019 : 2:09:04 PM
Making the setting available outside the Encapsulate Field dialog makes some sense, I have put in a feature request for this to see what our developers make of it:

case=135042

For now, if you go into the VA Snippet editor and delete your custom Encapsulate Field snippet, and then trigger Encapsulate Field once in your code, the default snippet will be recreated, and you will be presented with the standard Encapsulate Field dialog. Inside this dialog you can now turn Off the new setting "Public accessor visibility", which will be remembered when you return the Encapsulate Field snippet to your custom version. So you will be back to the old behaviour, without having to deal with the dialog box.
FlawedLogic Posted - Jan 14 2019 : 12:29:49 PM
Thanks for looking at this.

I only ever use encapsulate field immediately after I define a member just to save me typing, so I don't need a search or a dialogue, there's nothing to change.

The problem for me is that if I define a few members and then use encapsulate field on them, it keeps moving the cursor to where it put them (often some distance away, and sometimes in the wrong public area) so I have to move back down again to where the members are, to do the next one.

Before these changes it just dumped the accessor code above the data member declaration and I could copy the whole lot into the public area and delete the member definitions, but keep the comment for the accessors. This means the new method is actually a backward step for me.

Could we move the checkbox into the settings dialogue as a global default perhaps?
feline Posted - Jan 14 2019 : 07:58:06 AM
OK, this is interesting. When I use your snippet, rather than the default snippet, no dialog appears. So it's not a setting, it is an effect of your snippet, compared to the default snippet.

I think the trigger is that you have removed the expected token $GeneratedPropertyName$ from the snippet body. Because you are not asking VA to work out the name of the function, we are not triggering the Encapsulate Field dialog.

So, this suggests changing your snippet into:

const $SymbolType$& Get$GeneratedPropertyName$() const { return $SymbolName$; }
$ClassName$& Set$GeneratedPropertyName$(const $SymbolType$& val)
{
    $SymbolName$ = val;
    return *this;
}

unfortunately, this runs into a known bug with VA's Encapsulate Field code. If the generated setter function has a return type other than void this confuses us, so when the dialog appears you cannot just accept it, since instead of the comma being between the two function names as normal, it appears at the end of the two joined together function names.

case=118972

To get around this, I have changed the snippet into:

const $SymbolType$& Get$GeneratedPropertyName$() const { return $SymbolName$; }
// $ClassName$&
void Set$GeneratedPropertyName$(const $SymbolType$& val)
{
    $SymbolName$ = val;
    return *this;
}

which is a bit ugly, but it keeps the expected void return type, while inserting the expected return type as a comment, making it fairly quick and easy to edit the code into the correct form.

So, the question becomes, which is the least problem here. Your snippet inserts the desired code, and avoids the dialog, as you want. But you don't get VA's help in updating any existing references in your code. Also, since you don't get the dialog, you don't get the check boxes to control public visibility, or searching all projects, etc.

If you do get the dialog, you have to deal with an unwanted dialog, but you can just accept it with Enter once the Find References has finished running, but you also run into the bug caused by having a setter with a return value, which we are looking to fix, but I don't yet have an estimate for when this will be fixed.
FlawedLogic Posted - Jan 11 2019 : 08:54:23 AM
I'm using C++. I've been using both VS2015/VS2017. I usually define a member in the header, then click the VAX drop-down on the name and click encapsulate field.

When I do it puts the definition at the end of the first public area and moves the cursor there too, no dialogue.

I have modified the snippet itself to match our coding standards:

const $SymbolType$& Get$SymbolName$() const { return $SymbolName$; }
$ClassName$& Set$SymbolName$(const $SymbolType$& new_value)
{
    $SymbolName$ = new_value;
    return *this;
}
feline Posted - Jan 11 2019 : 08:41:00 AM
Which programming language are you working in?
How, exactly, are you triggering Encapsulate Field? I am wondering if you are triggering Encapsulate Field via an unusual route, or even using a command from a different extension, or from the IDE its self.

This could explain why you are seeing a different result.

We do show the dialog, first to give you a change to edit the generated names, in case you want to customise them. Secondly it shows the code references that we are going to update, basically a Find References Results window in the bottom half of the dialog. Again this is so you can see what we are going to do before we do it.
FlawedLogic Posted - Jan 11 2019 : 04:08:18 AM
Something odd here then, I'm up to date, 2302, dated 13/12/2018. Same at home (personal licence) and at work (site licence).
accord Posted - Jan 10 2019 : 5:57:25 PM
Which version of Visual Assist are you using? We didn't update references in Visual Assist build 2076 and older.

Encapsulate field pops a rename-like dialog (unless you're using an older build) because it searches for the references of your variables and updates it with the newly created method:
https://docs.wholetomato.com/default.asp?W156

Does this make sense?
FlawedLogic Posted - Jan 10 2019 : 12:16:08 PM
I've never seen that dialogue. When I click encapsulate field it just does it (as I would expect, I don't want a dialogue popping up), is this a global settings dialogue somewhere?
accord Posted - Jan 09 2019 : 7:51:14 PM
case 91882 was about an option to disable creating the accessors in public visibility section during Encapsulate Field.
You can change it on the dialog itself:
FlawedLogic Posted - Jan 09 2019 : 10:35:09 AM
I can't find the new option you've implemented, where is it please?
sean Posted - Nov 20 2015 : 4:01:05 PM
case=91882 was opened for issues discussed in this thread.
case=91882 is implemented in build 2083.
accord Posted - Sep 16 2015 : 4:36:20 PM
*ah* I was talking about a new, planned feature. For example:

class abc
{
   int Apple;
}

void func()
{
    abc obj;
    obj.Apple = 5;
}


With the following example, VA will replace "obj.Apple = 5;" with "obj.SetApple(5)". This is how Rename and Change Signature works now, updating all references.
So learning from your case it might be wise to put a checkbox for NOT updating the references like this.
*oh* And VA will move the variable to a private/protected section as well, hiding it's declaration. So we may need 2 or 3 different checkboxes:

1. do not update references
2. do not move accessors to public section
3. do not move member to hidden section

So 3 checkbox or maybe the 2. and 3. should be the same to avoid way too many options
FlawedLogic Posted - Sep 16 2015 : 01:47:23 AM
quote:
We're planning to update references as well. Would you want to keep that one enabled?

I'm sorry, I don't understand what you mean by that.
accord Posted - Sep 14 2015 : 5:57:43 PM
We're planning to update references as well. Would you want to keep that one enabled?
accord Posted - Sep 13 2015 : 7:01:33 PM
Yes, your request is absolutely legitimate I just wanted to see what's exactly is happening in your case. Thank you for the very detailed explanation, it helps. I kind of hoped that we can move the comment automatically, but your case is special and you also have a coding standard to follow.
FlawedLogic Posted - Sep 11 2015 : 03:58:02 AM

In the class that follows, which follows my companies coding standard's mandated access order, if I encapsulate field I want the comment in the centre public section, for functions, not the first, which is for types. I also want it to take the comment with it.

Previously it just dropped the accessors below the variable, I then copied them, along with the comment, into the public functions section, not too much effort. Now it drops them at the top, below the types, which is wrong so I have to move them, and I also have to go back to the bottom to copy the comment alongside the accessors to ensure the functions are documented for Doxygen as well.

Trust this shows what I mean, I'm aware his might be an unusual scenario for some people, but for me it has turned encapsulate field into a helpful feature into one that is now more effort than just typing the accessors by hand.


template <typename T>
class AClass
{
// Public types
public:

    typedef T value_type;
    
    ... There could be protected or private types here but omitted if not used.
    
    ... This is where encapsulate field currently places the accessors (without comments)
    
// Public functions
public:

    /// Constructor
    AClass() {}
    
    ... This is where I want to put the accessor functions when I encapsulate field
    ... and I want to take the comment with them, so what I want is this:
    
    /// Comment for the variable
    const value_type& GetVar() const { return Var; }
    void SetVar(const value_type& var) { Var = var; }
    
// Protected functions (typically virtuals)
protected:

    ...
    
// Private functions
private:
    ...
    
    ... In very rare circumstances there could be public or protected member variables here
    
// Private data 
private:
    
    /// Comment for the variable
    value_type Var;
   
};
accord Posted - Sep 09 2015 : 7:04:08 PM
Can you please post a sample source code about what do you mean? The accessors are still created but in a different place, into a public section. Can you please include a comment in your sample and describe what would you like VA to do differently?
FlawedLogic Posted - Sep 08 2015 : 01:33:45 AM
Thanks.

By way of explanation, there are two problems I have with the new implementation due to the way we lay out class declarations.

First, our coding standards have a fixed order of access areas within a class declaration, public types, protected types, private types, public functions, protected functions, private functions and then public data (if you are prepared to justify it to your peers), protected data (ditto) and finally private data. Sections are omitted if not used. This means that when I declare a variable, invariably at the bottom of the class, and then use encapsulate field it puts it at the bottom of the first public area, in our case that means if the class has public types it puts it in the wrong place, if it doesn't then your implementation is OK in this respect.

Second, when I define a member variable, the next thing I do is comment what it is, special cases etc, and I want the same comment put above the accessor functions so they get picked up by Doxygen. Because your encapsulate field implementation does not copy the comment, this means, because it has also moved the accessors elsewhere in the file, I have to navigate back and copy the comment as well. This didn't use to be a problem because you dropped it right where the data was and I could copy both in one go.

All sounds a bit arcane but these standards are 15 years old and they aren't going to change. The new implementation of encapsulate field, when you are in a class with public types (quite common nowadays with templates), means a jarring jump to elsewhere in the file, copy from the types to the public functions section, back to the bottom to pick up the comment, back to the public functions sections and paste, a bit of a palaver to say the least.

Perhaps I should request that encapsulate field has an option to takes the comment for the variable with it then it would probably be OK, I would be back to a single copy as I was before.
accord Posted - Sep 07 2015 : 11:15:29 AM
quote:
could I place a request for it.


Sure! I have put in a feature request for this:

case=91882

Can you please explain what's the use case for this? I mean, I would think that the accessors should be in a public sections. Otherwise you won't be able to call them from outside the class. Do you frequently use the feature for things so that the accessors needs to stay in a hidden visibility section? Or you just like doing it the way you want manually?
FlawedLogic Posted - Sep 07 2015 : 04:36:37 AM
Is it possible to turn the new public feature off for encapsulate field and if not could I place a request for it.

Thanks.
sean Posted - Aug 21 2015 : 12:23:50 AM
case=7857 is implemented in build 2073
feline Posted - Jan 24 2011 : 11:47:37 AM
It is unlikely VA will try and do this via a marker comment. A public block in a class is a standard feature that VA can expect to find.

Any form of comment would need to be user definable, since different users will have different comment styles or rules. Plus this is much less obvious, so most users are unlikely to get any benefit from it.

Are you aware that you can use VA Outline to quickly and easily drag and drop reorder the items in your code files, to group and organise them how you want?

http://www.wholetomato.com/products/features/vaoutline.asp
beylevem Posted - Jan 21 2011 : 10:53:05 AM
Would it be possible to specify the location in the header file using a specially formatted comment? The contents of the comment string could be specified using a VA Snippet - e.g.

//=== Accessor Functions

The idea would be to place the new code just below the comment string

kevinsikes Posted - Dec 31 2010 : 4:33:53 PM
John,

You can control the format of the accessors and mutators (getters and setters) by editing the Refactor Encapsulate Field VA Snippet.

Regarding placing the resulting methods in the public section of your class, we have an enhancement request open for this:

case=7857

Please let us know if we may be of further assistance. Have a happy New Year!

© 2023 Whole Tomato Software, LLC Go To Top Of Page
Snitz Forums 2000