Why use non-member functions?

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

Recommended Posts

Hey guys,

What are the advantages of using non-member functions?
As an example take a class for a 2D vector:
class Vector2D { public: Vector2D(float x, float y); float getLength() const; static float dot(const Vector2D& left, const Vector2D& right); float x; float y; };
This is the way I implemented my vector class, but I have seen implemantations which define all methodes and operators as non-member functions. Isn't it the same as declaring a methode static (not the operators)?

I also have a class with has no instance-methodes only static-mthodes:
class Directory { static void remove(const std::string& path); static void create(const std::string& path); ... };
Isn't this a more clean way of writting code since everything is organized nicely in classes?

I hope these questions are not to newbie ^^

Share on other sites
Member functions are part of the class definition. Some non-immediately obvious consequences of this include the fact that you can't call member functions, including static member functions, with just a forward declaration. Adding or removing a member function forces recompilation of code that depends on the class definition even if it doesn't change the representation or core interface. Member functions have access to complete class details and therefore all need to be vetted to see if they respect class invariants.

If you want to group a bunch of functions together you can use a namespace rather than stick static member functions in a class.

Share on other sites
I try to only put functions in a class when they need to access private members. Just looks cleaner to me and removes unneeded dependencies.

Also I'm interested in what that class is doing:

Edit: nevermind ....

Share on other sites
Because they can be extended without modying the original class, something C++ doesn't support.

Consider this:template < class T > void print_length(T t) { std::cout << t.length; // vs. std::cout << length(t); }

If I give you Vector2 which you cannot modify (for any reason), it needs to have .length() member. If it doesn't, we're stuck. In some cases one could inherit Vector2, but that doesn't help if I'm not the one creating the instance.

I can however define length() as free function at any time, so even if I'm given third-party type, I can support it.

To C#/Java programmers this may seem foreign. But at least Ruby and JavaScript have proven that such extensibility is very welcome in practice.

A lot of patterns in Java exist solely due to lack of ability to declare free functions, resulting in orthogonal code duplication to satisfy language constraints. C# did introduce a few additions that help with this, even if it continues to constrain everything to objects.

Isn't this a more clean way of writting code since everything is organized nicely in classes?[/quote]

C++ has namespaces that serve this function.

Share on other sites
In addition to what SiCrane said, I'd imagine that even if you may not prefer "dot(v1, v2)" to "Vector2D::dot(v1, v2)", you could probably 'forgive' people with such a preference(?).

I very much second the use of namespaces rather than classes as, well, a space for names, as you then get the benefits of ADL and "using" directives.

Share on other sites
So you guys would suggest to implement all functions of the Vector2D class as non-member ones?
This seems very odd to me (I'm from the Java/C# section)

The class Directory contains static methodes for managing directories such as removing or creating one.
It's supposed to be a static class, but I'll just implement those functions in a namespace.

I tend to use static methodes, because if I use a lot of namespaces the names tend to get quite ugly and long:
 core::math::dot(v1, v2); core::filesystem::remove("dir"); 

Thanks for the replies!

Share on other sites

So you guys would suggest to implement all functions of the Vector2D class as non-member ones?

Look at STL design. Perhaps operator << and >> overloads, also design of containers. Stuff closely associated with type is declared as members, the rest are free functions. This allows general stuff like <algorithm>.

It's supposed to be a static class, but I'll just implement those functions in a namespace.[/quote]

Does it carry a state? Then it's a class. Otherwise, it's a namespace.

If "Directory" has to hold something, such as handle, it has to be a class.

I tend to use static methodes, because if I use a lot of namespaces the names tend to get quite ugly and long:[/quote]
For caller, there is no real difference between class or namespace in that regard.

Long namespace chains can become a problem, but C++ provides a few helpers for that:{ using namespace core; math::dot(v1, v2); filesystem::remove("dir"); }These should be used in smallest scope possible, definitely never in headers.

Alternative: namespace c = core; c::math::... c::filesystem::... 

Namespaces can also be extended externally. So you could do something like this:#include <core.h> // which defines core:: functions; namespace core { void foo() { math.dot(a,b); // we're in core namespace } }There's some annoying gotchas with this approach.

For deeply nested types, such as class declared inside multiple namespaces, typedef works:typedef core::math::Vector2D C2D; C2D v;

And I've probably forgotten about some other techniques.

Share on other sites
Thanks Antheus!
That should do the trick.

I will also look how the STL was designed to improve my style.

Thanks guys, you really helped me alot

Share on other sites
Yes, *stream from the std library is probably the best example of that usage.

Say, you have a class from an external library that you want to output in a stream, just overload the << operator. (Operators can be free functions, I didn't realize that for quite a while)

 class ClassFromExternalLibrary { const char* getName() const; ... }; ... std::ostream& operator <<(std::ostream& stream, const ClassFromExternalLibrary& instance) { stream << instance.getName(); return stream; } 

Share on other sites

So you guys would suggest to implement all functions of the Vector2D class as non-member ones?
This seems very odd to me (I'm from the Java/C# section)

Implement as non-member function if it's possible. ADL is great.

The class Directory contains static methodes for managing directories such as removing or creating one.
It's supposed to be a static class, but I'll just implement those functions in a namespace.

I tend to use static methodes, because if I use a lot of namespaces the names tend to get quite ugly and long:
 core::math::dot(v1, v2); core::filesystem::remove("dir"); 

If v1 and v2 are in core::math namespace, you can rely on the ADL and just call:
 dot(v1, v2); 

How Non-Member Functions Improve Encapsulation: http://drdobbs.com/184401197

1. 1
2. 2
Rutin
19
3. 3
khawk
15
4. 4
A4L
13
5. 5

• 13
• 26
• 10
• 11
• 44
• Forum Statistics

• Total Topics
633744
• Total Posts
3013658
×