Google C++ Style Guide / Google C++ Style Guide: Classes
| Английский оригинал | Перевод на русский | |
|---|---|---|
Сожалеем, но текст оригинала доступен только зарегистрированным пользователям. |
Классы xmorph 16.03.13 в 09:25 |
|
|
Классы являются фундаментальной единицей кода в C++. Естественно, мы широко их используем. Данный раздел содержит список основных плюсов и минусов, о которых нужно помнить при написании класса. xmorph 16.03.13 в 09:05 |
+1 | |
|
Выполнение кода в конструкторах xmorph 16.03.13 в 09:07 |
||
|
Избегайте комплексной инициализации в конструкторах (в частности, инициализации способной закончиться ошибкой либо требующей вызова виртуального метода). xmorph 16.03.13 в 09:11 |
||
|
Определение: xmorph 16.03.13 в 09:12 |
||
|
Возможность выполнить инициализацию в теле конструктора. xmorph 16.03.13 в 09:20 |
||
|
Плюсы: xmorph 16.03.13 в 09:21 |
||
|
Удобство печати. Нет нужды беспокоится о том, инициализирован ли класс или нет. xmorph 16.03.13 в 09:22 |
||
|
Минусы: xmorph 16.03.13 в 09:23 |
||
|
Проблемы с выполнением работы в теле конструктора: xmorph 18.03.13 в 12:26 |
||
|
Для конструктора не существует простого способа сообщить об ошибках, кроме использования исключений (которые запрещены). peterdemin 31.08.13 в 20:14 |
||
|
Если работа не удалась, то у нас имеется объект, чей код инициализации не выполнен, что влечет за собой неопределенное состояние. xmorph 18.03.13 в 12:40 |
||
|
Если при работе вызываются виртуальные методы, эти вызовы не будут переданы наслденику. Будущие изменения вашего класса могут значительно усугубить проблему, даже если ваш класс не унаследован в данный момент, что может привести к большим затруднениям. peterdemin 31.08.13 в 20:17 |
||
|
Если кто-то создаёт глобальную переменную такого типа (что против правил, но всё же), код конструктора будет вызван до вызова main(), возможно, ломая некоторые неявные предположения в коде конструктора. aereiae 05.02.14 в 02:30 |
||
|
Вывод: xmorph 18.03.13 в 12:51 |
||
|
Конструкторы никогда не должны вызывать виртуальные функции или пытаться повлечь нефатальные ошибки. Если Ваш объект нуждается в нетривиальной инициализации, решите это созданием функции-фабрики или метода Init(). aereiae 05.02.14 в 02:33 |
||
|
Конструкторы по умолчанию xmorph 18.03.13 в 12:41 |
||
|
Вы должны определить конструктор по умолчанию, если ваш класс определяет члены-переменные и не имеет других конструкторов. В противном случае компилятор сделает это за вас, плохо. xmorph 18.03.13 в 12:45 |
||
|
Определение: xmorph 18.03.13 в 12:46 |
||
|
Конструктор по умолчанию вызывается когда мы создаем экземпляр класса без аргументов. Он всегда вызывается при вызове new[] (для массивов). xmorph 18.03.13 в 12:48 |
||
|
Плюсы: xmorph 18.03.13 в 12:48 |
||
|
Инициализацию структур по умолчанию, провести "невозможно", дебагинг, делает отладку намного легче. Dridrift 10.09.13 в 13:22 Инициализация структур по умолчанию, чтобы исключить "невозможные" значения, делает дебаггинг гораздо проще. aereiae 05.02.14 в 00:37 |
||
|
Минусы: xmorph 18.03.13 в 12:50 |
||
|
Дополнительная работа для вас, написание большего кода. xmorph 18.03.13 в 12:50 Дополнительная работа для вас, создателя кода. aereiae 05.02.14 в 00:38 |
||
|
Вывод: xmorph 18.03.13 в 12:52 |
||
|
Если Ваш класс определяет поля и не имеет конструкторов, необходимо всё же создать стандартный конструктор (пусть в нём даже не будет аргументов). Он должен предпочитаемым образом инициализировать объект таким образом, чтобы его внутреннее содержимое было целостно и достоверно. aereiae 05.02.14 в 00:41 |
||
|
Причина для этого заключается в том, что, если у Вас нету конструкторов и не определён стандартный, то компилятор сгенерирует такой конструктор сам. И этот сгенерированный конструктор может неправильно инициализировать Ваш объект. aereiae 05.02.14 в 00:43 |
||
|
Если ваш класс наследуется от существующего класса но вы не добавляли новых переменных-членов, то конструктор по умолчанию не нужен. xmorph 18.03.13 в 12:54 |
||
|
Явные конструкторы peterdemin 31.08.13 в 20:19 |
||
|
Используйте ключевое слово explicit для конструкторов с одним аргументом. peterdemin 31.08.13 в 20:19 |
||
|
Определение: peterdemin 31.08.13 в 20:18 |
||
|
В большинстве случаев, если конструктор принимает аргумент, то он может использоваться для конвертации. К примеру, если вы определяете Foo::Foo(string name) и затем передаёте некую строку в функцию, которая принимает Foo, то конструктор может быть вызван для конвертации строки в Foo и передачи результата в Вашу функцию. Это может быть удобным для Вас, но может послужить и источником проблем, когда переменные конвертируются и этим создаются новые объекты, хотя Вы этого и не хотели. Объявление конструктора явно предотвращает его косвенные вызовы как конвертера. aereiae 05.02.14 в 00:49 |
||
|
Преимущества: peterdemin 31.08.13 в 20:17 |
||
|
Исключает нежелательные преобразования. peterdemin 31.08.13 в 20:21 |
||
|
Минусы: flyngate 12.10.13 в 23:26 |
||
|
Не имеются. flyngate 12.10.13 в 23:26 |
||
|
Вывод: peterdemin 31.08.13 в 20:18 |
||
|
Мы требуем, чтобы все конструкторы с одним аргументом были explicit. Всегда помещайте explicit перед такими конструкторами в объявлениях класа: explicit Foo(string name); aereiae 05.02.14 в 00:51 |
||
|
Исключением являются copy-конструкторы, которые в тех редких случаях, когда мы их разрешаем, не должны быть explicit. Классы, являющиеся прозрачными оболочками для других классов, также в списке исключений из этого требования. Такие исключения должны быть обязательно помечены комментариями. aereiae 05.02.14 в 02:35 |
||
|
Copy-контрукторы aereiae 05.02.14 в 00:52 |
||
|
Переопределяйте copy-конструктор и оператор присваивания только когда это необходимо. Иначе, выключайте их с помощью DISALLOW_COPY_AND_ASSIGN. aereiae 05.02.14 в 00:53 |
||
|
Определение: aereiae 05.02.14 в 00:53 |
||
|
Copy-конструктор и оператор присваивания используются для создания копий объектов. Copy-конструктор косвенно вызывается компилятором в некоторых ситуациях (например, передача объекта как значения). aereiae 05.02.14 в 00:55 |
||
|
Преимущества: peterdemin 31.08.13 в 20:17 |
||
|
Copy-конструкторы делают проще копирование объектов. STL контейнеры требуют, чтобы всё содержимое было доступно для записи и копирования. Copy-конструкторы могут быть более эффективны, чем CopyFrom()-обработчики, потому как они совмещают определение класса с копированием, компилятор может игнорировать их в некоторых контекстах и они позволяют проще избегать выделение памяти heap. aereiae 05.02.14 в 00:58 |
||
|
Недостатки: aereiae 05.02.14 в 00:59 |
||
|
Косвенное копирование объектов в С++ является огромным источников ошибок и проблем производительности. Так же, оно затрудняет чтение кода, так как становится сложным отследить, какие объекты были переданы по значению, а какие - по ссылке и, как результат - где отражаются изменения в объекте. aereiae 05.02.14 в 01:02 |
||
|
Вывод: peterdemin 31.08.13 в 20:18 |
||
|
Некоторые классы нуждаются в возможности копирования. Большинство же не должно иметь ни copy-конструктора, ни оператора присвоения. Во многих ситуациях, ссылка или указатель будут работать так же хорошо, как скопированное значение, но с большей скоростью. К примеру, Вы можете передать в функцию параметру по ссылку или указателю вместо передачи по значениям и Вы можете хранить указатели, а не объекты в STL контейнерах. aereiae 05.02.14 в 01:06 |
||
|
Если ваш класс должен быть копируемым, то лучше используйте создание собственного метода для копирования, такого как CopyFrom() или Clone(), так как такие методы не могут быть вызваны косвенно или случайно. Если собственный метод не может быть решением в Вашем случае (например, низкая производительность или ваш класс должен храниться по значению в STL контейнере), создайте и copy-конструктор, и оператор присваивания. aereiae 05.02.14 в 01:09 |
