1

I have a conceptual doubt which i'll try to put across using an example:

main.cpp

#include "array_list.cpp"
int main() 
{
  array_list list1;
  return 0;
}

Scenario1: array_list.cpp->

class array_list
{
    private:
    int list[10];
public:
    array_list () {};
    ~array_list () {};
    void set_element (int,int);

};

void array_list::set_element (int i,int a) {
list[i] = a;
}

Error:

main.obj : error LNK2005: "public: void __thiscall array_list::set_element(int,int)" (?set_element@array_list@@QAEXHH@Z) already defined in array_list.obj 1>C:\Users\vrastog\Documents\Visual Studio 2012\Projects\C++ learning\Debug\list using arrays.exe : fatal error LNK1169: one or more multiply defined symbols found

Scenario 2: array_list.cpp->

class array_list
{
private:
    int list[10];
public:
    array_list () {};
    ~array_list () {};
    void set_element (int i,int a) {
        list[i] = a;
    }
};

Error: No error!!

Question: I understand the reason for error. The same method has been defined twice, once in main.obj and second in array_list.obj and hence, it should be an error. My question is why does the second scenario work? Here also, since we have includes array_list.cpp in the main file, 'set_element' should have been defined twice here as well. What am I missing here?

  • 2
    Why in the world are you including a `.cpp` file?!? These aren't intended to be included, but compiled separately and linked in the end. – πάντα ῥεῖ Jun 24 '14 at 10:38
  • 1
    I understand that it's not supposed to be included as a good coding practice. But theoretically it's possible. I want to understand the underlying compilation issue through this example. – tyl3rdurd3n Jun 24 '14 at 10:39
  • possible duplicate of [Including .cpp files](http://stackoverflow.com/questions/19547091/including-cpp-files) – Csq Jun 24 '14 at 10:41
  • 2
    This question is essentially asking why an inlined function can be defined multiple times. – Drew Dormann Jun 24 '14 at 10:42
  • @ Drew: Precisely yes!! – tyl3rdurd3n Jun 24 '14 at 10:44
  • @DrewDormann Good point! user267096: I'd be better if the title of the question reflected this. – Csq Jun 24 '14 at 10:47

2 Answers2

2

In-class definition makes a method inline, and therefore it does not cause a multiple definition error in the object file.


An inline method should be implemented in every translation unit it is used in, so the inline method compiles into both object files.

C++ Standard Draft (n3797) 3.2.4: An inline function shall be defined in every translation unit in which it is odr-used.

Also 3.2.6 requires that these function should be exactly the same.

g++ implements this using weak symbols: inline functions are special exported functions that do not cause multiple definition error when linking.

Use a tool like nm under Linux and see for yourself. It emits a weak symbol into the object file:

$ nm arraylist.o
00000000 W _ZN10array_list11set_elementEii
(... ctors, dtors ...)
00000000 T main

Also, if you do not use the function, or the compiler inlines all occurrences, it may get optimized out.

Csq
  • 5,775
  • 6
  • 26
  • 39
  • You mean it doesn't go in main.obj or array_list.obj or both? If it doesn't go into any of the obj file, where does the inline method get compiled? – tyl3rdurd3n Jun 24 '14 at 19:01
  • @user267096 I've extended (and corrected) the answer to contain answers to your question. – Csq Jun 24 '14 at 19:40
  • Thanks for that answer. Clears up my doubt mostly. Just as an extension, what could be the reason that inline functions should have definition in each translation unit in which it has to be used? – tyl3rdurd3n Jun 25 '14 at 16:12
  • @tyl3rdurd3n If you see the definition of a function you can do inlining. If you don't see the definition of a function in a translation unit, all the compiler can do is to generate a function call. – Csq Jun 25 '14 at 16:15
2

Please don't include .cpp files.

In the first example, the function is defined out of class, you need to add inline, otherwise it's a multiple definition.

In the second example, the function is defined in the class definition, so it's an implicit inline function (it's like the compiler added the inline for you), that's why it's not causing multiple definitions.

Zsolt
  • 582
  • 2
  • 5