Определение конструктора копирования в классе, унаследованном от структуры POD - PullRequest
1 голос
/ 26 сентября 2011

Как вы знаете, компилятор определяет конструктор по умолчанию, конструктор копирования, оператор присваивания и деструктор для структур POD, если он не был определен вручную. Обычно (или, может быть, я должен сказать всегда), это немного операция копирования. Поэтому я решил унаследовать свой класс от структуры Win BITMAP, чтобы обеспечить выделение памяти в конструкторе и освобождение в деструкторе. Я не использовал состав, потому что я хочу разрешить использовать его с некоторыми функциями WinAPI. Вот фрагмент кода:

class CPreviewFrame : public BITMAP
{
public:
   CPreviewFrame( );
   CPreviewFrame( std::size_t width, std::size_t height, UCHAR bytesPerPixel = 3 );
   CPreviewFrame( const CPreviewFrame& frame );

   ~CPreviewFrame( );
   .....
};

И конструктор копирования определяется примерно так:

CPreviewFrame::CPreviewFrame( const CPreviewFrame& frame ):
   BITMAP( static_cast<BITMAP>(frame) ), //question is here
   m_bufferSize( frame.m_bufferSize )
{
   bmBits = new uint8_t[ m_bufferSize ];
   memcpy( bmBits, frame.bmBits, m_bufferSize );
}

Итак, мой вопрос: это правильный способ вызвать конструктор копирования, определенный компилятором, из унаследованной структуры, или я должен скопировать все поля вручную в теле конструктора? Оба варианта выглядят несколько странно для меня, потому что структуры POD не могут иметь конструкторов, несмотря на то, что их определяет компилятор. Как вы можете вызвать конструктор для типа данных POD, если он не существует по определению?

P.S. Код, упомянутый выше, хорошо компилируется на VS2010.

P.P.S. Есть связанный с этой темой вопрос, размещенный мной здесь .

1 Ответ

4 голосов
/ 26 сентября 2011

BITMAP(frame) выполнит трюк без приведения, так как компилятор будет знать тип родительского объекта и сможет неявно преобразовать аргумент. Обратите внимание, что если вы хотите использовать приведение для явного отображения того, что вы делаете, приведите в качестве ссылочного типа: BITMAP( static_cast<const BITMAP&>(frame) ),

Кроме того, серьезно подумайте об этом наследстве. Примерно через год или два кто-то собирается удалить один из ваших CPreviewFrame объектов как BITMAP. В лучшем случае это утечка памяти, в худшем - на отладку нескольких дней или недель, почему приложение работает неправильно. Композиция (с соответствующим интерфейсом, который может вызывать функцию WinAPI за сценой), как правило, не так сложна для реализации, и она будет более точно и правильно моделировать вашу проблему здесь.

В качестве альтернативы вы можете использовать композицию и просто предоставить получатель для части растрового изображения (как это предлагается в комментарии). Это раскрывает детали реализации вашего класса, но может упростить кодирование в Win API в краткосрочной перспективе.

...