Доступ на уровне пространства имен

У меня следующая ситуация:

namespace MyFramework {
class A {
void some_function_I_want_B_to_use() {}
};
class B {
B() {
some_function_I_want_B_to_use() {}
}
};
}

где я хочу some_function_I_want_B_to_use не быть видимым за пределами MyFramework пространство имен, но я хочу, чтобы оно было видимым для всех внутри MyFramework (в качестве альтернативы можно также видеть только класс B). У меня есть несколько таких методов, это единственный способ скрыть их от публичного API MyFramework, чтобы все классы были внутри MyFramework друзья? Я также рассматривал возможность размещения всех классов «более низкого уровня» внутри B, но я не хочу идти по этому пути, пока не буду уверен, что это обеспечит возможность доступа ко всем методам A изнутри B, но не из за пределами MyFramework.

Иными словами, у меня есть фреймворк, созданный в одном пространстве имен, и у каждого класса есть методы, которые полезны для широкой публики при использовании фреймворка. Однако каждый класс также имеет несколько методов, которые усложняют общедоступный API, но необходимы для правильной работы инфраструктуры.

2

Решение

Идиома, часто называют Компиляция Firewall, это то, что вы ищете. Целый Qt реализуется с использованием этой идиомы.

// A.hpp
namespace MyFramework {
class A {
private:
class Private;

Private* implementation;
};
}

// A_Private.hpp
#include "A.hpp"
namespace MyFramework {
class A::Private {
public:
void some_function_I_want_B_to_use() {}
};
}

// A.cpp
#include "A_Private.hpp"
namespace MyFramework {
A::A() {
implementation->some_function_I_want_B_to_use();
}
}

// B.hpp
#include "A.hpp"
namespace MyFramework {
class B {
B();

A a;
};
}

// B.cpp
#include "A_Private.hpp"
namespace MyFramework {
B::B() {
a.implementation->some_function_I_want_B_to_use();
}
}

НОТА: Конечно A_Private.hpp не входит в include каталог вашего фреймворка, окончательный дистрибутив, т.е. он остается частный пакет как вам требуется.

Пример очень простой. Конечно, это можно сделать более продвинутым и надежным. Дополнительно, Pimpl имеет много других преимуществ. Для всей этой информации обратитесь к:

2

Другие решения

Я хочу some_function_I_want_B_to_use не быть видимым за пределами MyFramework пространство имен, но я хочу, чтобы оно было видно любому MyFramework,

Таким образом, вы хотите что-то похожее на пакеты в Java.

К сожалению, для вас это не возможно с пространствами имен. Каждый класс, включенный в пространство имен, доступен из внешнего пространства имен: пространства имен открыты.

Решение обычно состоит в том, чтобы добавить другое пространство имен для деталей реализации:

namespace MyFramework
{
// Implementation details
// Should not be used by the user
namespace detail
{
class A
{
public:
void func();
};
}

class B
{
public:
B()
{
A a;
a.func();
}
};
}

Не забудьте добавить комментарий о detail пространство имен не должно использоваться пользователем.

3

Общее соглашение, например, в Boost — это вложенное пространство имен detail,

Если хотите обеспечивать соблюдение доступность вы всегда можете вместо этого использовать вложенный class называется detail, Класс обеспечивает проверку доступности, но ему не хватает расширяемости, как в пространстве имен. Тем не менее, detail сфера будет редко, если когда-либо потребуется расширение.

Итак, во всем своем безобразии,

namespace my_framework {
class detail
{
private:
static void some_function_I_want_B_to_use() {}

public:
class A
{};

class B
{
B() { some_function_I_want_B_to_use(); }
};
};

typedef detail::A A;        // "using detail::A"typedef detail::B B;        // "using detail::B"}  // namespace my_framework

Попутно обратите внимание, что класс B (прямо из вопроса) имеет собственный конструктор по умолчанию, поэтому его экземпляры не могут быть созданы.

2
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector