VisualStudio 2017 15.8.1 есть модуль a.cpp с кодом: Код (Text): class Foo { public: int a = 5; __declspec(noinline)Foo() {__debugbreak();}; }; void test_2() { { __debugbreak(); Foo d; ++d.a; } } и есть модуль b.cpp с кодом: Код (Text): class Foo { public: int a = 1; int b = 2; int c = 3; __declspec(noinline) Foo() { cout << "ctor()\n"; } __declspec(noinline) Foo(Foo&) { cout << "c_ctor()\n"; } __declspec(noinline) ~Foo() { cout << "dtor()\n"; } Foo& operator=(const Foo&) { cout << "assignment op\n"; } Foo(int, int, int); };//... линкуются вместе, ошибок нет. при отработке void test_2() вызывается конструктор из файла b.cpp, конечно решается обёртеой Foo в любой неймспейс, но вообще я ожидал что линкер ругнётся на редеф конструктора...
тоже самое и с методами. только единсна - по какойто причине компилер в модуле а не генерит кода, а в б генерит. и референц с а идёт в б.
А почему он должен ругнуться? У вас тут UB, и можно случиться вообще все что угодно. По умолчанию компилятор предполагает, что если он видит 2 и более определения одного и того же класса, то они идентичны) Стоит почитать про ODR: Only one definition of any variable, function, class type, enumeration type, concept (since C++20) or template is allowed in any one translation unit (some of these may have multiple declarations, but only one definition is allowed). There can be more than one definition in a program, as long as each definition appears in a different translation unit, of each of the following: class type, enumeration type, inline function with external linkage inline variable with external linkage (since C++17), class template, non-static function template, static data member of a class template, member function of a class template, partial template specialization, concept, (since C++20) as long as all of the following is true: each definition consists of the same sequence of tokens (typically, appears in the same header file) ... If all these requirements are satisfied, the program behaves as if there is only one definition in the entire program. Otherwise, the behavior is undefined.
Это всё следствие того, что инстанцированные темплейты надо как-то компоновать так, чтобы они не дублировались. Короче, типа фича, а не баг со стороны C++.
Нашёл возможное решение для вас - оберните класс в анонимный неймспейс, и будет счастье: Код (Text): namespace { class Foo { /* ... */ } } [code]
вот еще кстати, проверял на микромягком: class SampleClass { public: __declspec(noinline) void Message(char* d) { MessageBoxW(0, 0, 0, 0); } }; пилим это в 2 модуля, компилим и линкуем их. и нету ошибок линкера о редефе, хотя каждый объектник содержит идентично замангленный Message притом в секции PUBLIC. тут либо я хреново маны курнул, либо так и должно быть. ну и само собой каждый модуль будет прилинковывать "свой" экземпляр. если имплементацию в одном снести - прилинкует оную с другого модуля. единственно что не проверил - 3 модуля: в двух с noinline inclass definition а в третьем - только декларация. кого слинкует.
SadKo , спс, но просто пробую различные вариации разного с разным. а насчёт анонимного ns - там тоже интересно, один компилер запиливает в объектниках всё как static другой - нет f1redArk да понятно, руководствуюсь cppreference разумеется, просто как уже написал - миксую, смотрю на реализацию