Aditya Kashi
Aditya Kashi

Reputation: 366

Compilation of C++ member functions defined outside the class body

I have a hpp file like this:

#ifndef __MYLIB_H
#define __MYLIB_H

class A {
public:
  void func1();
  void func2();  
};

void A::func1() {
  // maybe do something
}

#endif

There is a corresponding cpp file which has the implementation of func2. The header file is included by other files in the project (and those are included by yet more files). When I try to build this, I get "multiple definition" linker errors for func1. Why should that happen? Since I've protected the header file with the #ifndef, I did not expect the error.

If I add the keyword inline to the definition of func1, then everything is fine. So if I don't care about a function being inlined and I don't want to have the definition in the class body, I cannot include the definition it in the hpp file? If someone can explain the what's going on here, it'll be very helpful. I'm using GCC 6.

Upvotes: 1

Views: 158

Answers (3)

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726479

Recall that the content of the entire header, along with any files that it may include, is virtually "copy-pasted" into each translation unit* that includes the header at the point of inclusion.

That is why the effect of including the header in multiple CPP files is the same as if you literally copy-pasted function definition into each CPP, i.e. it is the same as if you wrote multiple identical definitions of the same member-function.

The problem is solved by declaring the function inline, because C++ allows multiple definitions of inline functions, as long as they are identical to each other. Moving the body of the function into the declaration of the class also works, because such functions are automatically considered inline.

* In this context, "translation unit" is a fancy name for your CPP file.

Upvotes: 2

unDeadHerbs
unDeadHerbs

Reputation: 1403

The problem is that you are redefining func1 in every file.

The #include directive is a very simple command that just pastes the contents of the header file into the location specified.

The result of this is that each time you #include your header you are "redefining" func1 in that file.

Upvotes: 2

tadman
tadman

Reputation: 211540

Implementations generally go in the associated .cpp files. Putting them in the headers is problematic. inline is a hack to get around this you probably don't want to use since it stamps out that code everywhere it appears, resulting in wild duplication.

Remember, #include is quite like pasting that file in the code right where that directive appears. Having more than one implementation for a function is incorrect, that's why they're split out between header for signature purposes, so it's understood how to use those functions correctly, and implementation for the actual code.

Upvotes: 0

Related Questions