Я всегда был хорошим мальчиком при записи моих классов, добавлении префикса всех членских переменных m_:
class Test {
int m_int1;
int m_int2;
public:
Test(int int1, int int2) : m_int1(int1), m_int2(int2) {}
};
int main() {
Test t(10, 20); // Just an example
}
Однако недавно я забыл делать это и закончил тем, что писал:
class Test {
int int1;
int int2;
public:
// Very questionable, but of course I meant to assign ::int1 to this->int1!
Test(int int1, int int2) : int1(int1), int2(int2) {}
};
Хотите верьте, хотите нет, код, скомпилированный без ошибок/предупреждений и присвоений, произошел правильно! Это было только при выполнении последней проверки перед регистрацией в моем коде, когда я понял то, что я сделал.
Мой вопрос: почему мой код компилировал? Похож на что-то, что позволило в стандарте C++, или это - просто случай компилятора, являющегося умным? В случае, если Вы задавались вопросом, я использовал Visual Studio 2008
Да, это корректно. Имена в списке инициализаторов членов ищутся в контексте класса конструктора, поэтому int1
находит имя переменной-члена.
Выражение инициализатора ищется в контексте самого конструктора, поэтому int1
находит параметр, который маскирует переменные-члены.
Я полагаю, что это работает, потому что вы использовали int1 в списке инициализаторов, и единственное, что вы можете инициализировать, это переменные-члены => это было на самом деле однозначно, какая переменная инициализировалась.
Другой вопрос, будут ли все компиляторы C ++ такими снисходительными!
То, что вы сделали, нормально. Такая реализация позволяет избежать даже использования указателя this (в данном случае).
Это совершенно нормальное поведение. Как справедливо заметил AAT, здесь нет никакой двусмысленности. Переменные, инициализируемые списком, должны быть членами класса. Это стандарт и работает во всех совместимых компиляторах.
Единственное, что нужно помнить при использовании подобного списка, это то, что человеку, который не понимает такого рода код, возможно, придется его поддерживать. Нет ничего плохого в написании подобного кода инициализации, если вы знаете, что делаете.
Вы сделали стандартный C ++. Только переменные-члены или базовые классы могут быть инициализированы в списке инициализации, поэтому переменная вне парантезы однозначна. В круглых скобках применяются типичные правила области действия, а имена параметров затеняют элементы.