Стандарты программирования на С++. 101 правило и рекомендация | страница 104
>f(int)
будет невидима для >B::g
, если ее объявление окажется после объявления >using
.Рассмотрим два частных случая. Пусть фрагменты 1, 2 и 3 находятся в трех различных заголовочных файлах >s1.h
, >s2.h
и >s3.h
, а фрагмент 4 — в файле реализации >s4.срр
, который включает указанные заголовочные файлы. Тогда семантика >B::g
зависит от порядка, в котором заголовочные файлы включены в >s4.срр
! В частности:
• если >s3.h
идет перед >s2.h
, то >B::g
будет вызывать >A::f(int)
;
• иначе если >s1.h
идет перед >s2.h
, то >B::g
будет вызывать >A::f(doublе)
;
• иначе >B::g
не будет компилироваться вовсе.
В описанной ситуации имеется один вполне определенный порядок, при котором все работает так, как должно.
Давайте теперь рассмотрим ситуацию, когда фрагменты 1, 2, 3 и 4 находятся в четырех различных заголовочных файлах >s1.h
, >s2.h
, >s3.h
и >s4.h
. Теперь все становится существенно хуже: семантика >B::g
зависит от порядка включения заголовочных файлов не только в >s4.h
, но и в любой код, который включает >s4.h
! В частности, файл реализации >client_code.срр
может пытаться включить заголовочные файлы в любом порядке:
• если >s3.h
идет перед >s2.h
, то >B::g
будет вызывать >A::f(int)
;
• иначе если >s1.h
идет перед >s2.h
, то >B::g
будет вызывать >A::f(doublе)
;
• иначе >B::g
не будет компилироваться вовсе.
Ситуация стала хуже потому, что два файла реализации могут включать заголовочные файлы в разном порядке. Что произойдет, если >client_code_1.срр
включает >s1.h
, >s2.h
и >s4.h
в указанном порядке, a >client_code_2.срр
включает в соответствующем порядке >s3.h
, >s2.h
и >s4.h
? Тогда >B::g
нарушает правило одного определения (one definition rule — ODR), поскольку имеются две несогласующиеся несовместимые реализации, которые не могут быть верными одновременно: одна из них пытается вызвать >A::f(int)
, а вторая — >A::f(doublе)
.
Поэтому никогда не используйте директивы и объявления >using
для пространств имен в заголовочных файлах либо перед директивой >#include
в файле реализации. В случае нарушения этого правила вы несете ответственность за возможное изменение смысла следующего за >using
кода, например, вследствие загрязнения пространства имен или неполного списка импортируемых имен. (Обратите внимание на "директивы и объявления >using
для пространств имен". Указанное правило неприменимо при описании члена класса с помощью объявления >using
для внесения, при необходимости, имен из базового класса.)
Во всех заголовочных файлах, как и в файлах реализации до последней директивы