Какая разница между функцией (myVar) и (функцией) myVar?
Я просматриваю полный учебник на cplusplus.com, кодируя и компилируя каждый пример вручную. Регулярно я натыкаюсь на то, что оставляет меня озадаченным.
В настоящее время я изучаю этот раздел: http://www.cplusplus.com/doc/tutorial/structures/. Есть некоторые тонкости, которые можно легко упустить, только прочитав учебник. Преимущество печатать все вручную - это то, что такие детали выделяются.
На приведенной выше странице есть две примеры программ. У этой строки есть:
stringstream(mystr) >> yours.year;
Другой имеет следующую строку:
(stringstream) mystr >> pmovie->year;
То, что я не понимаю, - это разница (если есть) между function (myVar) = x;
и (function) myVar = x;
.
Я не делаю весь учебник в последовательном порядке. Я проверил, но не нашел это нигде, хотя я, возможно, пропустил его.
- Есть ли разница?
- Есть ли предпочтительный способ сделать это одним способом, а не другим?
Ответы
Ответ 1
Нет разницы между type(x)
и (type)x
. Эти два полностью эквивалентны. Большинство людей предпочитают type(x)
для классов и (type)x
для неклассовых типов, но это чисто до одного собственного выбора. Оба конструктора вызова для классов с одним аргументом x
.
Предпочтительным способом для классов является type(x)
, потому что это позволяет передавать более одного аргумента конструктору, как в type(x, y)
. Пытаясь применить другую форму, (type)x, y
не будет работать: он отличает x
, а затем применяет оператор запятой и evalutes y
изолированно. Скобки, такие как (type)(x, y)
, не помогают: это будет оценивать x
и y
изолированно с помощью оператора запятой, а затем отбрасывает y
в type
.
Для типов, отличных от класса, такой приведение часто слишком мощное. С++ имеет static_cast<type>(x)
для грубого обращения к неявному преобразованию (например, приведение базовых классов к производным классам и отбрасывание void*
к другому указателю), что часто является тем, что подходит. См. Когда следует использовать static_cast, dynamic_cast и reinterpret_cast?.
stringstream
не является функцией. Выполнение function(x)
вызовет его функцию, но выполнение (function)x
является незаконным, потому что рядом друг с другом есть два выражения, без оператора между ними.
Для тех, кто не верит в этот ответ, и уменьшите его на ощущениях кишки, обратитесь к стандарту в 5.2.3/1
Спецификатор простого типа (7.1.5), за которым следует заключенный в скобки список выражений, строит значение указанного типа с учетом списка выражений. Если список выражений является одним выражением, выражение преобразования типа эквивалентно (в определенности и, если определено по смыслу), в соответствующее выражение (5.4).
Ответ 2
Страница, которую вы цитируете, не является тем, что я бы рассматривал как авторитет на С++ вообще.
В любом случае,
(stringstream) mystr → pmovie- > year;
передает объект std::string
в объект std::stringstream
. Это C-стиль. Скорее опасно, если вы не знаете, что делаете. Это создаст объект stringstream
, и значение будет извлечено в pmovie->year
next.
stringstream (mystr) → yours.year;
Создает анонимный объект std::stringstream
и инициализирует его с помощью mystr
, а затем значение извлекается до pmovie->year
. Объект исчезает в конце его лексического масштаба, который в этом случае будет ;
в конце строки.
Не так много различий (как другие отметили до сих пор) среди двух объектов класса w.r.t.
С другой стороны, с идентификаторами (функций/макросов) это становится сложным: function (myVar) = x;
работает независимо от того, является ли function
фактической функцией или макросом. Однако (function) (myVar) = x;
работает только для реальных функций.
Некоторым стандартным идентификаторам библиотеки разрешено иметь обе формы (в первую очередь, tolower
и друзей), и поэтому, если вы хотите всегда вызывать функцию, вы должны перейти к первой.