class C {
T a;
public:
C(T a): a(a) {;}
};
Является ли это законным?
class C {
T a;
public:
C(T a): a(a) {;}
};
Является ли это законным?
Да, это законно и работает на всех платформах. Он правильно инициализирует вашу переменную-член a, переданную в значение a.
Считается более чистым назвать их по-разному, хотя и не все. Я лично использую его много:)
Списки инициализации с тем же именем переменной работают, потому что синтаксис элемента инициализации в списке инициализации выглядит следующим образом:
< член > (< значение > )
Вы можете проверить, что я написал выше, создав простую программу, которая делает следующее: (он не будет компилироваться)
class A
{
A(int a)
: a(5)//<--- try to initialize a non member variable to 5
{
}
};
Вы получите компиляционную ошибку, например: A не имеет поля с именем 'a'.
На боковой ноте:
Одна из причин, по которой вам может не хотеть использовать одно и то же имя участника, что и имя параметра, состоит в том, что вы были бы более склонны к следующему:
class A
{
A(int myVarriable)
: myVariable(myVariable)//<--- Bug, there was a typo in the parameter name, myVariable will never be initialized properly
{
}
int myVariable;
};
На боковой ноте (2):
Одна из причин, по которой вы можете хотеть использовать одно и то же имя участника, что и имя параметра, состоит в том, что вы менее склонны к следующему:
class A
{
A(int myVariable_)
{
//<-- do something with _myVariable, oops _myVariable wasn't initialized yet
...
_myVariable = myVariable_;
}
int _myVariable;
};
Это также может произойти с большими списками инициализации, и вы используете _myVariable перед его инициализацией в списке инициализации.
Одна из вещей, которая может привести к путанице в отношении этой темы, - это то, как переменные задают приоритет компилятором. Например, если один из аргументов конструктора имеет то же имя, что и член класса, вы можете записать следующее в списке инициализации:
MyClass(int a) : a(a)
{
}
Но имеет ли вышеуказанный код тот же эффект, что и этот?
MyClass(int a)
{
a=a;
}
Ответ - нет. Всякий раз, когда вы вводите "a" внутри тела конструктора, компилятор сначала ищет локальный аргумент или конструктор, называемый "a" , и только если он не найдет его, он начнет искать элемент класса "a" , (а если нет, то он будет искать глобальную переменную, называемую "a" , кстати). В результате вышеуказанная позиция "a = a" присваивает значение, хранящееся в аргументе "a" , аргументу "a" , что делает его бесполезным.
Чтобы присвоить значение аргумента члену класса "a" , вам необходимо сообщить компилятору, что вы ссылаетесь на значение внутри экземпляра класса this:
MyClass(int a)
{
this->a=a;
}
Хорошо, но что, если вы сделали что-то вроде этого (обратите внимание, что нет аргумента под названием "a" ):
MyClass() : a(a)
{
}
Ну, в этом случае компилятор сначала будет искать аргумент под названием "a" , и когда он обнаружит, что он не был каким-либо, он бы присвоил значение члену класса "a" члену класса "a" , что эффективно ничего не сделает.
Наконец, вы должны знать, что вы можете назначать значения только членам класса в списке инициализации, поэтому следующее приведет к ошибке:
MyClass(int x) : x(100) // error: the class doesn't have a member called "x"
{
}
если формальный параметр и член названы одинаковыми, тогда остерегайтесь использования этого указателя внутри конструктора для использования переменной-члена
class C {
T a;
public:
C(T a): a(a) {
this->a.sort ;//correct
a.sort();//will not affect the actual member variable
}
};
Право: да, как объяснил Брайан, компилятор знает, что имя, ожидаемое в списке инициализаторов, должно быть членом (или базовым классом), а не чем-либо еще.
Хороший стиль: скорее всего, нет - для многих программистов (включая вас, кажется) результат не очевиден. Использование другого имени для параметра будет держать код законным и сделать его хорошим стилем в то же время.
Я бы предпочел написать некоторые из них:
class C {
T a_;
public:
C(T a): a_(a) {}
};
class C {
T a;
public:
C(T value): a(value) {}
};
Проблема с этой практикой, хотя она и может быть, заключается в том, что компиляторы будут рассматривать переменные, затененные при использовании -Wshadow, и это будет запутывать эти предупреждения в другом коде.
Кроме того, в нетривиальном конструкторе вы делаете ошибку, забывая поставить this- > перед именем члена.
Java даже не допускает этого. Это плохая практика, и ее следует избегать.