2010-05-04 2 views
2

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

class Foo 
{ 
public: 
    Foo(int i) : m_i(i) {} //works with no problem 

    int getInt() {return m_i;} 

    ~Foo() {} 
private: 
    int m_i; 
}; 

class Bar 
{ 
public: 
    Bar() : 
    m_foo(5),   //this is ok 
    m_myInt(m_foo.getInt()) //runtime error, seg 11 
    {} 

    ~Bar() {} 
private: 
     Foo m_foo; 
    int m_myInt; 


}; 

При попытке вызова функции-члены членов инициализируется выше список инициализатора, я получаю seg. Кажется, я помню, что это известная проблема (или, возможно, так или иначе по дизайну), но я никогда не видел ее хорошо описанной. Приложенный пример наложен на простые старые типы данных, но замените Bar::m_myInt на другой объект, в котором отсутствует конструктор по умолчанию (пустой), и проблема более реальна. Может ли кто-нибудь просветить меня?

+1

Typo: '~ Foo {}' for '~ Foo() {}'? –

+0

Это компилируется и запускается с использованием GCC 3.4.3 без ошибок в Cygwin. Какой компилятор вы используете? – andand

ответ

9

Порядок инициализации не зависит от порядка элементов в списке инициализации. Фактический порядок - порядок членов в определении класса. То есть в вашем примере m_foo будет инициализирован до m_myInt не из-за списка инициализации, а потому, что элемент появляется первым в классе.

Конкретный пример, который вы опубликовали, должен компилироваться и запускаться без проблем.

+2

В случае gcc вы можете передать его '-Wreorder', и он будет предупреждать, если вы испортите –

+0

Yup это то, что кусает меня! Я включил его в голову. Я думал, что порядок инициализации основан на порядке определения порядка сортировки списка инициализаторов. Спасибо, что поняли! – awm129

3

Элементы данных инициализируются в порядке, указанном в объявлении класса (заказ под номером private: в вашем примере). Порядок, указанный в списке инициализаторов, не имеет запрета на порядок строительства.

Таким образом, в вашем примере, переупорядочивая элементы данных, как это может привести к непредсказуемому поведению:

private: 
    int m_myInt; 
    Foo m_foo; 

Возможно ли, что порядок элементов данных была актуальна иначе, чем вы показали?

+0

Да, в моем примере должны быть закрытые члены Bar, чтобы полностью проиллюстрировать проблему. Спасибо за вашу помощь! – awm129

Смежные вопросы