Какая разница между функцией (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 и друзей), и поэтому, если вы хотите всегда вызывать функцию, вы должны перейти к первой.