C ++ Странность списка инициализации конструктора - PullRequest
11 голосов
/ 19 марта 2010

Я всегда был хорошим мальчиком, когда писал свои классы, добавляя все переменные-члены к 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

Ответы [ 5 ]

26 голосов
/ 19 марта 2010

Да, это действительно. Имена в списке инициализатора члена ищутся в контексте класса конструктора, поэтому int1 находит имя переменной члена.

Выражение инициализатора ищется в контексте самого конструктора, поэтому int1 находит параметр, который маскирует переменные-члены.

15 голосов
/ 19 марта 2010

То, что вы сделали, это стандартный C ++. Только переменные-члены или базовые классы могут быть инициализированы в списке инициализации, поэтому переменная вне парантеза однозначна. В круглых скобках применяются типичные правила области видимости, а элементы затеняются именами параметров.

2 голосов
/ 19 марта 2010

Это совершенно нормальное поведение. Как правильно заметил AAT, двусмысленности нет. Переменные, инициализированные списком, должны быть членами класса. Это стандарт и работает для всех совместимых компиляторов.

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

0 голосов
/ 19 марта 2010

То, что вы сделали, это нормально. Реализация такого типа позволяет вам даже не использовать указатель this (в данном случае).

0 голосов
/ 19 марта 2010

Я думаю, это работает, потому что вы использовали int1 в списке инициализаторов, и единственные вещи, которые вы можете инициализировать, - это переменные-члены => фактически, однозначно, какая переменная была инициализирована.

Все ли компиляторы C ++ будут этим прощением - это другой вопрос!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...