Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++: Difference between member and non member functions

Tags:

c++

oop

What is the difference between member and non-member functions in C++?

like image 811
Luke Avatar asked May 07 '11 12:05

Luke


People also ask

What is the difference between function and member function?

A function declared/defined within a class is a member function and a function declared/defined outside the scope of a class is a function.

What is the difference between data member and member function?

Data members are the data variables and member functions are the functions used to manipulate these variables and together these data members and member functions defines the properties and behavior of the objects in a Class.

What is a member function in C?

Member functions are operators and functions that are declared as members of a class. Member functions do not include operators and functions declared with the friend specifier. These are called friends of a class.

What is the difference between static member function and non static member function?

A static member function can be called, even when a class is not instantiated. A static member function cannot have access to the this pointer of the class. A non-static member function can be declared as virtual but care must be taken not to declare a static member function as virtual.


2 Answers

There are several differences between a member function (which I will now call method) and a free function (which I will now call function).

First, let's just state that they are not so different. Object code can generally be compiled down to C (or assembly) which are procedural languages with no notion of methods. Both methods and functions are then called like subroutines.

Now that this is out of the way, let's look at the differences. They can be classified in two categories: conceptual and syntactic.

Syntactically

The syntax is the obvious part of any language, so it's the easiest to get out of the way.

First note: there are two different kinds of methods in C++ (and a number of other languages), the static methods and regular methods.

Both kinds of methods have full access to the class internals (protected and private sections) as well (of course) as access to the class public interface.

static methods are equivalent to friend functions (apart from some scoping differences).

Within a regular method, a special keyword (this in C++) allows access to the current object on which the method has been invoked (via the ., ->, .* or ->* operators).

A regular method may be const and/or volatile qualified, enabling it for (respectively) const and/or volatile qualified objects. For example, a non-const method cannot be called on a const object. This can be seen as qualifying this within the method, ie void Foo::bar() const has a this of type Foo const*.

A regular method may be marked as virtual. Virtuality enables runtime polymorphism by enabling overriding. I won't extend on this mechanism here, let's just note that functions cannot be virtual.

One often ignored point, is that methods (both static and regular) are scoped within the class. This is important for name lookup (of other methods or attributes/variables) as it means that the elements of the class have priority during lookup from a method on the elements declared outside of the class.

Since the qualification using this-> before attribute or methods is not mandatory, this comes handy in regular methods, though it may introduce subtle bugs. In static methods, it avoids qualifying by the class name the static attributes and methods one whishes to access.

Now that the main syntactic differences have been asserted, let's check the conceptual differences.

Conceptually

OOP is generally about tying together state and behavior (of this state). This is done by creating classes which group attributes (state) and behavior (methods) and (in theory) stating that only the methods can act on the state. Therefore, in OOP, the methods are responsible for implementing the behavior of the class.

The methods participate to the encapsulation of state (freeing clients from the implementation detail) and to the preservation of the class invariants (statements about the class state that hold true from its birth to its death, whatever you do with it).

C++

In C++, as we have seen previously, this is done by using different access levels (public, protected and private) and granting access to the non-public levels to a restricted portion of the code. Generally attributes will be private and thus only accessible to the class methods (and maybe some friends, for syntax quirks).

Note: I urge you not to use protected attributes, it's hard to track down their modifications and since the set of derived classes is unbounded... their implementation cannot be changed easily afterward.

However, beware that C++ discourages from bloating the interface with lots of methods.

The trouble is that because methods are responsible of maintaining invariants, the more there are and the more the responsability is spread, making it more difficult to track down bugs and ensure correctness. Also, since methods depends on the class internals, it makes change more costly.

Instead, in C++, it is generally advised to write a minimal set of methods and delegating the rest of the behavior to non-friend functions (as long as it doesn't increase the cost too much).

  • See Sutter's take on std::string in Monolith Unstrung.
  • The delegation to non-friend methods was emphasized by Sutter in its Interface Principle in which he states that functions that are delivered with the class (in the same file/same namespace) and use the class, are logically part of the class interface. He restates in Exceptional C++.

This answer is becoming rather long-winded, yet I suspect that I have overlooked differences that other would find critical... oh well.

like image 105
Matthieu M. Avatar answered Sep 25 '22 08:09

Matthieu M.


A (non-static) member function has an implicit this argument, a non-member doesn't.

Syntactically, you pass that implicit argument on the left of the . or -> operator like.so() or like->so(), instead of as a function argument so( like ).

Likewise, when declaring a member function, you need to do so in the class of which it is a member:

class Class { public:     void a_public_member_function(); }; 

Non-member functions are instead declared outside any class (C++ calls this "at namespace scope").

(Non-static) member functions can also be virtual, but non-member functions (and static member functions) cannot.

like image 34
Marc Mutz - mmutz Avatar answered Sep 23 '22 08:09

Marc Mutz - mmutz