У меня возникла проблема с пониманием синтаксиса. Увидел вот такой конструктор:
foo(char *msg) : msg(msg) { ..... }
Что значит двоеточие после аргумента в первых скобках?
Область кода за двоеточием и до начала тела конструктора называется инициализатором конструктора.
Используется как для инициализации членов класса, так и для вызова конструктора базового/базовых классов, т.е. по сути, инициализации базовой составляющей. Так же здесь может быть вызов другого конструктора текущего класса (делегирование конструкторов, начиная с c++11).
Без инициализатора конструктора не обойтись, если в классе присутствует член ссылочного типа или константа, или член класса, у которого нет конструктора по умолчанию:
struct S {
S(int) {} // Конструктор с параметром. Не является конструктором по умолчанию.
};
class B {
public:
B(int i) : i(i), r(i), s(i) {
// this->i = i; // Ошибка. Нельзя присваивать константе.
// r = i; // Ошибка. Не является инициализацией ссылки.
// s = S(i); // Ошибка. `s` должен быть создан в инициализаторе конструктора.
}
private:
const int i;
int& r;
S s;
};
т.к. код, начинающийся за фигурной скобкой будет приводить уже не к инициализации члена, а к присваиванию ему значения, чего нельзя сделать для упомянутых ранее ссылок или констант.
Дополнительно стоит заметить (как было упомянуто в комментарии Monah Tuk), что если член-класса не инициализирован явно в инициализаторе конструктора и при этом ему присваивается значение в теле конструктора, то он сначала будет инициализирован конструктором по умолчанию (или инициализацией в определении класса (c++11)):
class D {
int i = 42; // Инициализация члена в определении класса
};
После чего выполнится присваивание в теле конструктора. Для сложных классов это может приводить к дополнительным расходам.
Т.о. инициализацию членов стоит производить либо в определении класса, либо в инициализаторе конструктора. Не стоит пытаться сделать нечто подобное непосредственно внутри тела конструктора.
class foo
{
public:
foo(int a) : a(a) {}
// эквивалентно foo(int a) { this->a = a; }
private:
int a;
}
Это вообще-то база синтаксиса определения конструкторов в плюсах.
Еще может быть:
class foo : public bar
{
public:
foo(int a) : bar(a) { ... }
}
В этом случае, после двоеточия вызывается конструктор базового класса. ЕМНИП (могу ошибаться), в случае базового класса это единственный верный способ его вызова, т.е. написать вот так:
foo(int a) { bar(a); ... }
будет неверно.
П.С. Думаю, ответ alexolut более полон, чем мой.
Это использование списка инициализации (Initialization List) для конструктора. Эта запись эквивалентна строчке кода в начале конструктора
this->msg = msg;
Оборудование для ресторана: новинки профессиональной кухонной техники
Частный дом престарелых в Киеве: комфорт, забота и профессиональный уход
Здравствуйте, работай со средой разработки QT, написав некоторый базовый функционал приложения, решил собрать ее и перенести на другой компьютер,...
Нужно добавить строку и программа падает при попытке выделить ее, то есть тут // Выделяем добавленную запись; uitable->setCurrentCell(insertPos,...
Всем приветЯ изучаю классы и перегрузки операций в С++
Мне нужно отследить нажатие клавиши F4 на OSX и выполнить действие, пишу на С++, желательно код обьяснить и без зависимостей