2010-01-30 2 views
2

Я использую два больших библиотек (GUI & сети), и я могу с радостью делатьКак разрешить конфликт имен между двумя библиотеками в C++?

using namespace FirstLib; 
using namespace SecondLib; 

1 одного класса под названием Foobar где имена конфликтовать исключением.

I мой код, я не использую FirstLib::Foobar. Есть ли способ сказать «в моем коде, когда вы видите Foobar, подумайте SecondLib::Foobar?

+4

Не используйте 'с помощью namespace'. Он был изобретен, чтобы защитить вас от вашей самой проблемы, и он отвратителен, потому что он вновь вводит проблему, как и вы.Используйте псевдоним пространства имен, если вы слишком долго набираете его. – GManNickG

+1

Я не очень большой поклонник dos и donts. В школьных книгах случаи применения никогда не бывают черными или белыми. Фактически, решение, которое я предлагаю (использовать декларацию использования), находится в http://www.parashift.com/c++-faq-lite/coding-standards.html#faq-27.5 – gaspard

ответ

2

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

Если мы не можем сказать,

включают все FirstLib, но удалить SecondLib::Foobar

Мы можем использовать using-declarations точных элементов нам нужно:

using FirstLib::Boids; 
using FirstLib::Life; 
// no using FirstLib::Foobar... 
1

Вы должны выбрать одно из этих пространств имен и избавиться от« использования »и явно вызвать все имена классов. C# есть способ обойти это, но C++ не делает afaik ...

1

Вы в основном ответили на свой вопрос. Вы должны прямо сказать, какой класс вы хотите использовать, поэтому вы должны делать SecondLib::Foobar всякий раз, когда вы используете этот класс.

6

using namespace является evil! Пространства имен были , сделанные, чтобы предотвратить такие проблемы, как у вас! Но это сказал, попробуйте:

using namespace FirstLib; 
using namespace SecondLib; 
using SecondLib::Foobar; 

или даже (для некоторых компиляторов):

using namespace FirstLib; 
using namespace SecondLib; 
typedef SecondLib::Foobar Foobar; 
+3

+1 Однако, когда злое использование любого аспекта C++, полезно объяснить, почему что-то можно рассматривать как таковое, иначе это сбивает с толку. Или, по крайней мере, ссылаясь на C++ FAQ: http://www.parashift.com/c++-faq-lite/big-picture.html#faq-6.15 – mloskot

+0

@mloskot - спасибо за подсказку - хорошая ссылка, я «Я буду связывать свои« злые »с ним, если не будет лучшей ссылки: P –

+0

Ни один из них, похоже, не имеет никакого отношения к GCC, а также к Comeau в Интернете. 'namespace a {struct X {};} namespace b {struct X {}; } с использованием пространства имен a; используя пространство имен b; используя b :: X;/* typedef b :: X X; */int main() {X x; } ' – UncleBens

1

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

Однако, вы можете использовать ЬурейиЙ переименовать класс обижая:

typedef Lib2::FooBar FooBaz; 

И я думаю, с конфликтующей функцией, вы можете использовать указатель на функцию «переименовать» конфликтующие один.


Я думаю, что это не решение. Я могу понять случайную мотивацию использования с помощью объявлений - иногда есть действительно много разных имен, которые вы будете использовать повсюду, но если только один противоречит друг другу: будьте ясными. В любом случае, это будет путать любого, кто знаком с библиотеками, и импортирует оба пространства имён.

Кроме того, использование деклараций относится к области видимости: вы можете сделать одно пространство имен видимым в одной функции, но не в другом пространстве имен - если вы даже не используете его в этой функции.

+0

'typedef Lib2 :: Foobar Foobar' не работает ни с gcc. – gaspard

+0

Это Fooba * z *. Ответ Корнеля отсутствует, что конкретное использование объявления должно быть в функции, а не в глобальной области (я предполагаю, что обычные правила области действия: вещи во внутренней области скрывают вещи во внешней области). – UncleBens

+0

Извините, моя ошибка, это просто, что другой ответ предлагал typedef без изменения имени в имени класса, которое, очевидно, не работает. – gaspard

0

Если вы загружаете все элементы из обоих имен в текущей области путем использования using namespace directove:

using namespace FirstLib; 
using namespace SecondLib; 

и есть возможность, что некоторые из имен в этих имен могут противоречить друг другу, то вам необходимо сообщить компилятору явно какой из элемента, который вы хотите использовать, в текущей области, путем использования using декларации:

using SecondLib::Foobar; 

в качестве стандарта C++ говорит:

7.3.3 с помощью декларации

1 А с использованием декларирование вводит имени в декларативную область в , которая появляется с помощью декларирования. Это имя является синонимом имени некоторой сущности, объявленной в другом месте.

Эта строка просит компилятор думать SecondLib::Foobar всякий раз, когда он видит Foobar для остальной части текущей области видимости, в которой была использована с использованием декларация.

Директива и декларация using очень полезны, но могут вызывать проблемы, с которыми вы сталкиваетесь. Таким образом, неплохо было бы сузить использование любой формы using до минимальной возможной области. Вы можете использовать директиву using namespace в рамках других имен

namespace MyApp { 
    using namespace ::SecondLib; 
} 

или даже функции. То же самое относится к декларации using. Таким образом, это хорошая идея, чтобы сузить сферу применения любого из них:

void foo() 
{ 
    ::SecondLib::Foobar fb; 
} 

Это может показаться утомительным, но это только тогда, когда вы печатаете, хотя вы, скорее всего, использование IntelliSense с поддержкой редактора, поэтому стоимость действительно небольшие, но преимущества большие - никаких путаниц, читаемого кода, проблем с компиляцией.

Это также очень хорошая идея НЕ использовать using namespace в области заголовка. См Header files usage - Best practices - C++

Моего собственного совета: использовать полную квалификацию всякий раз, когда вам нужно использовать любого из этих типов

Смежные вопросы