Я играл с кодом, чтобы понять внутреннюю и внешнюю связь в c ++. Я придумал код, выход которого, кажется, меняется в зависимости от последовательности, в которой он связан.
test1.cpp
#include<iostream>
using namespace std;
inline int c()
{
static int p=0;
p++;
return p;
}
void a()
{
cout<<"\nIn function a() , c = "<<c();
}
test2.cpp
#include<iostream>
using namespace std;
inline int c()
{
static int p=12;
p++;
return p;
}
void b()
{
cout<<"\nIn function b() , c = "<<c();
}
driver.cpp
#include<iostream>
using namespace std;
void a();
void b();
int c();
int main()
{
b();
a();
a();
b();
cout<<"\nIn function main() = , c "<< c();
cout<<"\n";
}
вывод 1: —
when compiles as follows :-
bash#>g++ -c test1.cpp
bash#>g++ -c test2.cpp
bash#>g++ -c driver.cpp
bash#>g++ -o out driver.o test1.o test2.o
bash#>./out
In function b() , c = 1
In function a() , c = 2
In function a() , c = 3
In function b() , c = 4
IN main() , c = 5
В приведенном выше выводе компилятор рассматривает c (), определенный в test1.cpp
вывод 2: —
изменение последовательности test1.o и test2.o при компоновке.
bash#>g++ -o out driver.o test2.o test1.o
In function b() , c = 13
In function a() , c = 14
In function a() , c = 15
In function b() , c = 16
IN main() , c = 17
В приведенном выше выводе компилятор рассматривает c (), определенный в test2.cpp
Я был озадачен, когда я сделал небольшие изменения в коде, а именно:
1) если я не вызову c () в функции a () [test1.cpp] и c () в функции b () [test2.cpp]
//test1.cpp changes
void a()
{
cout<<"\nIn function a() , c = "; // not calling c()
}
//test2.cpp changes
void b()
{
cout<<"\nIn function b() , c = "; // not calling c()
}
Я получаю следующую ошибку при ссылке: —
bash#>g++ -o out driver.o test1.o test2.o
driver.o: In function `main':
driver.cpp:(.text+0x1f): undefined reference to `c()'
collect2: ld returned 1 exit status
2) Если я вызову c () в любом из файлов, т. Е. В test1.cpp или test2.cpp, то я не получу ошибку компоновщика.
Может ли кто-нибудь, пожалуйста, помогите мне в понимании этого поведения.
Заранее спасибо.
Ваша программа имеет неопределенное поведение, потому что она нарушает правило единого определения. Две разные единицы перевода определяют функцию с одинаковым именем и подписью, но с разными телами.
В соответствии с пунктом 3.2 / 6 стандарта C ++ 11:
[…] Дано
такой объект по имениD
определено более чем в одной единице перевода, затем— каждое определение
[…]D
должен состоять из одинаковой последовательности токенов; а также
Ваша программа также плохо сформирована, потому что функция c()
объявлен как inline
в test1.cpp
а также test2.cpp
, но не в driver.cpp
, Согласно пункту 7.1.2 / 4
[…] Если функция с внешней связью
объявленныйinline
в одной единице перевода это должно быть объявленоinline
во всех переводческих единицах, в которых он появляется;
Диагностика не требуется. […]
«Диагностика не требуется«бит» означает, что компилятор (или компоновщик) может сообщать или не сообщать об ошибке за нарушение этого правила. Это означает, что вы должны быть очень осторожны, чтобы его нарушить.
Других решений пока нет …