назначение общих ptrs (boost) в конструкторе, модульное тестирование - PullRequest
4 голосов
/ 27 февраля 2010

У меня есть класс C ++ (внутри проекта dll), переменные-члены которого являются boost :: shared_ptrs для объектов других классов. Лучше назначать их внутри конструктора класса или иметь отдельную функцию init (), которая делает это.

Я предполагаю, что значение по умолчанию для указателя на T внутри boost :: shared_ptr равно NULL. Так что если я ничего не сделаю внутри конструктора, то Boost :: shared_ptr возвращает (NULL) перед вызовом функции Init ().

Кроме того, что происходит, когда в одном из операторов присваивания возникает проблема с выделением памяти для new в одном из операторов присваивания, если я должен перехватить исключение (в Init), или лучше сообщить вызывающей стороне этого Init (), что перехватить это исключение? boost :: shared_ptr a (new T);

Существуют ли стандартные подходы для моделирования исключений выделения памяти внутри модульных тестов? и видим, что все объекты правильно выделены

Ответы [ 3 ]

2 голосов
/ 27 февраля 2010

У меня есть класс C ++ (внутри проекта dll), переменные-члены которого являются boost :: shared_ptrs для объектов других классов. Лучше назначать их внутри конструктора класса или иметь отдельную функцию init (), которая делает это.

Обычно лучше все делать в конструкторе.
Наличие функции init (), которая вызывается afterwords, подразумевает, что объект недействителен после создания, поэтому вам необходимо сохранить флаг состояния, чтобы указать, был ли вызван init (), и проверять этот флаг всякий раз, когда вызывается какой-либо публичный метод, и делать что-то подходящее для неинициализированного объекта

Я предполагаю, что значение по умолчанию для указателя на T внутри boost :: shared_ptr равно NULL. Так что если я ничего не сделаю внутри конструктора, то Boost :: shared_ptr возвращает (NULL) перед вызовом функции Init ().

Да: конструктор по умолчанию для shared_ptr инициализирует его значением NULL.

Кроме того, что происходит, когда в одном из операторов присваивания возникает проблема выделения памяти с new в одном из операторов присваивания, если я должен перехватить исключение (в Init), или это правильно сказать вызывающей стороне этого Init () перехватить это исключение? boost :: shared_ptr a (new T);

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

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

Существуют ли стандартные подходы для моделирования исключений выделения памяти внутри модульных тестов? и увидеть все объекты правильно выделены

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

1 голос
/ 27 февраля 2010

По первому вопросу вы должны в идеале использовать списки инициализаторов, чтобы убедиться, что ваши указатели действительны. Невыполнение этого условия означает, что вам, возможно, придется постоянно проверять правильность вашего указателя перед его использованием; особенно если вы оставите это до вызывающего кода, чтобы позвонить init()

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

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

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

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

Может быть, вы могли бы проверить счетчик ссылок или установить остроконечный объект и (при уничтожении) очистить семафор, который ваш тест мог бы отслеживать. Я что-то упускаю из виду?

1 голос
/ 27 февраля 2010

Использовать списки инициализаторов для назначений членов. Они являются предпочтительным (и иногда единственный подход).

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

Вы всегда можете ловить исключения и сообщать о них. В случае неудачного завершения сеанса вы не должны выдавать исключение, а обрабатывать его в dtor, сообщать об этом и двигаться дальше.

...