27 сент. 2015 г., 03:51 отMogsdadSmacL

Чрезмерное использование `this` в C ++ [дубликат]

На этот вопрос уже есть ответ:

Когда я должен явно использовать указатель `this`? 13 ответов

Я имею дело с большой кодовой базой, которая использует следующую конструкцию

<code>class MyClass
{
public:
  void f(int x);
private:
  int x;
};


void MyClass::f(int x)
{
'
'
  this->x = x;
'
'
}
</code>

Лично я всегда использовал и поэтому предпочел бы форму

<code>class MyClass
{
public:
  void f(int x);
private:
  int _x;
};


void MyClass::f(int x)
{
'
'
  _x = x;
'
'
}
</code>

Причины, по которым я предпочитаю последнее, заключаются в том, что он более лаконичен (меньше кода = меньше потенциальных ошибок) и что мне не нравится иметь в области действия одновременно несколько переменных с одним и тем же именем, где я могу избежать этого. Тем не менее, в последнее время я все чаще вижу бывшее использование. Есть ли какой-то плюс ко второму подходу, о котором я не знаю? (например, влияние на время компиляции, использование с шаблонным кодом и т. д.). Являются ли преимущества одного из подходов достаточно значительными для рефакторинга другого? Причина, по которой я спрашиваю, заключается в том, что хотя мне не нравится второй подход, представленный в коде, объем усилий и связанный с этим риск появления дальнейших ошибок не вполне заслуживают рефакторинга.

Ответы на вопрос(15)

29 июн. 2009 г., 10:28 отmarkh44

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

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

29 июн. 2009 г., 08:42 отJem

oft C #. Он обеспечивает хорошую ясность кода и призван стать стандартом использования m_ или _ или чего-либо еще в переменных-членах.

Честно говоря, в любом случае, мне действительно не нравится подчеркивание в именах, я использовал префикс всех своих членов с помощью одной буквы "m".

29 июн. 2009 г., 08:50 отPete Kirkham

В C ++ более нормально инициализировать элементы при построении с использованием инициализатора.

Для этого вы должны использовать имя, отличное от имени переменной-члена.

Так что, хотя я бы использовалFoo(int x) { this.x = x; } в Java я бы не стал в C ++.

Настоящим запахом может быть отсутствие использования инициализаторов и методов, которые ничего не делают, кроме изменения переменных-членов, а не использованияthis -> x сам

Кто-нибудь знает, почему в каждом магазине C ++ есть универсальная практика использовать разные имена для аргументов конструктора для переменных-членов при использовании с инициализаторами? были ли какие-то компиляторы C ++, которые его не поддерживали?

29 июн. 2009 г., 08:39 отAlexey Malistov

class MyClass{
public:  
  int x;  
  void f(int xval);
};
//
void MyClass::f(int xval){  
  x = xval;
}
29 июн. 2009 г., 08:47 отCommunity

Нил сказал, видимость поля - единственный кодовый элемент здесь.

В C ++ есть различные статьи относительно соглашений об именах:

Соглашение об именах для публичных и приватных переменных? Собственное соглашение об именовании методов c ++ использование пространства имен и правила именования

так далее

29 июн. 2009 г., 08:39 отDimitri C.

M_ соглашение об именовании. Хотя мне вообще не нравится «венгерская нотация», очень полезно очень четко видеть, работаю ли я с данными учеников. Кроме того, я обнаружил, что использование 2 одинаковых имен переменных в одной и той же области слишком подвержено ошибкам.

29 июн. 2009 г., 08:38 от1800 INFORMATION

оглашение, в котором есть очевидное различие между переменными-членами и локальными переменными. Что произойдет, если вы уйдете сthis?

29 июн. 2009 г., 08:43 отCommunity

Избегайте подчеркивания: _x все в порядке, пока кто-нибудь не выберет _MyField, которое является зарезервированным именем. Начальное подчеркивание, за которым следует заглавная буква, не допускается в качестве имени переменной. Видеть: Каковы правила использования подчеркивания в идентификаторе C ++? Сделайте атрибут личным или защищенным: изменение безопасно, если оно компилируется, и вы убедитесь, что ваш установщик будет использован. История this-> используется, например, в шаблонном коде, чтобы сделать имя поля зависимым от вашего типа (может решить некоторые проблемы с поиском).

Небольшой пример разрешения имен, которые исправляются с помощью явного this-> (протестировано с g ++ 3.4.3):

#include <iostream>
#include <ostream>

class A
{
public:
  int g_;
  A() : g_(1) {}
  const char* f() { return __FUNCTION__; }
};

const char* f() { return __FUNCTION__; }
int g_ = -1;

template < typename Base >
struct Derived : public Base
{
  void print_conflicts()
  {
    std::cout << f() << std::endl; // Calls ::f()
    std::cout << this->f() << std::endl; // Calls A::f()
    std::cout << g_ << std::endl; // Prints global g_
    std::cout << this->g_ << std::endl; // Prints A::g_
  }
};

int main(int argc, char* argv[])
{
   Derived< A >().print_conflicts();
   return EXIT_SUCCESS;
}
29 июн. 2009 г., 08:49 отMarco van de Voort

потому что в их IDE появится список идентификаторов текущего класса.

Я знаю, что в BCB.

Я думаю, что пример, который вы привели с конфликтом имен, является исключением. Однако в Delphi правила стиля используют префикс (обычно «a») для параметров, чтобы избежать именно этого.

30 июн. 2009 г., 07:00 от

что бороться с существующим соглашением о кодировании - это то, что вы не должны делать. Как говорит Саттер / Александреску в своей книге «Соглашения по кодированию на C ++»: не надо прибегать к мелочам. Любой может прочитать одно или другое, независимо от того, есть ли ведущие 'this->' или '_' или что-то еще.

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

Если, в конце концов, вы обнаружите, что есть веская причина для его изменения, не делайте этого вручную. В лучшем случае ваша IDE поддерживает такие «рефакторинги». В противном случае напишите скрипт для его изменения. Поиск и замена должны быть последним вариантом. В любом случае у вас должна быть резервная копия (контроль исходного кода) и какое-то автоматическое средство тестирования. Иначе тебе не понравится.

29 июн. 2009 г., 08:42 отDario Solera

эт имеет тенденцию добавлять беспорядок в код, поэтому я склонен использовать разные имена переменных (в зависимости от соглашения это может быть подчеркивание, M_, без разницы)

29 июн. 2015 г., 11:01 отThomas Fauskanger

чтобы указать членов класса локальных переменных. Таким образом, IMO, ни префиксы, ни 'this->' не требуются для удобства чтения.

29 июн. 2009 г., 08:51 отDan Brown
class MyClass
{
public:
  int m_x;
  void f(int p_x);
};


void MyClass::f(int p_x)
{
  m_x = p_x;
}

сти. m_ для члена, p_ для параметра (некоторые вместо него используют a_ для аргумента), g_ для глобального и иногда l_ для локального, если это помогает удобочитаемости.

Если у вас есть две переменные, которые заслуживают одного и того же имени, это может помочь, и вам не придется придумывать случайные изменения в значении, чтобы избежать переопределения. Или, что еще хуже, страшные «х2, х3, х4 и т. Д.» ...

29 июн. 2009 г., 14:03 отeeeeaaii

потому что это атавистично. Если вы программируете на старом добром C (помните C?), И вы хотите имитировать некоторые характеристики ООП, вы создаете структуру с несколькими членами (они аналогичны свойствам вашего объекта), и вы создаете набор функций, которые все принимают указатель на эту структуру в качестве первого аргумента (они аналогичны методам этого объекта).

(Я думаю, что этот синтаксис typedef правильный, но это было давно ...)

typedef struct _myclass
{
   int _x;
} MyClass;

void f(MyClass this, int x)
{
   this->_x = x;
}

Фактически, я считаю, что старые компиляторы C ++ на самом деле компилируют ваш код в приведенную выше форму, а затем просто передают его компилятору C. Другими словами - C ++ в некоторой степени был просто синтаксическим сахаром. Поэтому я не уверен, почему кто-то захочет программировать на C ++ и вернуться к явному использованию «this» в коде - возможно, это «синтаксический Nutrisweet»

29 июн. 2009 г., 09:01 отSecko

вы можете попробовать использовать что-то вроде следующего.

class tea
{
public:
    int cup;
    int spoon;
    tea(int cups, int spoons);
};

ил

class tea
{
public:
    int cup;
    int spoon;
    tea(int drink, int sugar);
};

Думаю, у тебя есть идея. Это в основном имена переменных, но «одинаковые» в логическом смысле. Я надеюсь, что это помогает

ВАШ ОТВЕТ НА ВОПРОС