2016-09-06 4 views
2

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

Например, используя типичный конструктор присваивания, я бы что-то вроде этого:

class MyObj 
{ 
    private: 
     int one_; 
     int two_; 
     DiffObj diffObj_; 

    ... // other stuff 
} 

MyObj::MyObj(int a, int b, std::string type, std::vector<double> params) 
{ 
    one_ = a; 
    two_ = b; 
    if (verifyType(type, params)) 
    { 
     diffObj_ = createDiffObj(params); 
    } 
} 

с этой ситуацией, хотя, как я мог бы использовать список инициализации? Я думал, возможно, инициализируя некоторые параметры в конструкторе и используя отдельный вызов для инициализации остальных, но я не совсем уверен, что это кошерный.

MyObj::MyObj(int a, int b) : 
    one_(a), 
    two_(b) 
    {} 

MyObj::initializeDiffObj(std::string type, std::vector<double> params) 
{ 
    if (verifyType(type, params)) 
    { 
     diffObj_ = createDiffObj(params); 
    } 
} 
+0

Не обязательно указывать инициализацию для чего-либо. Как вы говорите, если вы не укажете, то члены будут построены по умолчанию, что во многих случаях просто отлично. Вы можете инициализировать некоторые элементы в списке инициализаторов, а остальные - в теле конструктора, вызывая функцию-член во втором блоке кода, если хотите. – Chris

+1

«Я знаю, что ...» всегда, кажется, следует ложное утверждение –

+0

@ M.M: «Я думал, что ...», возможно, было лучше сказано – marcman

ответ

2

Нечто подобное было бы вполне разумным. Вы можете иметь список инициализаторов и выполнять некоторую работу внутри своего конструктора, вам не нужно его выбирать.

class MyClass { 
    public: 
     MyClass(int a, SomeStruct b) 
      : _a(a) { 
       if (isValid(b)) { 
        // Initialize _b 
        _b = createWeirdThingFromSomeStruct(b); 
       } 
     } 
    private: 
     int _a; 
     WeirdThing _b; 
}; 
+1

Это именно то, о чем я не знал. Благодаря! – marcman

1

Если конструктор не предоставляет инициализатор для члена, этот член по умолчанию инициализируется. Для int это означает отсутствие инициализации вообще; для типов классов с предоставленным пользователем конструктором это означает вызов этого конструктора.

В идеале список конструкторов-инициализаторов должен выполнять всю инициализацию членов. Вот один из способов сделать это для вашей ситуации:

MyObj::MyObj(int a, int b, std::string type, std::vector<double> params) 
    : one_(a), two_(b), 
     diffobj(verifyType(type, params), std::move(params)) 
{ 
} 

это (аb) использует оператор запятой вписываться в вызове verifyType во время инициализации diffobj. Функция verifyType должна выдавать исключение, если проверка не выполняется.

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