A class type datatype such as structs (and classes) contains data members and there are functions to which we can pass these struct objects. Here, data and behavior are separated. It would be good if we can put the data and behaviors together at the place. This is where member functions come into existence.
For example,
struct Point
{
int x{};
int y{};
};
void printPoint(Point &p)
{
std::cout << p.x << ", " << p.y << "\n";
}
int main()
{
printPoint(Point{1, 2});
return 0;
}We need to pass Point object to printPoint which then it prints to the console.
Member functions
We can change above example into something following where we put function definition inside the Point itself.
#include <iostream>
struct Point
{
int x{};
int y{};
void print()
{
std::cout << x << ", " << y << "\n";
}
};
int main(int argc, char const *argv[])
{
Point p{1, 2};
p.print();
return 0;
}print is now a member function to Point. We invoke member function on the struct object which is p in this case. This is similar to accessing data members using dot operator.
Object from which member function is invoked is implicitly passed to the member function and we can directly access members of the object as shown in the example.
A member function has to be declared inside the class (or struct) but can be defined inside or outside the class (or struct). A member function is different from nonmember function (called free function) as it has internal linkage by default. So, defining the class type multiple has no issue with ODR.
Note
If we are defining member function outside then it comes under the eyes of ODR.
A member function can be defined outside as shown below,
struct Point
{
int x{};
int y{};
void print();
};
void Point::print()
{
std::cout << x << ", " << y << "|" << "\n";
}