Указатель на вопрос Указатель - PullRequest
4 голосов
/ 04 марта 2009

У меня есть класс с (не умным) указателем на интерфейсный объект (назовем его pInterface), и я создаю вложенный класс, которому также нужен доступ к этому интерфейсу. Я собираюсь обойти это, передав указатель на интерфейс в конструктор вложенного класса следующим образом:

CNestedClass someClass( pInterface, ... );

Однако я не уверен, как лучше хранить этот указатель во вложенном классе. Я мог бы использовать:

1) A scoped (or other smart) pointer (to the original object)
2) A pointer to a pointer 

Что бы вы, ребята, предложили и почему?

РЕДАКТИРОВАТЬ: я должен уточнить - вложенный класс должен будет вызывать методы для объекта интерфейса, однако он не создает его (или изменяет объект, на который указывает), за это отвечает родительский класс.

Ответы [ 5 ]

6 голосов
/ 04 марта 2009

Используйте указатель на указатель, если любой класс может изменить значение указателя - например, удалив существующий объект и заменив его новым. Это позволяет обоим классам по-прежнему использовать один и тот же объект, разыменовывая указатель на указатель.

Если вы не заботитесь о том, чтобы объект оставался действительным на протяжении всего жизненного цикла обоих классов.

  • Если вложенный класс живет короче, вам не о чем беспокоиться.
  • Если это то же самое, при условии, что вы выполняете очистку в правильном порядке (например, сначала вложенный класс, потом объект), тогда вам снова не о чем беспокоиться
  • Если вложенный класс может сохраниться после уничтожения владельца, вы должны реализовать способ, обеспечивающий сохранение этого объекта.

Если вам необходимо обеспечить время жизни объекта, это можно сделать с помощью семантики подсчета ссылок, либо вручную, либо через интерфейс интеллектуального указателя.

Для умного указателя хорошим вариантом будет Boost :: shared_ptr. shared_ptr позволяет владельцу объекта совместно использовать несколько указателей. Когда последний shared_ptr выходит из области видимости, объект удаляется.

(обратите внимание, что это не относится к auto_ptr, где объект принадлежит исключительно).

Что нужно знать;

  1. При использовании boost :: shared_ptr убедитесь, что вложенный класс имеет копию shared_ptr, а не ссылку / указатель.
  2. std :: auto_ptr ведет себя совершенно по-разному, объекты принадлежат исключительно и не используются совместно
  3. boost :: shared_ptr может работать только с объектами кучи, например, указатели, возвращаемые при вызове «new»

Пример: * * тысяча тридцать-один

typedef boost::shared_ptr<Interface> shared_interface;

class NestedClass
{
  shared_interface mInterface; // empty pointer
}

void NestedClass::setInterface(shared_interface& foo)
{
  mInterface= foo; // take a copy of foo.
}

void ParentClass::init( void )
{
  // mInterface is also declared as shared_interface
  mInterface = new Interface();
  mNestedClass->setInterface(mInterface);
}
2 голосов
/ 04 марта 2009

Другая причина, по которой вы можете захотеть использовать указатель на указатель, заключается в том, что код external может изменить исходное значение указателя (например, сделать его указателем на новый объект или установить его в NULL после выпуская объект, на который он указывает). Тем не менее, IMO это очень плохая практика, чтобы изменить указатель после передачи его кому-то еще.

Таким образом, если ни внешний код, ни вложенный класс не изменяют указатель, просто сохраните его во вложенном классе как копию исходного указателя как переменную-член (поле).

1 голос
/ 04 марта 2009

Передайте адрес указателя на ваш интерфейс (IMyInterface ** ppInterface) и заполните указатель, если он реализован классом.

Класс может привести свой указатель this к этому интерфейсу и заполнить указатель * ppInterface. Если класс не реализует этот интерфейс, он может установить * ppInterface в NULL.

0 голосов
/ 04 марта 2009
class Outer
{
    class Inner
    {
    };
};

Поскольку объект Outer содержит только указатель RAW на объект pInterface, это означает, что объект Outer не владеет и не контролирует продолжительность жизни объекта pInterface. Поэтому мы надеемся, что есть некоторая гарантия, что объект pInterface будет жить столько же, сколько и внешний объект; В этом случае нет никакой причины даже использовать указатель, вы могли бы просто использовать ссылку (при условии, что нет ситуации, когда pInterface будет иметь значение NULL).

Зависит от того, как Inner хранит свою «ссылку» (не ссылку на C ++), и нам действительно нужно больше информации об отношениях между вовлеченными объектами!

  • Какова реализация между Внутренними и Внешними объектами.
  • Какова продолжительность жизни Внутреннего объекта по отношению к Внешнему объекту, от которого он унаследовал указатель pInterface?
  • Что является гарантией того, что срок службы внешнего объекта короче, чем у объекта pInterface.

и т.д.

0 голосов
/ 04 марта 2009

По сути, вы делите указатель на один и тот же объект между двумя разными объектами. Если вы не используете умные указатели, просто сохраните указатель на общий объект. Вы должны быть осторожны с владельцем общего объекта, т. Е. Какой объект отвечает за освобождение общего объекта и уведомление других о его исчезновении.

...