odr2_create(); o1->xxx(); o2->xxx(); } odr1.cpp #include <stdio.h> #include "odr.h" class CDummy : public CBase { public: void xxx() override { printf("odr ONE dummy: Hello\n"); } }; CBase *odr1_create() { return new CDummy(); } odr2.cpp #include <stdio.h> #include "odr.h" class CDummy : public CBase { public: void xxx() override { printf("odr TWO dummy: World\n"); } }; CBase *odr2_create() { return new CDummy(); } Under a Linux shell to try out, compile with: g++ -c odr1.cpp g++ -c odr2.cpp g++ -c main.cpp g++ -o odr main.o odr1.o odr2.o Under a Windows Visual Studio "Build Tools Command Prompt", compile with: cl /c main.cpp cl /c odr1.cpp cl /c odr2.cpp cl /Feodr.exe main.obj odr1.obj odr2.obj When executed the expected output is: odr ONE dummy: Hello odr TWO dummy: World But you very likely get: odr ONE dummy: Hello odr ONE dummy: Hello The problem is, that the C++ linker has to figure out how to build the virtual method table for the (two different) "CDummy" classes, and that only works if the class names are different. See also Include directive Include guard References C++ Articles with example C++ code