Foo(int num): bar(num)
Эта конструкция называется списком инициализаторов членов в C ++.
Проще говоря, она инициализирует ваш член
bar
значениемnum
.В чем разница между инициализацией и присваиванием внутри конструктора?
Инициализация члена:
Foo(int num): bar(num) {};
Назначение членов:
Foo(int num) { bar = num; }
Существует значительная разница между Инициализацией члена с использованием списка инициализаторов членов и присвоением ему значения внутри тела конструктора.
Когда вы инициализируете поля через список инициализаторов члена конструкторы будут вызываться один раз, и объект будет создан и инициализирован в одной операции.
Если вы используете присваивание , тогда поля будут сначала инициализированы конструкторами по умолчанию, а затем переназначены ( через оператор присваивания) с фактическими значениями.
Как вы видите, есть дополнительные накладные расходы на создание & amp; назначение в последнем, что может быть значительным для пользовательских классов.
Cost of Member Initialization = Object Construction Cost of Member Assignment = Object Construction + Assignment
Последнее фактически эквивалентно:
Foo(int num) : bar() {bar = num;}
Хотя первое эквивалентно простому:
Foo(int num): bar(num){}
Для встроенных (ваш пример кода) или членов класса POD практических накладных расходов нет.
Когда вам нужно использовать список инициализаторов Member?
У вас будет (довольно принудительно) использовать список инициализатора члена, если:
class MyClass
{
public:
//Reference member, has to be Initialized in Member Initializer List
int &i;
int b;
//Non static const member, must be Initialized in Member Initializer List
const int k;
//Constructor’s parameter name b is same as class data member
//Other way is to use this->b to refer to data member
MyClass(int a, int b, int c):i(a),b(b),k(c)
{
//Without Member Initializer
//this->b = b;
}
};
class MyClass2:public MyClass
{
public:
int p;
int q;
MyClass2(int x,int y,int z,int l,int m):MyClass(x,y,z),p(l),q(m)
{
}
};
int main()
{
int x = 10;
int y = 20;
int z = 30;
MyClass obj(x,y,z);
int l = 40;
int m = 50;
MyClass2 obj2(x,y,z,l,m);
return 0;
}
MyClass2
не имеет конструктора по умолчанию, поэтому он должен быть инициализирован через список инициализаторов членов. MyClass
не имеет конструктора по умолчанию, поэтому для инициализации его члену-члену нужно будет использовать список инициализаторов членов. Переменные класса-члена всегда инициализируются в том порядке, в котором они объявлены в классе.
Они не инициализируются в том порядке, в котором они указаны в Список членов Initalizer. Короче говоря, список инициализации Member не определяет порядок инициализации.
Учитывая вышеизложенное, всегда является хорошей практикой поддерживать тот же порядок членов для инициализации члена как порядок, в котором они объявлены в определении класса. Это связано с тем, что компиляторы не предупреждают, отличаются ли эти два порядка, но относительно новый пользователь может смутить список инициализаторов членов как порядок инициализации и записать код, зависящий от этого.
Привязка не знает, что MyTitle
изменилось. Распространенным способом информирования об изменениях является реализация INotifyPropertyChanged
; также взгляните на MVVM, который является очень распространенным способом реализации его через DataContext
.