[pimpl] конвертирование класса в его реализацию и наоборот
От: chipmunk  
Дата: 11.06.08 12:10
Оценка:
Есть либа с несколькими взаимосвязанными классами. Делаю для неё public-интерфейс по идиоме pimpl.
Но столкнулся с трудностью, что некоторые классы не должны выставлять наружу некоторых методов, но они используются внутри самой библиотеки. Выход — оперировать внутри библиотеки только impl-версиями классов, а наружу конвертировать их в public-версии. Но не могу придумать как это сделать Также потребуется и обратная конвертация — из public-версии в impl-версию.


class A {
public:
  void doSomething();  
private:
  class AImpl;
  AImpl* m_impl;
};

class AImpl {
public:
  void doSomething();
  void doSomethingOnlyFromLib(); // этот метод используется только внутри библиотеки, наружу выставлять его нет смысла
};


или все-таки хреновый дизайн раз такого хочется ?
pimpl
Re: [pimpl] конвертирование класса в его реализацию и наобор
От: StevenIvanov США  
Дата: 11.06.08 12:22
Оценка: 2 (1)
Здравствуйте, 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, но это ничего.
Re[2]: [pimpl] конвертирование класса в его реализацию и нао
От: chipmunk  
Дата: 11.06.08 13:46
Оценка:
Здравствуйте, StevenIvanov, Вы писали:

спасибо, так и сделал, а то я чуть голову не сломал
Re: [pimpl] конвертирование класса в его реализацию и наобор
От: Кодт Россия  
Дата: 11.06.08 13:51
Оценка: 2 (1)
Здравствуйте, 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>>
Перекуём баги на фичи!
Re: [pimpl] конвертирование класса в его реализацию и наобор
От: Юрий Жмеренецкий ICQ 380412032
Дата: 11.06.08 16:42
Оценка: 2 (1)
Здравствуйте, 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();
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.