views:

339

answers:

4

Scott Meyer's argument that non-member functions increase encapsulation and allow for more elegant design (designwise) seems very valid to me. See here: Article

Yet I have problems with this. (And seemingly others too, especially Library developers, who usually completely ignore this)

Code usually looks better and more logical when I use member functions. This may be an acquired taste though and just takes some getting used to looking at algorithms first and then on the objects. (shudder)

So maybe I have only one problem:

With member functions, me AND my IDE know what the class can do.

For me this is huge! I use nothing that doesn't support member function code completion for programming. In well designed libraries it completely replaces documentation for me. And even if I would look at the api doc, looking through the member list just feels absolutely natural, logical and I can be sure that, well, this is the end. If the method is not in there, I can safely assume it doesn't exist and I can write my non-member non-friend.

I put up with this in the STL, because, well, it makes sense to see algorithms apart from basic components and because of the you get used to it factor.

I haven't seen an IDE that can tell me what non-member functions work on a particular class.

And this actually is my question: Is there an IDE (or IDE feature) out there that helps with this code convention?

+1  A: 

I don't believe it is possible for an IDE to tell you all non-member functions that you can use with your class. Using templates, it is simply too difficult to make a list of all such functions. IMO, the best you can hope for is for an IDE to be able to tell you before compilation whether a call you're trying to make is valid. And even that requires some serious compilation-like process inside the IDE.

I understand how you use member functions as a replacement for documentation in classic classes. But the design Scott Meyer suggests isn't about classes that provide complex functionalities, just basic ones. Complex functionalities come from elsewhere, the original class may or may not know about it, it does not really matter. It's all part of the idea. But you are right. In that case, there is a renewed need for well-thought documentation.

Benoît
"I don't believe it is possible for an IDE". For instance, should the IDE list std::swap as a function that can be used on any assignable class, std::max for comparable classes, and so on? The questioner's "list all members" approach doesn't discover these algorithms, either. So I think you're right to say it's basically a problem with no solution.
Steve Jessop
Thanks for your support :)
Benoît
+4  A: 

Meyers is certainly correct that using non-members increases encapsulation, by minimising the number of functions that could potentially access the private state. However, encapsulation is just one of many (often conflicting) aspects of code quality.

He does make a valid point that the library writer won't necessarily write functions for every possible usage of the class (since there may be usages that they don't think of). This means that you may well have to add non-member "helper" functions yourself, just as they would do if they followed Meyers's advice. So there's no way of knowing that the set of member and friend functions is indeed the only set of functions that act on the class.

As a technoluddite, the "IDE" that I favour (a text editor and a shell) has the following "feature" that's pretty good for finding the functions acting on a class:

find . -name '*.h' -o -name '*.cpp' | xargs grep MyClass

I can't comment on "real" IDEs.

Mike Seymour
Well, I could map this in vim.It works ... ok.Do you know if there is a ctags way of doing that query? I use specific tags files for omnicomplete etc. This should be doable with those, shouldn't it?
AndreasT
I don't know about vim or ctags - that's all a bit too high-tech for me. I would suggest that you have a think about why you think you need this functionality. Bear in mind that we're talking about finding all functions that use your class's *public* interface - that could be any function, anywhere in the world (as long as it can access the class definition).
Mike Seymour
If you follow Meyers's (and others') advice and design your class so it has a single well-defined purpose, and a complete and minimal interface that implements that purpose and nothing else, then you shouldn't need to change the interface once it's in use, so there shouldn't be any reason to track down all its users.
Mike Seymour
+1  A: 

I've come across this thing in the past.

My idea then was rather clumsy, but got the job done: namespaces.

What I did was

namespace myclass
{
class MyClass { ... };

MyClass operator+(const MyClass& lhs, const MyClass& rhs){...}
}

S.C. Madsen
+1, I don't think this is particularly clumsy, although you don't necessarily need a namespace per class. The benefit is that you know exactly where to go to get a list of all the library-provided things that can be done to MyClass. Specifically, that place is the documented list of functions in the namespace containing MyClass.
Steve Jessop
A: 

Try to use Visual AssistX, it has this nice feature: Right click on your class, Refactor (VA X) -> Find references. It actually works.

fritzone
Is that different to Visual Studio's Find References? (2010 is much better with C++)
Simon Buchan
Don't know, we're using 2005...
fritzone