Странные грабли в C++

Feb 06, 2018 16:02


Наблюдал сейчас такое:

Файл a.cpp:

struct Foo {
 void foo() { cout << "A"; }
}

Файл b.cpp

struct Foo {
 void foo() { cout << "B\n"; }
}

void f() {
 Foo q;
 q.foo();
}

При вызове f() выдается "A". Какого хрена?

Прямо в таком виде пока не проверял, это наблюдается на более сложном коде. Но суть такова.

Update: спасибо Read more... )

Leave a comment

Comments 12

unreal_undead February 6 2018, 13:25:07 UTC
Выглядит как undefined behaviour - я бы ожидал, конечно, что линкер ругнётся на несколько вариантов одного символа, но стандарт не мешает отрегировать как угодно (вызвать не ту функцию, отформатировать диск и т.д.)

Reply

yorool_gui February 6 2018, 14:14:13 UTC
Вот-вот. Просто на функции с одинаковыми именами линкер ругается, сейчас проверил. Но если это классы с одинаковыми именами - то без лишних вопросов создается экземпляр класса из другого исходника - сейчас проверил :-E Это MSVC 2015 если что.

Reply

yorool_gui February 6 2018, 14:28:58 UTC
Точнее не так: экземпляр создается из a, а вот метод для него вызывается из b

Reply

unreal_undead February 6 2018, 14:46:43 UTC
В принципе логично, что для инлайн методов (в том числе неявно объявленного конструктора) линкер ведёт себя по особому - он должен нормально отрабатывать объявление класса в хедере и наличие методов в нескольких объектниках. Возможно, просто сравнивает по размеру - если сходится, считает код одинаковым и берёт первый попавшийся.

Reply


binf February 6 2018, 14:54:41 UTC
А не могли бы Вы солюшен запостить для наглядности?

Reply

yorool_gui February 6 2018, 14:56:50 UTC
namespace {
struct Foo {
void foo() { cout << "A"; }
};
}
и так во всех .cpp файлах

Reply


vikky_13 February 7 2018, 14:51:43 UTC
Раз уж я опоздала с анонимным namespace, тоже полобную забавность расскажу. В gcc можно включать в проект файлы с одинаковыми названиями,но лежащие в разных папках. И вот я такой проект перенесла на visal studio,лаже не подозревая об этом.. Он скомпилировался, но из двух файлов создался один obj -скорее всего,первый по порядку компиляции,или второй переписал первый. Но факт в том,что линковаться оно отказалось, а ошибку я искала почти час :(

Reply

yorool_gui February 7 2018, 21:11:06 UTC
Проверил - и правда так. Переименовываю один из a.cpp - все собирается.

... )

Reply

awson February 8 2018, 08:42:23 UTC
Это косяк MSBuild, а не C++.

Reply


Leave a comment

Up