Почему компилятор не автоматически вставляет свободно определенную функцию? Вместо этого приводит к ошибке компоновщика - PullRequest
1 голос
/ 29 сентября 2011

Пример:

// header.h
void foo ()  // function definition in the file
{
}

// file1.cpp
#include"header.h"
...

// file2.cpp
#include"header.h"
...

Приведенный выше код приведет к ошибке компоновщика. Предположим, что если компилятор автоматически наберет inline foo(), то ошибки компоновщика не будет.

Мой вопрос касается языковой перспективы. Почему компилятор не делает это inline автоматически? Будет ли это иметь значение?

Вопрос другими словами: "Что может произойти, если компилятор предполагает inline перед каждой определенной свободной функцией?"

Ответы [ 5 ]

6 голосов
/ 29 сентября 2011

Заголовки обрабатываются как копирование текста заголовка.Компилятор не знает, что ваш код находится в заголовке, а не в исходном файле, поэтому он должен обрабатывать их одинаково, учитывая ошибку.Язык определяет это.

1 голос
/ 29 сентября 2011

Это не приводит к ошибке компоновщика. Это может привести к ошибке компоновщика, но компилятору не требуется перехватывать эту ошибку.

Межмодульная согласованность является полностью обязанностью программиста. Компилятор C ++ не обязан видеть, например, что вы используете одно и то же имя класса в двух несвязанных файлах с разными определениями классов. Что бы ни случилось, это твоя вина.

В целом многие явно странные слабости модели компиляции C ++ связаны с тем фактом, что должна быть возможность компилировать программу C ++, рассматривая только один модуль (модуль компиляции) одновременно. Требуется, чтобы компиляция времени и пространства не взорвалась для больших проектов.

1 голос
/ 29 сентября 2011

Ну, ответ, по сути, стандарт C ++ требует, чтобы он вел себя так, как и он. Это часть правила One Definition .

Практически, компилятор должен генерировать видимую компоновщиком функцию в случае, если вы действительно используете ее в другом месте. Например, должен работать следующий file3.cpp:

void foo();
void call_foo() {
    foo();
}

и чтобы это работало, сгенерированный код для foo() должен быть доступен компоновщику. Компилятор просматривает только один блок перевода (файл .cpp плюс все, что в нем содержится), поэтому он не может знать, что он фактически генерирует его дважды. Так оно и есть. Тогда компоновщик ловит его.

0 голосов
/ 29 сентября 2011

Проблема с автоматическим вставкой во время соединения, учитывая, как определяется C, в том случае, если существуют две разные функции с одинаковым именем. Базовые двоичные интерфейсы не поддерживают необходимые метаданные для разрешения таких коллизий. Добавьте третий исходный файл, который использует (но не определяет себя) функцию с таким именем, и он не будет знать, какую из них предполагается использовать.

Я подозреваю, что могут быть некоторые экспериментальные C (или, более вероятно, C-подобные) компиляторы, которые делают это, но они в значительной степени гарантированно нарушат совместимость каким-либо образом.

0 голосов
/ 29 сентября 2011

Это может inline это (но если оно не static, оно все равно должно иметь функцию отдельно), но вы упускаете суть.

Компилятор видит, чтоВы определили функцию с одной и той же сигнатурой дважды.Они могут потенциально отличаться.Поэтому на этапе компоновки будет выдано сообщение об ошибке, сообщающее, что происходит что-то плохое.

Поместите объявление в заголовок void foo (); и внедрите функцию в один из файлов cpp.

...