Скрыть детали реализации через внутренний указатель

У меня есть следующий сторонний класс (просто обертка вокруг некоторого указателя):

// a.h
class AImpl;
class A
{
AImpl*   pImpl;

public:
A(): pImpl(0) {}
A(AImpl* ptr): pImpl(ptr) {}
...
AImpl* getImpl() const { return pImpl; }
...
void someMethodOfA();
};

Я хочу изменить AИнтерфейс: отключите некоторые методы, добавьте несколько новых, скрывая при этом детали реализации. Я решил сделать следующее:

// new_a.h
class AImpl;
class A;

class NewA
{
AImpl*   pImpl;

public:
NewA( const A& a );
...
void newMethodOfA();
...
};

//new_a.cpp
#include "a.h"NewA::NewA( const A& a ): pImpl( a.getImpl() ) {}
...
void NewA::newMethodOfA()
{
A( pImpl ).someMethodOfA();
}
...

Это нормально? Может быть, есть лучшее решение? я хочу измениться A интерфейс, потому что он не соответствует моим потребностям и не хочу хранить его в своем собственном коде.

0

Решение

В комментарии вы говорите, что

Я не хочу выделять A и удерживать A * pImpl, потому что это уже обертка вокруг некоторого указателя (AImpl)

Несмотря на это требование, вы выделяете временный A объект в NewA::newMethodOfA(), Каким образом это должно быть лучше, чем распределение A один раз и просто использовать повторно? Ваше решение не является хорошим, потому что 1) вы создаете новый временный A снова и снова, и 2) вы заставляете пользователей NewA предоставить экземпляр A вместо того, чтобы просто создать его самостоятельно.

Я предлагаю вам прикусить пулю и просто сделать правильную реализацию «PIMPL поверх PIMPL» (как выразился капитан Obvlious):

// new_a.h
class A;

class NewA
{
A* pImpl;

public:
NewA();
~NewA();

void newMethodOfA();
};

//new_a.cpp
#include "a.h"NewA::NewA() : pImpl( new A() ) {}
NewA::~NewA() { delete pImpl; }

void NewA::newMethodOfA()
{
pImpl->someMethodOfA();
}

Это соответствует всем вашим другим требованиям:

  1. Вы не хотите иметь a.h включен в new_a.h
  2. Вы хотите предоставить модифицированный интерфейс A так что пользователи NewA не буду ничего знать о A а также AImpl
  3. Вы хотите скрыть реализацию A

Единственное, что не совсем соответствует, — это то, что в коде вы показываете конструктор по умолчанию A инициализирует его pImpl член 0 — это странно! С каких это пор пользователь класса PIMPL должен предоставлять объект, который обернут классом PIMPL? Ср Википедия Непрозрачная статья указателя.

1

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

Других решений пока нет …

По вопросам рекламы [email protected]