Я переписываю некоторый код для устранения глобальных переменных и заставляю конструктор / деструктор класса выполнять очистку некоторых сторонних библиотечных ресурсов, но меня беспокоит некоторый код, который инициализирует один член из другого члена в списке инициализатора класса.
class MyPodofoDocument {
public:
// generates pdf to stream
MyPodofoDocument(std::stringstream *pStringStream)
: device(pStringStream), document(&device)
{
}
private:
PoDoFo::PdfOutputDevice device;
PoDoFo::PdfStreamedDocument document;
PoDoFo::PdfPainter painter;
};
Код, который использует этот класс, не должен видеть все детали, которые входят в использование библиотеки, но способ, которым я их скрываю, делает его зависимым от использования членов для инициализации других членов, прежде чем он достигнет фактического блока кода конструктора, где он имеет действительный указатель
Он работает в скелете юнит-тестирования, поэтому мой вопрос в основном таков: «Это нормально, портативно и безопасно?»
Элементы инициализируются в порядке их объявления сверху вниз
PoDoFo::PdfOutputDevice device;
PoDoFo::PdfStreamedDocument document;
PoDoFo::PdfPainter painter;
так что это безопасно для использования device
инициализировать document
,
Вид. Правила состоят в том, что переменные-члены инициализируются в порядке, в котором они объявлены в объявлении класса.
В вашем случае это нормально, так как device
объявлен ранее document
,
Однако в следующем случае мы имеем неопределенное поведение, несмотря на порядок списка инициализатора.
class A {
public:
A(int i) : b(i), a(b) { }
private:
int a;
int b;
}