Why do class member functions defined outside the

2019-07-20 05:15发布

问题:

I have read existing answers on the two meanings of inline, but I am still confused.

Let's assume we have the following header file:

// myclass.h

#ifndef INCLUDED_MYCLASS
#define INCLUDED_MYCLASS

class MyClass
{
   public:
      void foo(); // declaration
};

inline void MyClass::foo()
{
    // definition
}

#endif

Why does void foo() which is defined outside the class in the file, have to be explicitly defined with inline?

回答1:

It's because you defined MyClass::foo in a header file. Or a bit more abstract, that definition will be present in multiple translation units (every .cpp file that includes the header).

Having more than one definition of a variable/function in a program is a violation of the one definition rule, which requires that there must be only one definition in a single program of every variable/function.

Note that header guards do not protect against this, as they only protect if you include the same header multiple times in the same file.

Marking the function definition as inline though means that the definition will always be the same across multiple translation units.1.

In practice, this means that the linker will just use the first definition of MyClass::foo and use that everywhere, while ignoring the rest,


1: If this is not the case your program is ill-formed with no diagnostics required whatsoever.



回答2:

If you put MyClass::foo() in a header file and fail to declare it inline then the compiler will generate a function body for every compilation unit that #includes the header and these will clash at link time. The usual error thrown by the linker is something along the lines of Multiple definition of symbol MyClass::foo() or somesuch. Declaring the function inline avoids this, and the compiler and linker have to be in cahoots about it.

As you mention in your comment, the inline keyword also acts a hint to the compiler that you'd like the function to be actually inlined, because (presumably) you call it often and care more about speed than code size. The compiler is not required to honour this request though, so it might generate one or more function bodies (in different compilation units) which is why the linker has to know that they are actually all the same and that it only needs to keep one of them (any one will do). If it didn't know they were all the same then it wouldn't know what to do, which is why the 'classical' behaviour has always been to throw an error.

Given that the compilers these days often inline small functions anyway, most compilers also have some kind of noinline keyword but that is not part of the standard.

More about inline at cppreference.