Подтвердить что ты не робот

Могу ли я использовать идентичные имена для полей и параметров конструктора?


class C {
  T a;
public:
  C(T a): a(a) {;}
};

Является ли это законным?

4b9b3361

Ответ 1

Да, это законно и работает на всех платформах. Он правильно инициализирует вашу переменную-член 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 перед его инициализацией в списке инициализации.

Ответ 2

Одна из вещей, которая может привести к путанице в отношении этой темы, - это то, как переменные задают приоритет компилятором. Например, если один из аргументов конструктора имеет то же имя, что и член класса, вы можете записать следующее в списке инициализации:

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"
{
}

Ответ 3

если формальный параметр и член названы одинаковыми, тогда остерегайтесь использования этого указателя внутри конструктора для использования переменной-члена

class C {
  T a;
public:
  C(T a): a(a) {
this->a.sort ;//correct
a.sort();//will not affect the actual member variable
}
};

Ответ 4

Право: да, как объяснил Брайан, компилятор знает, что имя, ожидаемое в списке инициализаторов, должно быть членом (или базовым классом), а не чем-либо еще.

Хороший стиль: скорее всего, нет - для многих программистов (включая вас, кажется) результат не очевиден. Использование другого имени для параметра будет держать код законным и сделать его хорошим стилем в то же время.

Я бы предпочел написать некоторые из них:

class C {
  T a_;
public:
  C(T a): a_(a) {}
};


class C {
 T a;
 public:
 C(T value): a(value) {}
};

Ответ 5

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

Кроме того, в нетривиальном конструкторе вы делаете ошибку, забывая поставить this- > перед именем члена.

Java даже не допускает этого. Это плохая практика, и ее следует избегать.