Скрытие #include, используемого шаблоном класса, от пользователей класса - PullRequest
1 голос
/ 10 ноября 2011

Рассмотрим следующий код, распределенный по 3 файлам:

// secret.h
#pragma once
class Secret { /* ... */ };

// foo.h
#pragma once
#include "secret.h"
template <typename T>
class Foo {
public:
    // Other members ...
    void bar();
};

/* Definition is included inside 'foo.h' because Foo is a template class. */
template <typename T> void Foo<T>::bar() {
    Secret s;
    /* Perform stuff that depend on 'secret.h' ... */
}

// main.cpp
#include "foo.h"
int main() {
    Foo<int> foo;
    Secret secret; // <--- This shouldn't be allowed, but it is!
    return 0;
}

Итак, моя проблема в том, что я хочу скрыть Секрет от пользователя Foo если они явно не используют #include "secret.h".Обычно это можно сделать, включив secret.h в foo.cpp.Однако это невозможно, поскольку Foo является классом шаблона, и я не могу отделить его определение от его объявления. Явное создание экземпляра шаблона не вариант.

В конечном счете, я хочу знать, возможно ли это каким-либо иным образом, кроме явного создания экземпляра шаблона, и если да, то как?Спасибо!

Ответы [ 2 ]

1 голос
/ 10 ноября 2011

Итак, благодаря подсказке @Mooing Duck, я думаю, что получил ответ.Таким образом, я рассматриваю решение этой проблемы путем создания нового класса, который действует как тонкая оболочка для Secret , который не зависит от параметра шаблона.Этот класс будет другом Foo и обеспечит защищенный доступ к Secret , что позволит Foo получить доступ к Secret без раскрытия Secret для публичного пользователя путем включения "foo.h".

Я обновлю этот ответ фактическим фрагментом кода, как только я напишу и скомпилирую его, и убедитесь, что он работает.

1 голос
/ 10 ноября 2011

Это невозможно при всех тех условиях, которые вы упомянули, потому что написание #include "foo.h" означает, что вы также косвенно пишете #include "secret.h" (значит, все его содержимое).

Вы можете использовать пространство имен, такое как details чтобы ограничить видимость имени класса:

// secret.h
#pragma once

namespace details
{
   class Secret { /* ... */ };
}

А затем напишите details::Secret везде, где вы его используете.

НЕ пишите using namespace details;, НЕ даже using details::Secret;.

...