Список инициализации C++ с выражениями
Я только что узнал, что мне следует использовать список инициализации вместо назначений в моих конструкторах C++. Вот мой пример.
**Пример Задания: * *
Class Graph {
private:
int count;
int spacing;
int width;
public:
Graph(int _count, int _spacing, int _chart_width) {
count = _count;
spacing = _spacing;
width = (_chart_width - ((_count - 1) * _spacing)) / _count;
}
};
**Пример Списка Инициализации: * *
Class Graph {
private:
int count;
int spacing;
int width;
public:
Graph(int _count, int _spacing, int _chart_width) : count(_count), spacing(_spacing), width((_chart_width - ((_count - 1) * _spacing)) / _count) {}
};
Как вы можете видеть, это выглядит действительно уродливо.
Мой вопрос:
- является ли это способом написания конструктора списка инициализации с выражениями?
- есть ли лучший синтаксис? Что делать, если выражение действительно длинное и делает синтаксис списка инициализации полностью нечитаем?
- Должен ли я написать метод
getWidth()
, который вычисляетwidth
и очищает конструктор? Что-то вродеwidth(getWidth(_chart_width))
.
Синтаксис списка инициализации - указывает, что, например,
count(_count)
является функцией, которая принимает_count
в качестве входного аргумента. Не путаю ли я синтаксис списка инициализации с синтаксисом функций? илиcount()
действительно функция? Это очень запутанно. - Если способ, которым я пишу список инициализации, правильный, не могли бы вы предложить лучший способ форматирования кода для удобства чтения? Я думаю, Мне хотелось бы знать, какой синтаксис является наиболее распространенным для длинных списков инициализации.
3 ответа:
Разные проекты (и люди) имеют разные стандарты кодирования и вкусы, но лично я нахожу это форматирование очень читаемым:
Class Graph { private: int count; int spacing; int width; public: Graph(int _count, int _spacing, int _chart_width) : count(_count), spacing(_spacing), width((_chart_width - ((_count - 1) * _spacing)) / _count) {} };
И нет, это не обязательно вызовы функций. Но они могут быть... Лучше всего думать об этом следующим образом: если переменные, которые вы инициализируете, являются экземплярами класса, то вы вызываете конструктор, чтобы инициализировать их. Если вы смотрите на это таким образом, синтаксис имеет смысл.
И я бы рекомендовал вспомогательную функцию (как частный и, возможно, статический метод класса) для вычисления ширины.
Можно ли таким образом написать конструктор списка инициализации с выражениями?
Да, это так (хотя вы могли бы отформатировать его, чтобы он был более читаемым).
Есть ли лучший синтаксис? Что делать, если выражение действительно длинное и делает синтаксис списка инициализации полностью нечитаемым?
Насколько мне известно, нет. Если список становится слишком длинным, его можно отформатировать в строки. Если инициализация вашего параметра очень длинная, сложная и едва читаемая (то есть занимает 2-3 строки и полон логики) я бы рекомендовал переместить его в тело конструктора. Как правило, для этого используется список инициализаторов: initialize. Вы не должны делать блоки логики в параметрах вашего списка по нескольким причинам:
Если для вашего параметра требуется небольшое математическое уравнение, это нормально, но все, что больше этого, может потребовать своей собственной функции. Это также может быть сделано в конструкторе объекта, где вы можете использовать переменные имен, чтобы представляйте, что происходит.
Общее правило "чистого кода" - не пытаться быть умным. Если что-то не читается, вы должны приложить активные усилия, чтобы сделать это понятным для ваших коллег.
Смотрите ответ на ваш следующий вопрос.
Должен ли я написать метод getWidth (), который вычисляет ширину и очищает конструктор? Что-то вроде width(getWidth(_chart_width)).
- вполне допустимо использовать a вызов функции в параметрах списка инициализаторов. Я бы даже посоветовал вам сделать это ради удобства чтения. В конце концов, одна из главных функций списка инициализаторов-избавить конструктор от строк "x = _x", которые могли бы заполнить его, и освободить место для функций, которые не просто присваивают значения.
Синтаксис списка инициализации указывает, что, например, count (_count) - это функция, которая принимает _count в качестве входного аргумента. Я что-то путаю? Синтаксис списка инициализации с синтаксисом функции? или count() действительно функция? Это очень запутанно.В принципе, C++ создает неявную функцию для присвоения передаваемых параметров соответствующей переменной. Думайте об этом, как о C++, создающем кучу невидимых функций, которые выглядят следующим образом:
aType setVarName(aType aParam) { varName = aParam; }
Если я правильно пишу список инициализации, не могли бы вы предложить лучший способ форматирования кода для удобства чтения? Наверное, мне хотелось бы знать. каков наиболее распространенный синтаксис для длинных списков инициализации.
Список инициализаторов должен находиться в том же месте, где вы определяете свой конструктор. В приведенном примере конструктор пуст, и поэтому вы решили определить его в заголовочном файле, так что вы можете определить список и там. Я знаю, что это не относится к вашей ситуации, но всегда полезно иметь в виду, что если у вашего конструктора был контент, вы должны определить список непосредственно над блоком конструктора в твой ".cpp " файл как таковой:
Меня учили, что вы должны отделять каждый параметр новой строкой, но, как сказал rain city: "разные проекты (и люди) имеют разные стандарты кодирования и вкусы". На самом деле, я бы не советовал писать все это в одной строке, так как это сильно затрудняет его читаемость, если он становится большим. Как правило, вы хотите избежать линий, которые потребовали бы от пользователей "портретного монитора" прокрутки по горизонтали.Graph(int _count, int _spacing, int _chart_width) : count(_count), spacing(_spacing), width((_chart_width - ((_count - 1) * _spacing)) / _count) { ... [your constructor's code here] ... }
Правка: I заметил, что вы сказали, что у вас есть фон в java в другом комментарии, и задавались вопросом о логике объекта int vs. Хотя я не уверен, что Java делает это, C++ делает много неявных определений функций, где он будет "молча" генерировать функции для выполнения некоторого общего поведения. Например, объекты могут иметь неявный конструктор копирования, который позволяет создать экземпляр объекта, передав ему другой объект того же типа. Однако в случае списка инициализаторов, это просто неявные функции, которые присваивают значения переменным. Я бы порекомендовал прочитать о различных случаях неявных функций в C++, чтобы разобраться в этом.
Мой вопрос:
- Можно ли таким образом написать конструктор списка инициализации с выражениями?
Да
- Есть ли лучший синтаксис? Что делать, если выражение действительно длинное и делает синтаксис списка инициализации полностью нечитаемым?
Используйте несколько строк и отступы, когда строки становятся длинными.
- должен ли я написать метод getWidth (), который вычисляет ширину и очищает конструктор? Что-то вроде width (getWidth (_chart_width)).
Да, вы можете сделать это, но это не может быть метод экземпляра того же класса, так как у вас еще нет "этого".
Синтаксис списка инициализации указывает, что, например, count (_count) - это функция, которая принимает _count в качестве входного аргумента. Не путаю ли я синтаксис списка инициализации с синтаксисом функций? или count() действительно функция? Это очень запутанно.
Синтаксис тот же. Именно размещение в коде является тем, что определяет его как инициализацию, а не вызов функции (после символа':', следующего за сигнатурой конструктора). Нет, count-это не функция, это просто способ указания для x(y), чтобы инициализировать x с y. в C++ один и тот же синтаксис может использоваться для разных вещей, они различаются контекстом вокруг них. Вы обнаружите, что синтаксис x(y) используется для других вещей в C++ (макросы-это одно, приведения-другое, а инициализация суперкласса-другое).
Просто используйте более одной строки. Новые строки можно использовать везде, где есть пробелы. Когда вы использовали новые строки, использовали дополнительные отступы. Вы можете использовать немного творчества, или вы можете обратиться к документам стандартов кодирования для идей. Это хорошо:
- Если способ, которым я пишу список инициализации, является правильным, не могли бы вы предложить лучший способ форматирования кода для удобства чтения? Я думаю, Мне хотелось бы знать, какой синтаксис является наиболее распространенным для длинных списков инициализации.
Graph(int _count, int _spacing, int _chart_width) : count(_count), spacing(_spacing), width((_chart_width - (_count - 1) * _spacing) / _count) {}
Или если есть много параметров, вы можете сделать:
Graph(int _count, int _spacing, int _chart_width) : count(_count), spacing(_spacing), width((_chart_width - (_count - 1) * _spacing) / _count) {}