Why the Class definition does compile one way and not the other?

74 Views Asked by At

I simplified the code to 2 files compiled independently and linked together.

file: main.cpp

class A{
    public:
        int value;
        A(int);
};

#include <iostream>
using namespace std;

int main(int argc, char **argv)
{ A a{7};
    cout<<"a.value="<<a.value<<endl;
    return 0;
}

file: classA.cpp

class A{
    public: 
        int value;
        A(int x):value{x}{};
};

//A::A(int x):value{x}{}

From my understanding of the process, when classA.cpp get's compiled, a function "A::A" is created (a constructor of the Class). If I comment the line A(int x):value{x}{} and uncomment the commented one the result into the object file should be the same.

But in the first case the two object files do not link together, and in the other case they do link. Why is that ?

I checked the object file generated for classA and in the first case is empty, so it is normal that it won't link, But why ?

3

There are 3 best solutions below

7
Ted Lyngmo On BEST ANSWER

The definitions of the two As are different. One has an inline definition of the constructor and the other has not. This is not allowed and would cause undefined behavior if linking had succeeded.

If you make the definitions exactly the same and then define the constructor non-inline:

A::A(int x):value{x}{}

Then the linkage will succeed and the program will have defined behavior.

4
fjs On

The code as you show in classA.cpp is a declaration for class A with inline definition of the constructor. When you link classA.o and main.o together, you have repetitive declarations of class A.

A::A(int _a){...} on the other hand is just a definition of the constructor that complements the class declaration in main.cpp

3
George Kourtis On

As far as I have understood things until now, methods defined inside the class definition, are never exposed in the object file (thus you will not find their name doing an objdump -d on the object file). This is true, either if these are inlined or not. The idea is that what is inside the class definition or "header", is included in every file that makes reference to that "header". Pay attention that in our case such a "header" does contain code too. Given that the above code is included in every file that makes use of the "header" of the class, these functions are recompiled and code is regenerated in every object file that uses the header, so the same function name does not clash with the function names in other object files because none of these definitions has external exposure.

I read from the standard (found the reference from https://softwareengineering.stackexchange.com/questions/56215/why-can-you-have-the-method-definition-inside-the-header-file-in-c-when-in-c-y ) that:

*9.2.1 Member functions

1 A member function may be defined (8.4) in its class definition, in which case it is an inline member function (7.1.2) etc.... (note inline does not mean that is really inlined !!! )

2 An inline member function (whether static or non-static) may also be defined outside of its class definition provided either its declaration in the class definition or its definition outside of the class definition declares the function as inline or constexpr. [Note: Member functions of a class in namespace scope have the linkage of that class. Member functions of a local class (9.4) have no linkage. See 3.5. — end note ] 3 [ Note: There can be at most one definition of a non-inline member function in a program. There may be more than one inline member function definition in a program. See 3.2 and 7.1.2. — end note ]*

Simple ? I don't think !