Мой товарищ по команде регулярно использует вариацию на pimpl, которая ему нравится:
Foo.h:
namespace { struct Impl; }
class Foo
{
public:
Foo();
~Foo();
void Bar(int n);
/* ... */
private:
std::unique_ptr<Impl> _impl;
};
Здесь происходит то, что он заранее объявляет, что класс реализации находится в анонимном пространстве имен. Затем он определит класс Impl
в Foo.cpp.
Таким образом, определение структуры ::Impl
будет доступно для единицы перевода Foo.cpp
. Другой код, включающий Foo.h
, вызовет предупреждение, потому что они, очевидно, не могут получить доступ к ::Impl
, определенному в Foo.cpp
. Но тогда они нам и не нужны - это класс, предназначенный для использования только в Foo.cpp
; мы не хотим, чтобы он был виден или известен где-либо еще.
И хотя мы, безусловно, можем иметь ситуацию, когда в .cpp
файл включается несколько заголовков, каждый из которых объявляет свои собственные ::Impl
структуры, на самом деле они не конфликтуют, потому что структуры никогда не используются за пределами соответствующих единиц перевода.
tl; dr: Это выглядит странно, вызывает предупреждения и выглядит так, как будто может вызвать конфликты, но, похоже, на самом деле работает.
Все это, как говорится, мне неудобно, когда что-то, вызывающее предупреждения, так глубоко встроено в наш код (чем больше это файлов заголовков, тем сложнее будет удалить). Это также просто тонна предупреждений.
Мой товарищ по команде поддерживает это, потому что это просто, сохраняет простые определения кода и позволяет нам использовать короткое согласованное имя класса Impl
во всем нашем коде.
Я не сторонник соглашений о кодировании; если это хорошая практика для нашего случая использования, я не возражаю. Но я хотел бы чувствовать себя комфортно, потому что это безопасно и ремонтопригодно, и не собирается взорваться в какой-то момент.
::Impl
. Использование::Impl
пытается получить доступ к символуImpl
в глобальном пространстве имен, но его нет в глобальном пространстве имен. Другой распространенный способ - сделать структуруImpl
закрытым членом самого класса. - person Some programmer dude   schedule 25.09.2016Impl
вложенным классом / структурой? Я думал, вы не можете пересылать-объявить вложенный класс (и если вы не можете переадресовать-объявить это, это бесполезно для pimpl). - person Ziv   schedule 25.09.2016Foo.cpp
может действительно получить доступ к указателю. Но я согласен, с любыми неточностями играть опасно. - person Ziv   schedule 25.09.2016class Foo { struct Impl; public: ... };
- person Some programmer dude   schedule 25.09.2016