Как поместить некоторый код в несколько пространств имен без дублирования этого кода?
Предположим, что у меня есть метод, определенный в двух разных пространствах имен:
namespace foo
{
void print()
{
//do work...
}
}
namespace bar
{
void print()
{
//do work...
}
}
Функции foo::print()
и bar::print()
абсолютно равны. В моем проекте используются многочисленные вызовы этих функций.
Есть ли способ удалить одно из print()
определений без изменения вызовов этой функции? Я имею в виду что-то вроде следующего (конечно, язык С++ не позволяет эту конструкцию, это просто пример):
namespace foo, bar //wrong code!
{
void print()
{
//do work...
}
}
Если нет способа реорганизовать код, как я хочу, скажите, пожалуйста, вам нравится следующее решение? Будете ли вы рады, если ваш проект содержит такой код?:)
namespace foo
{
void print()
{
//do work...
}
}
namespace bar
{
void print()
{
foo::print();
}
}
ADD:
Спасибо, ребята, я полностью удовлетворен вашими ответами. Только один момент я хочу, чтобы вы уточнили: есть ли разница между using ::foo::print
и using foo::print
?
Ответы
Ответ 1
Вы можете достичь этого с помощью объявления using
.
namespace foo
{
void print()
{
//do work...
}
}
namespace bar
{
using foo::print;
}
ИЗМЕНИТЬ
Относительно разницы между ::foo::print
и foo::print
: добавление квалифицированного имени с:: означает, что вы явно ссылаетесь на имя в глобальном пространстве имен. Это можно использовать для выбора глобального, даже если в области есть еще один объект с тем же именем.
Ответ 2
Как насчет объявления using
:
namespace foo
{
void print()
{
// do work ...
}
}
namespace bar
{
using ::foo::print;
}
Использование ::foo::print
вместо foo::print
является важной точкой. Если у вас есть еще foo
внутри bar
:
namespace foo
{
void print()
{
// 1 ...
}
}
namespace bar
{
namespace foo
{
void print()
{
// 2 ...
}
}
using foo::print; // refers to 2
using ::foo::print; // refers to 1
}
тогда вы увидите преимущество использования ::
. Подводя итог, добавление ::
- это безопасный способ гарантировать, что другое вложенное пространство имен foo
, которое может быть потенциально добавлено в будущем, не принесет вам никаких сюрпризов.
Ответ 3
С объявлением using
:
namespace bar
{
using ::foo::print;
}
Ответ 4
Возможно, лучшим решением является следующее:
namespace foo
{
void print()
{
//do work...
}
}
namespace bar
{
void print()
{
foo::print();
}
}
Однако вы можете написать:
namespace foo
{
void print()
{
//do work...
}
}
namespace bar
{
void print()
{
//do work...
}
}
Это не рекомендуется, но нет зла. Компиляторы достаточно умны, чтобы понять, что эти две функции одинаковы и могут использоваться один и тот же код сборки.
Помните, что ключевое слово namespace
предназначено для программистов, компилятор их не заботит, поскольку пространства имен компиляторов похожи на префикс для функций/методов/классов.
Ответ 5
Пример
namespace Q {
namespace V {
void f(); // enclosing namespaces are the global namespace, Q, and Q::V
class C { void m(); };
}
void V::f() { // enclosing namespaces are the global namespace, Q, and Q::V
extern void h(); // ... so this declares Q::V::h
}
void V::C::m() { // enclosing namespaces are the global namespace, Q, and Q::V
}
}