2009-11-02 2 views
3

Если вы используете вложенные пространства имен, объявления в заголовочных файлах могут быть очень длинными и нечитаемыми.Сокращение вложенных имен пространства имен

//header1 
namespace test { namespace test1 { 
class Test {}; 
} } //namespace 

В HEADER2 программы:

#include "header1" 

namespace test2 { 

class Test1 { 
    void test(test::test1::Test &test) {} 
    void test1(test::test1::Test &test) {} 
    void test2(test::test1::Test &test1, test::test1::Test &test2) {} 
}; 

} 

Существует ли какая-либо возможность укоротить имена в HEADER2?

+0

Приложение: поскольку header2 должен быть включен в другие части программы, использование псевдонимов или псевдонимов не может использоваться. – bighil

ответ

5

Вот моя любимая техника:

#include "header1" 

namespace test2 { 

class Test1 { 
private: 
    typedef ::test::test1::Test MeaningfulName; 

    void test(MeaningfulName &test) {} 
    void test1(MeaningfulName &test) {} 
    void test2(MeaningfulName &test1, MeaningfulName &test2) {} 
}; 

} 

Я делаю мои ЬурейиЕ псевдонимы частными, но я их в самом начале объявления класса. Не имеет значения, что они являются частными для остальной части программы, потому что никто не будет использовать псевдонимы, они будут использовать фактическое имя типа или свой собственный псевдоним для имени.

Я также предпочитаю использовать привязанные имена пространства имен, чтобы избежать последующих сюрпризов. Мое правило для этого заключается в том, что I всегда использует привязанное имя, если только пространство имен не является одним из элементов управления и/или является частью текущего проекта или пакета или чего-то еще. Тогда я буду использовать кратчайшее возможное относительное имя. Если это относительное имя будет начинаться с корневого пространства имен, я все же часто использую привязанное имя.

Основная проблема заключается в том, что digraph <: может появиться в объявлениях шаблонов, как только вы начнете чаще использовать привязанные имена. Вы должны уложить пространство, чтобы избежать этого, тем более, что обработка орграфа происходит на самом раннем этапе и может дать вам очень странные сообщения об ошибках.

+0

Я хотел бы добавить оговорку, что, поскольку 'private' имеет доступ к символам, а не их видимость, это может привести к тому, что эти имена будут разрешаться и не будут доступны в производных классах, что может быть немного запутанным для некоторых. – Omnifarious

0

В файле header2.h

using namespace test::test1; 
+2

Это работает, но я предлагаю избегать использования объявлений в файлах заголовков. – MP24

+0

Что вводит больше возможностей конфликтов имен. Я настоятельно рекомендую избегать «использования» в заголовках в качестве общего правила. –

3

вы можете псевдоним пространств имен, как это:

namespace tt=test::test1; 
+0

, но тогда будет tt быть псевдонимом для test :: test1 во всех файлах, в которые включен заголовок2, -> может иметь имя test :: test1 tt в первую очередь – bighil

+0

@bighil: вы не псевдоним пространства имен в заголовке, но в том числе, кто знает, что псевдоним (локально) уникален –

+2

Вопрос о файле заголовка, а не файле реализации. Так что эта техника - плохая идея. – Omnifarious

1

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

Вы должны помнить, что объявление чего-либо в заголовке такое же, как объявление его в каждом файле cpp, в который включен этот заголовок. Также было бы интересно спросить себя: «Если вы часто используете test1 внутри test2, почему они разные пространства имен?»

0

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

Этот метод определенно не самый безопасный, поскольку он включает в себя использование препроцессорных директив, но мне понравилось использовать #define и #undef для сокращения пространств имен в заголовках.

Вот пример:

#include "header1" 

#define shortNS test::test1 
namespace test2 { 
    class Test1 { 
     void test(shortNS::test &test) {} 
     void test1(shortNS::test &test) {} 
     void test2(shortNS::test &test1, shortNS::test &test2) {} 
    }; 
} 
#undef shortNS 

В основном он работает путем создания определяют называемые «shortNS», что препроцессор слепо заменяет «тест :: test1», где когда-либо это происходит после определения. Разумеется, проблема с определением макроса заключается в том, что он не ограничивается областью действия в какой-либо форме или форме, что может нанести ущерб и, как известно, заставляет любого ничего не подозревающего программиста терять рассудок, пытаясь его отладить.

Таким образом, чтобы предотвратить то, как только мы закончим с определением, мы #undef shortNS, чтобы сообщить препроцессору прекратить замену «shortNS» на «test :: test1». Это позволяет в некоторой степени моделировать область. В приведенном выше примере я ограничил shortNS «областью» файла.

Вот краткий список плюсов и минусов от верхней части головы.

Плюсы:

  • Позволяет вручную ограничить объем. (Только для половины функции?).
  • Прозрачный для всех, включая файл. не
  • Нет левой над пространством имен, как с «пространство имен = B :: C»
  • нет пространства имен коллизий с «использованием имен»
  • не приносит имен в текущее пространство имен (например, «с использованием пространства имен» делает)

Минусы:

  • Любые ошибки в определении укороченного пространства имен будет появляться там, где она не используется и не на самом макросе.
  • Если вы включите файл в блок #define #undef, то определение будет использоваться во включенном файле, что может привести к непредвиденным результатам и/или головным болям.
  • Если вы забудете #undef, он может/будет разрушать хаос, и вы сойдете с ума.
  • Это немного неуклюжий.
  • Люди, которые поддерживают ваш код, будут вас ненавидеть.

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

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