Использование параметра и переменной-члена в конструкторе

Время от времени при написании конструктора класса я спрашиваю себя, должен ли я использовать инициализированную переменную-член или параметр конструктора. Вот два примера, чтобы проиллюстрировать, что я имею в виду:

Параметр конструктора

class Foo {
public:
Foo(int speed) :
mSpeed(speed),
mEntity(speed)
{ }

private:
int mSpeed;
Entity mEntity;
}

Переменная члена

class Foo {
public:
Foo(int speed) :
mSpeed(speed),
mEntity(mSpeed)
{ }

private:
int mSpeed;
Entity mEntity;
}

Дальше больше та же проблема возникает при использовании переменных в теле конструктора.

Параметр конструктора

class Foo {
public:
Foo(int speed) :
mSpeed(speed)
{
mMonster.setSpeed(speed);
}

private:
int mSpeed;
Monster mMonster;
}

Переменная члена

class Foo {
public:
Foo(int speed) :
mSpeed(speed)
{
mMonster.setSpeed(mSpeed);
}

private:
int mSpeed;
Monster mMonster;
}

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

Если вам нужен конкретный вопрос для работы: каким образом получается хороший и последовательный дизайн кода и имеет ли одно (не) преимущество над другим?

Редактировать: Не забудьте вторую часть вопроса. Как насчет переменных в теле конструктора?

7

Решение

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

Действительно, в этом примере:

class Foo {
private:
int mEntity;
int mSpeed;
public:
Foo(int speed) :
mSpeed(speed),
mEntity(mSpeed)
{ }
}

инициализация mEntity произойдет до инициализации mSpeed ​​(потому что он был объявлен ранее). Поэтому вы инициализируете mEntity с неинициализированной скоростью mSpeed.

А внутри самого тела конструктора я бы также использовал параметр конструктора, потому что он немного проще при отладке, чтобы увидеть, что вы используете скорость инициализировать mMonster и не mSpeed который сам по себе инициализируется скорость. Конечно, это минималистичные накладные расходы, но, поскольку мы можем легко избежать этого, я думаю, что лучше сделать это таким образом.

2

Другие решения

Я бы использовал Constructor Parameter, потому что при использовании этого инициализатора порядок выполнения этих инициализаторов определяется порядком, в котором были объявлены элементы, а не порядком, в котором они перечислены. так что будьте осторожны здесь.

3

Я бы использовал параметр конструктора. Зачем? Из-за этого вопроса. Параметр construtor понятен и читабелен, вам не нужно много знать о C ++, чтобы знать, что происходит. Использование члена подвержено ошибкам, если вы недостаточно знаете о C ++ и вводите в заблуждение других людей в вашей команде, которые не имеют вашего уровня знаний, даже если вы делаете это правильно.

Если сомневаетесь, сделайте это просто.

0

Вы обязательно должны использовать параметры конструктора. Как уже упоминалось, переменные-члены будут инициализированы в том порядке, в котором они были объявлены в заголовочном файле, а не в том порядке, в котором они появляются в списке инициализации.

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

0

Я предпочитаю использовать переменную-член для случая, когда параметр должен быть ограничен:

class Foo {
public:
Foo(int speed) :
mSpeed((speed < 0 ? 0 : speed)),
mEntity(mSpeed)
{ }
}

Таким образом, если параметр недействителен, он не используется, чтобы последующие члены также были недействительными.

В противном случае я придерживаюсь переменной параметра.

0

Я бы также использовал параметр конструктора.
Смотрите простой пример:

// foo.h

class Foo
{
std::unique_ptr<int[]> mBuff;
int mSize;
public:
explicit    Foo(int size);
// other methods...
};

// foo.c
Foo::Foo(int size)
: mSize(size)
, mBuff( std::make_unique<int[]>(size) ) // here using mSize is wrong,
// because, mSize is not initialized yet.
// here mSize initialized after mBuff, because it's declarated after mBuff member.
{}

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

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector