Не инициализируется поле класса

Можно ли инициализировать поле списка инициализаций с использованием методов этого класса?

Пример, что я имею в виду

class A{
public:

    A(arg...) : a(foo(arg...){} //is used uninitialized

private:

    int a;

    int foo(arg...){
        //код
    }
}

Ответы (2 шт):

Автор решения: Andrey Tabakov

Можно если в методе foo не будут использоваться неинициализированные члены класса A. Члены класса инициализируются в порядке объявления в классе (а не в порядке перечисления в списке инициализации).

Простой случай, метод foo не использует члены класса, только аргумент:

class A {
 
   public:
       int a;
    
       A(int x) : a(foo(x)) {} 
   private:
       int foo(int x) { return 7 + x; } 
};

int main() {
    A variable = A(1);
    
    cout<<variable.a<<endl; // 8 - OK!
    
    return 0;
} 

Всё будет хорошо, если порядок объявления переменных будет указан верно. Т.е. вы используете метод foo, который вызывает только уже объявленные переменные. В этом примере сначала объявляется b, затем a. Инициализируем b затем мы инициализируем a через метод foo, который использует переменную b

class A {
       int b;
   public:
       int a;

       A(int x) : a(foo(x)), b(7) {}
   private:
       int foo(int x) { return b + x; } // b объявлено до a, она будет проинициализирована и код выполнится успешно
};

int main() {
    A variable = A(1);
    
    cout<<variable.a<<endl; // 8 - ОК!
    
    return 0;
} 

Меняем порядок объявления, теперь сначала объявляется a, затем b. Так как b не инициализирована, мы не знаем с чем сложится аргумент.

class A {
       
   public:
       int a;
       int b;

       A(int x) : b(7), a(foo(x)) {}
   private:
       int foo(int x) { return b + x; } // b не проинициализирована, так как она объявлена после int a, несмотря на порядок перечисления в списке инициализации
};

int main() {
    A variable = A(1);

    cout<<variable.a<<endl; // 1 или 8 или 834834 или что?

    return 0;
} 
→ Ссылка
Автор решения: αλεχολυτ

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

Всё, что нужно сделать, это добавить ключевое слово static:

static int foo(arg...) {
   // код, который в принципе не может иметь доступа к нестатическим членам класса
}

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

→ Ссылка