2010-10-31 6 views
12

Если в C++ у меня есть класс longUnderstandableName. Для этого класса у меня есть заголовочный файл, содержащий его объявление метода. В исходном файле для класса, я должен написать longUnderstandableName::MethodA, longUnderstandableName::MethodB и так далее, везде.C++: «Пространства имен классов»?

Могу ли я каким-то образом использовать пространства имен или что-то еще, поэтому я могу просто написать MethodA и MethodB в исходном файле класса и только там?

+0

На данный момент ответ отрицательный. ** Но ** ... Существует [предложение добавить ** 'namespace class' ** к языку] (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/ 2016/p0223r0.html), что позволит точно определить, что вы и я хотим: разрешить определение уже объявленных членов класса в блоке, который автоматически откроет их для класса, - и, таким образом, избежать постоянного повторного набора пространства имен классов, шаблона аргументы и т. д. Это странно, что это взято до сих пор, и это все еще только в стадии предложения, но мы здесь. Вздох! Я действительно надеюсь, что это превратит его в C++ 20 или что-то еще. –

+0

@underscore_d К сожалению, это предложение не включает эквивалент 'using class', поэтому он еще не обеспечивает полную гибкость. – negamartin

+0

@negamartin Что еще вы ищете? Просьба привести пример. Главное, что 'namespace class' разрешит это повторение для автора класса, который является перспективой, с которой OP задавал этот вопрос. Тем временем пользователи класса могут делать что-то вроде 'using tiny_type = SomeNamespace :: SomeOtherNamespace :: AHugeClassName;'. Что еще вы хотите? –

ответ

0

Я не уверен, что я рекомендовал бы это, но вы могли использовать макрос, как:

#define sn LongUnderstandableName 

void sn::MethodA(parameters) { ... } 
int sn::MethodB(parameters) { ... } 

и так далее. Одна из плохих точек макросов заключается в том, что они не учитывают область видимости, но в этом случае область, которую вы (по-видимому) хотите, является исходным файлом, который, как представляется, соответствует (довольно близко) с объемом макроса.

+1

+1, это быстрое решение, но я бы тоже не рекомендовал его. Это рецепт катастрофы. –

+1

Да - я бы скорее определил его как макрос в редакторе, поэтому мне нужно только ввести краткое имя, и оно автоматически будет расширено до реального, но никто не должен знать об этом , –

+0

Вместо этого вы можете использовать typedef. –

0

Ну, да, как только вы понимаете пространства имен.

Вместо того, чтобы назвать свой класс MyBonnieLiesOverTheOcean, вместо того, чтобы установить следующее:

namespace My { namespace Bonnie { namespace LiesOverThe { 
    class Ocean { ... }; 
} } } 

Теперь, когда определение методов, вы кладете те же пространство имен по всему файлу, и вы пишете:

Ocean::SomeMethod() ... 

При использовании класса от внешних всех пространств имен, это:

My::Bonnie::LiesOverThe::Ocean 

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

+0

Это хорошая идея, но она должна сосать, чтобы набрать все эти :: :) –

+0

Ну, вот почему мы «используем». – bmargulies

+0

Ах, да, да. Вы можете сказать «использовать My :: Bonnie :: LiesOverThe'; а затем работать с последним уровнем вложенности –

1

Внутри методов классов вы можете использовать имя без квалификации, так или иначе: просто снимите префикс longUnderstandableName::.

В функции внутри исходного файла класса, которые не являются методами, я предлагаю ввести файл-Scope статические встроенные функции, например, так:

inline type MethodA(type param){ 
    return longUnderstandableName::MethodA(param); 
} 

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

+0

Да, но это заставляет вас определять метод внутри заголовка, что неэффективно, потому что оно вынуждает перекомпилировать всех клиентов всякий раз, когда класс изменяется. –

+1

Нет, это не заставляет вас это делать.Фактически, вы не должны определять метод в заголовке, но в верхней части исходного файла класса - иначе ярлык будет доступен в глобальном масштабе, который OP не хочет выполнять. –

+1

Работает только для статических элементов. – Basilevs

11
typedef longUnderstandableName sn; 

Затем вы можете определить методы, как

void sn::MethodA() {} 
void sn::MethodB() {} 

и использовать их в качестве

sn::MethodA(); 
sn::MethodB(); 

это работает только если longUnderstandableName это имя класса. Он работает, даже если класс глубоко внедрен в другое пространство имен.

Если longUnderstandableName это имя пространства имен, то в пространстве имен (или исходного файла), где вы хотите использовать методы, вы можете написать

using namespace longUnderstandableName; 

, а затем вызывать методы, как

MethodA(); 
MethodB(); 

Вы должны быть осторожны, чтобы не использовать using namespace foo; в заголовочных файлах, потому что тогда он загрязняет каждый файл .cpp, который мы делаем #include в файле заголовка, но используя using namespace foo; в верхней части .cpp файл определенно разрешен и поощряется.

+0

Действительно ли это работает? Я имею в виду, что typedef - это спасатель, чтобы делать аббревиатуры, но декларации обычно имеют тенденцию к оригинальным именам. Вы использовали этот подход? – Basilevs

+0

@Basilevs: объявлениям не требуются оригинальные имена. Typedef не «создает новый тип», отличный от старого, он просто создает новое имя, относящееся к тому же старому типу. Люди используют этот подход все время, чтобы перевести что-то вроде 'std :: map :: iterator' в нечто более короткое. (И 'std :: map :: iterator' уже обычно является' typedef' для некоторого класса, который представляет собой деталь реализации в STL. –

+0

Но это не декларация итератора. вы цитируете использование типа итератора, объявленного в другом месте. – Basilevs

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