1

So, I have a pretty simple project in VS2019 that includes three files:

a.h

#pragma once

class A {
public:
    A();
};

a.cpp

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

main.cpp

#include <vector>
#include "a.h"

int main() {
    std::vector<A> va;
    va.emplace_back();
    return 0;
}

It works fine without vectors. But this code throws an linker error about constructor. What I really don't understand is if I change a.cpp that way:

#include "a.h"

A::A() {}

it works fine. Why doesn't the linker see the constructor in the body of the class?

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • What you currently haver in A.cpp redefines the `A` class. You don't want to do that. Your second attempt is the correct solution. It implements the constructor. – user4581301 Apr 26 '21 at 18:56
  • Oh. Ok, I got it, thanks. – VasterLordEP Apr 26 '21 at 19:07
  • I believe that 'defaulting' the constructor should be preferred over an empty body. `A::A() = default;` in header, and that's it. – sweenish Apr 26 '21 at 19:07
  • @IWonderWhatThisAPIDoes: Actually it is very common to define a class in multiple places (different compilation units) simultaneously. But it is very important that all of these definitions are identical, this is a formal requirement with a nice name: the **One Definition Rule** and there is a dedicated StackOverflow tag for it: [tag:one-definition-rule] – Ben Voigt Apr 26 '21 at 19:14

1 Answers1

1

The compilation unit with main sees only this declaration

class A {
public:
    A();
};

and indeed the constructor is not defined.

The declaration of the class A in the module a.cpp breaks the one definition rule. That is the class declared in a.cpp is not the same as the class declared in a.h.

In the case of this definition of the module a.cpp

#include "a.h"

A::A() {}

the both compilation units have the same class declaration and for this class there is defined the constructor.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335