#cpp #language_lawyer
//Файл A.cpp
class A
{
public:
int func( int i )
{
return i*i;
}
};
//Файл Test.cpp
#include
using namespace std;
class A
{
public:
int func( int i )
{
return i*i*i;
}
};
int main()
{
A a;
cout<
using namespace std;
int func( int i )
{
return i*i*i;
}
int main()
{
cout<
Ответы
Ответ 1
Согласно стандарту языка (правилу ODR) классы с external linkage (внешним связыванием),
определенные в нескольких единицах трансляции, должны быть определены одинаково во
всех этих единицах трансляции. Но диагностики этого не требуется.
Точно так же, по ODR, inline-функции с external linkage, определенные в нескольких
единицах трансляции, должны быть определены одинаково во всех этих единицах трансляции.
Но диагностики этого не требуется.
В вашем исходном примере наличествуют как раз две таких сущности - класс с external
linkage и inline-функция с external linkage.
Т.е. спецификация языка требует, чтобы эти сущности были определены одинаково во
всех единицах трансляции, но следить за этой одинаковостью - в общем случае ваша задача.
Продвинутый компилятор может помочь вам ловить такие ошибки, но это просто вопрос качества
реализации.
Как только ваша функция перестала быть inline, диагностика для нарушений ODR для
такой функции сразу же формально потребовалась и компилятор ее успешно вам предоставил.
Ответ 2
В стандарте не уточняется, должен ли компилятор выдавать диагностическое сообщение,
если нарушено правило одного определения. Он только говорит, что в этом случае поведение
программы неопределенное (Раздел Стандарта "3.2 One definition rule", параграф 6).
...If the definitions of D do not satisfy these requirements, then the
behavior is undefined.
Иногда в нем явно указывается, что компилятор не обязан выдавать диагностическое
сообщение, как в этой фразе (там же, параграф 4)
4...Every program shall contain exactly one definition of every non-inline
function or variable that is odr-used in that program; no diagnostic
required.
Даже для того случая, когда вы определили в модуле A функцию вне класса без спецификатора
функции inline, а в другом модуле она была определена внутри класса, а потому по умолчанию
считается inline-функцией, и ваш компилятор (или линкер) выдал сообщение об ошибке,
то даже в этом случае на самом деле компиляторы не обязаны выдавать диагностическое
сообщение (Раздел "7.1.2 Function specifiers"):
4...If a function with external linkage is declared inline in one
translation unit, it shall be declared inline in all translation units
in which it appears; no diagnostic is required.
Это практически невозможно диагностировать компилятору.
Вы должны довольствоваться неопределенным поведением программы.:)
Ответ 3
Test.cpp не знает о существовании A.cpp. Поэтому, используется класс из Test.cpp,
в котором число возводится в куб.
Если код из этих двух файлов переписать в один, то ошибка появится.
Комментариев нет:
Отправить комментарий