Есть либа с несколькими взаимосвязанными классами. Делаю для неё public-интерфейс по идиоме pimpl.
Но столкнулся с трудностью, что некоторые классы не должны выставлять наружу некоторых методов, но они используются внутри самой библиотеки. Выход — оперировать внутри библиотеки только impl-версиями классов, а наружу конвертировать их в public-версии. Но не могу придумать как это сделать
Также потребуется и обратная конвертация — из public-версии в impl-версию.
class A {
public:
void doSomething();
private:
class AImpl;
AImpl* m_impl;
};
class AImpl {
public:
void doSomething();
void doSomethingOnlyFromLib(); // этот метод используется только внутри библиотеки, наружу выставлять его нет смысла
};
или все-таки хреновый дизайн раз такого хочется ?
Здравствуйте, chipmunk, Вы писали:
C>....
C>C>class A {
C>public:
C> void doSomething();
C>private:
C> class AImpl;
C> AImpl* m_impl;
C>};
C>class AImpl {
C>public:
C> void doSomething();
C> void doSomethingOnlyFromLib(); // этот метод используется только внутри библиотеки, наружу выставлять его нет смысла
C>};
C>
C>или все-таки хреновый дизайн раз такого хочется ?
да почему же... самое простое, что может прийти в голову ввести метод getImpl в класс A:
class A
{
public:
void doSomething();
class AImpl;
// пометить, что for internal use only, и использовать все равно не получится
AImpl * getImpl()
{ return m_impl; }
private:
...
};
небольшой trade-off, но это ничего.
Здравствуйте, StevenIvanov, Вы писали:
спасибо, так и сделал, а то я чуть голову не сломал
Здравствуйте, chipmunk, Вы писали:
C>Есть либа с несколькими взаимосвязанными классами. Делаю для неё public-интерфейс по идиоме pimpl.
C>Но столкнулся с трудностью, что некоторые классы не должны выставлять наружу некоторых методов, но они используются внутри самой библиотеки. Выход — оперировать внутри библиотеки только impl-версиями классов, а наружу конвертировать их в public-версии. Но не могу придумать как это сделать Также потребуется и обратная конвертация — из public-версии в impl-версию.
Можно сделать такое
// facade.h
class Impl;
typedef shared_ptr<Impl> impl_ptr;
class PublicFacade
{
protected:
impl_ptr m_impl;
public:
PublicFacade();
protected:
explicit PublicFacade(impl_ptr impl) : m_impl(impl) {}
public:
void foo();
void bar();
};
// private.h
class PrivateFacade : public PublicFacade
{
public:
PrivateFacade() {}
PrivateFacade(const PublicFacade& src) : PublicFacade(src) {}
// а в обратную сторону даже делать ничего не нужно, срезка нас полностью устраивает
public:
void buz();
void xyz();
};
Если нужно как-то поаккуратнее с копированием — то придётся немножко похимичить: запретить всё неявное, сделать дружественные функции поверхностного копирования.
... << RSDN@Home 1.2.0 alpha rev. 655>>
Здравствуйте, chipmunk, Вы писали:
C>Есть либа с несколькими взаимосвязанными классами. Делаю для неё public-интерфейс по идиоме pimpl.
C>Но столкнулся с трудностью, что некоторые классы не должны выставлять наружу некоторых методов, но они используются внутри самой библиотеки. Выход — оперировать внутри библиотеки только impl-версиями классов, а наружу конвертировать их в public-версии. Но не могу придумать как это сделать Также потребуется и обратная конвертация — из public-версии в impl-версию.
...
Интерфейсы рулят:
// client ///////////////////////
class A
{
public:
typedef boost::shared_ptr<A> ptr;
virtual void doSomething() = 0;
virtual ~A(){}
};
A::ptr CreateA();
void SomeFunc(A::ptr);
// lib ///////////////////////////
class AImpl : public A
{
public:
virtual void doSomething(){
//...
}
void doSomethingOnlyFromLib(){
//...
}
};
A::ptr CreateA()
{
return A::ptr(new AImpl());
}
void SomeFunc(A::ptr p)
{
AImpl* impl = boost::polymorphic_downcast<AImpl*>(p.get());
impl->doSomethingOnlyFromLib();
}