Search code examples
c++compilationg++one-definition-rule

c++ include different header files with same implementation of class in multiple source files


For example

a.h

class Dummy {
public:
  Dummy() { std::cout << "a.h" << std::endl; }
};

b.h

class Dummy {
public:
  Dummy() { std::cout << "b.h" << std::endl; }
};

c.cc

#include "a.h"

void test() {
  Dummy a;
}

d.cc

#include "b.h"

int main() {
  Dummy a;
  return 0;
}

Then compile source files with command

g++ d.cc c.cc

output is

b.h

but with command

g++ c.cc d.cc

output is

a.h

My question is why there is no multiple definition error and why the output depends on compilation's order?


Solution

  • Your program has undefined behavior. To summarize the C++ standard's take, here's [basic.def.odr/6] with my emphasis:

    There can be more than one definition of a class type, [...] in a program provided that each definition appears in a different translation unit, and provided the definitions satisfy the following requirements. Given such an entity named D defined in more than one translation unit, then

    • each definition of D shall consist of the same sequence of tokens; and

    • [...]

    [...] If the definitions of D satisfy all these requirements, then the behavior is as if there were a single definition of D. If the definitions of D do not satisfy these requirements, then the behavior is undefined.

    So you observe two different behaviors. Perfectly acceptable, given the language places no restrictions on what behavior you should even see. You violated the contract, so there are no guarantees.

    Now, from a practical standpoint, what you see happen is just GCC operating under the above contract. It assumes you wouldn't violate it (even if you do), and just ignores any subsequent re-definitions of Dummy and/or its members. The first one "wins out".