|If the getNum() function is inline then there is no overhead. This is what the inline facility is for.|
If a getNum function was needed, then inlining it would be OK, because it is so short & simple. I wouldn't call it from the print function.
I wouldn't use inline for the getNum function in this situation, the following is the correct way to do it:
void example::print() const //why const when there are no args?
std::cout<< num << std::endl;
There is no function call, so no need for inlining anything.
That is why member functions have direct access to member variables. There is no inefficiency in this.
One would only have a getNum function, if it was actually needed. That is, if something outside the class needs it.
Sometimes people think they need to provide a get / set function for each member variable. This is often not the case. You have constructors, mutator functions that set multiple variables from 1 function, output functions like print() that display the value of multiple variables.
In general inline functions need a bit of caution, there can be some unwanted side effects, such as code bloating. There are real problems with inlining constructors & destructors because compilers can generate all kinds of code, which can go in the constructor, to deal with destruction coming from an exception being thrown in a constructor. So the constructor is no longer empty. It's worse when base & derived classes have inline constructors because that multiplies the code bloating. The bloating is also multiplied for each variable created.
There are also problems with inline template functions, and pointers to functions
The inline directive is only a request - the compiler may well ignore it.
I got the stuff about caution with inline functions from Scott Meyers Effective C++ 3rd edition item 30.