Хорошо, этот вопрос развился немного, и я хочу попытаться запуститься с основных целей, для которых я стреляю:
Я часто сталкиваюсь с этим сценарием, и ищу лучший путь...
У меня есть класс, C в пространстве имен N. C имеет участника, Свободного. Это free's что-то, чем C управляет и позволяет C управлять новой вещью.
Существует несколько глобальных Бесплатных функций. Существует также несколько функций помощника в том же пространстве имен N как C, один из которых является помощником что free's вещь, управляемая C, названным свободным.
Таким образом, у нас есть что-то как:
namespace N {
void free(THING * thing);
class C
{
public:
... details omitted...
free()
{
free(m_thing); // <- how best to refer to N::free(THING&)
}
}
} // namespace N
Я мог использовать N:: свободный (m_thing). Но это кажется неудачным мне. Там никакой путь не состоит в том, чтобы отослать к тому, что вне объема класса, но не разрешая абсолютное пространство имен (относительный шаг, мудрый объемом)?
Мне что, имея необходимость назвать N кажется:: свободный неприятно, так как Вы не имели бы к тому, если бы это было автономной функцией. И при этом Вам не было бы нужно к тому, если бы имя метода класса, оказалось, отличалось (например, расположило). Но потому что я использовал то же имя, я не могу получить доступ к нему, не имея необходимость указывать, какие суммы к полному пути - а не относительный путь - если Вы будете потворствовать мне аналогия.
Я ненавижу полные пути. Они делают перемещающиеся вещи в пространствах имен очень хрупкими, таким образом рефакторинг кода становится намного более ужасным. Плюс, правила того, как назвать вещи в телах функции, становятся более сложными с текущим подшипником (поскольку я понимаю их) - менее регулярный - стимулирование раскола между тем, что каждый ожидает и что каждый получает как программист.
Существует ли лучший способ получить доступ к автономным функциям в том же пространстве имен как класс, не имея необходимость абсолютно называть свободную функцию абсолютно?
Править: Возможно, я должен был пойти с менее абстрактным примером:
namespace Toolbox {
namespace Windows {
// deallocates the given PIDL
void Free(ITEMIDLIST ** ppidl);
class Pidl
{
public:
// create empty
Pidl() : m_pidl(NULL) { }
// create a copy of a given PIDL
explicit Pidl(const ITEMIDLIST * pidl);
// create a PIDL from an IShellFolder
explicit Pidl(IShellFolder * folder);
...
// dispose of the underlying ITEMIDLIST* so we can be free to manage another...
void Free();
};
Таким образом, ITEMIDLIST* прибывают из множества мест и уничтожаются с CoTaskMemFree (). Я мог представить Pidl как глобальное имя - а также все функции помощника в заголовке "Windows Shell.h", который является частью моей библиотеки панели инструментов.
Идеально, я сегментировал бы некоторые инструменты в моей библиотеке тем, чего они касаются - в этом случае, прежде всего, касается COM, программирующего в Windows. Я имею, выбрал Toolbox в качестве основного пространства имен для моего материала библиотек и в настоящее время думал, что я буду использовать Панель инструментов:: Windows для очень функций окон-y, классов, и т.д.
Но пространство имен C++ и правила определения имен, кажется, делают это очень трудным (следовательно этот вопрос). Это делает это очень неестественным для создания такой сегментации моего кода - с тех пор koenig сбои поиска (так как ITEMIDLIST не находится на моей Панели инструментов:: пространство имен Windows), и у меня нет способности переместить его туда! Ни если я. Язык должен быть достаточно выразительным, IMO, обоим позволяют, чтобы дополнительные библиотеки, такие как моя библиотека Toolbox расширились, другие люди кодируют, не имея необходимость вводить мои расширения в их пространство имен (который, в случае Win32 и общего подавляющего большинства кода, который существует сегодня, ГЛОБАЛЬНЫЙ NS - который является смыслом создания пространств имен во-первых: избегать глобальной давки NS / загрязнение / неоднозначность / программирующие неожиданности).
Так, я возвращаюсь вокруг к, Есть ли лучший способ сделать это: Расширьте существующие библиотеки кода, не загрязнение их NS с моими расширениями, но все еще допускает интуитивное и полезное определение имен, как можно было бы ожидать, был ли мой код в их NS, но явно представлен клиентом моего кода (т.е. Я не хочу вводить свой код волей-неволей, но только по явному запросу)?
Другая Мысль: Возможно, что удовлетворило бы, мой выше критериев был бы то, если бы у меня было следующее:
using namespace X {
code here...
}
Куда я мог поместить такую конструкцию куда угодно, включая в заголовке, и я не должен буду быть обеспокоен перетаскиванием X в код моего клиента, но у меня была бы та же свобода записать мой исходный код, как я был бы, если бы я был в корневом пространстве имен.
Я не вижу, чтобы избежать необходимости указывать здесь namespace-scope free ()
, но следует отметить, что это не то же самое, что «абсолютный путь». Во-первых, если у вас есть вложенные пространства имен, вам нужно обратиться только к самому внутреннему:
namespace N1 {
namespace N2 {
namespace N3 {
void free(THING * thing);
class C {
public:
free() {
N3::free(m_Thing); // no need to do N1::N2::
}
};
}
}
}
[EDIT] в ответ на отредактированный вопрос. Опять же, я не вижу никакого способа сделать это в том сценарии, который вы описываете. Однако это не кажется идиоматическим подходом C ++ - более распространенный способ сделать то же самое - предоставить собственный класс-оболочку для ITEMIDLIST
, который управляет всеми выделениями в стиле RAII и предоставляет исходный дескриптор (например, с помощью операторов преобразования а-ля ATL или явной функции-члена, такой как c_str ()
, если вам нужна дополнительная безопасность). Это полностью устранит необходимость в вашем бесплатном
, и для любой другой бесплатной функции, которая может вам понадобиться, поскольку вы контролируете тип оболочки и пространство имен, в котором она находится, вы можете использовать ADL как обычно.
[РЕДАКТИРОВАТЬ №2] . Эта часть вопроса:
допускает интуитивно понятное и полезное разрешение имен, как и следовало ожидать, если бы мой код был в их NS, но явно введен клиентом моего кода (т.е. я не хочу вводить свой код волей-неволей , но только по явному запросу )?
Разве это не то, что вы помещаете в пространство имен, и ваш клиент, записывающий с использованием пространства имен ...
, достигнет?
Мне кажется, что здесь есть проблема дизайна.
Мне кажется странным иметь такой же идентификатор используется и как бесплатная функция, и как метод класса, это действительно сбивает с толку. Я стараюсь свести к минимуму количество случаев, насколько это возможно, хотя я допускаю, что это происходит для свопа
...
Я стараюсь не уточнять имена внутри метода, но здесь, конечно, вы рискуете of сокрытие
, где MyClass :: free
скрывает метод N :: free
, который никогда не участвует в поиске ... попытался выяснить разрешение области здесь, но мне не удалось найти точный отрывок.
Для обмена я просто использую:
class MyClass
{
void swap(MyClass& rhs)
{
using std::swap; // Because int, etc... are not in std
swap(m_foo, rhs.m_foo);
swap(m_bar, rhs.m_bar);
}
};
inline void swap(MyClass& lhs, MyClass& rhs) { lhs.swap(rhs); }
Поэтому я удостоверяюсь, что правильный метод будет включен в поиск, и избегаю использования «глобального» метода, если таковой имеется.
Юу мог написать :: free (m_thing);
. Это вызовет глобальную функцию free ()
. Однако если у вас есть другая функция free ()
за пределами пространства имен N, у вас возникнут проблемы. Либо измените имена некоторых из ваших функций, либо используйте имя функции с явным пространством имен.
Я бы использовал совершенно другой подход к тому, чего вы пытаетесь достичь. Я думаю, вам нужно немного переделать. Удалите глобальные переменные и создайте фабрику / абстрактную фабрику, которая будет производить (создавать экземпляр вашего класса) и уничтожать его с помощью деструктора. Фактически, это идиома RAII.
У вас есть два варианта:
THING
принадлежит пространству имен N
). Я бы выбрал первую с таким популярным именем функции, как free
.
Альтернативный вариант - использовать m_thing-> Release ()
или что-то в этом роде.