Использование членов объекта до его создания

У меня есть следующий простой код:

#include <iostream>
#include <vector>

template <class Derived>
struct Base
{
    Base()
    {
        static_cast<Derived*>(this)->foo(); 
    }

    std::vector<int> m_ints;
};

struct Derived : Base<Derived>
{
    Derived() : Base() 
    {
        std::cout << a;
    }

    void foo()
    {
        m_ints.push_back(37);
        a = 4;
    }

    int a;
};

int main() 
{
    Derived d;
    return 0;
}

Я знаю о порядке вызова конструкторов при создании объекта. Конструктор вызывается из "самого базового -> вниз". Поэтому в конструкторе Base производный объект не полностью построен.

1) Безопасно ли звонить Derived::foo в Base конструктор, когда Derived::foo не трогай Derived объект? Я имею в виду, когда нет такой строки, как a = 4, просто касаясь Base объект.

2) Если я запускаю опубликованный код, он действительно работает, хотя я касаюсь a который не должен существовать в то время. Это гарантия на работу? (Я тестировал его на VS2013, VS2010 и GCC 4.8.1 на Ideone)

1 ответ

Это будет работать в этом конкретном случае, но я бы посоветовал не делать этого. Незаметные изменения в коде могут внезапно нарушить логику (например, кто-то делает метод foo виртуальным, кто-то инициализирует элемент данных a в конструкторе или Derived, ...).

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

И когда элемент данных a должен быть инициализирован, инициализируйте его в конструкторе Derived, а не где-нибудь еще.

РЕДАКТИРОВАТЬ: В C++11, если класс Derived хочет внедрить код в конструктор Base, он может передавать лямбда-выражения в Base. Затем Base просто выполняет лямбду в своем конструкторе.

Другие вопросы по тегам