2010-06-27 3 views
8

Если вы видите этот код,Когда все делает оператор запятой не как запятую?

class A{ 
public: 
    A(int a):var(a){} 
    int var; 
}; 

int f(A obj) { 
    return obj.var; 
} 

int main() { 
    //std::cout<<f(23); // output: 23 
    std::cout<<f(23, 23); // error: too many arguments to function 'int f(A)' 
    return 0; 
} 

f(23, 23) не компилируется потому, что запятая выступает в качестве разделителя здесь, а не в качестве оператора запятая.

Где находится запятая не Работает как оператор запятой? Или наоборот?

ответ

11

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

Оператор запятой делает выражение из-за экспрессии, A , и присваивания выражение, но выражение с участием оператора запятой не является сам по себе является присваивания выражение так может» t отображается в списке-фактуре , за исключением случаев, когда он является составной частью чего-то, что является присваиванием-выражением.

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

E.g.

постфикса-выражение, где выражение-лист состоит из двух присваивания выражение- каждого из которых является идентификатором .

f(a, b); 

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

f((a, b)); 
8

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

Wikipedia - Comma operator

+4

Что такое «аналогичные конструкции»? – Philipp

+0

@Philipp: В принципе, те конструкции, в которых грамматика явно описывает смысл запятой. Вышеприведенный список пропускает, например, объявления участников и друзей, которые очень похожи на объявления переменных. Другим примером может быть временное выражение объекта, такое как «Complex (0,1)», которое аналогично вызову функции. – MSalters

+0

+1 для супер краткого ответа. – stinky472

1

Оператор запятая всегда выступает в качестве оператора запятая, но запятая не всегда означает оператор запятая - иногда это просто знаки препинания.

Что касается пунктуации, то простой ответ - «когда стандарт говорит так». Прохождение всех ситуаций, когда стандарт говорит, дает гораздо более длительный ответ - но вряд ли он будет намного полезнее, потому что (на одном примере) он должен иметь дело с несколькими угловыми делами, большинство людей не очень-то заботятся около.

7

Это связано с определением языка выражений, которое довольно сложно.

f(1, 2) - выражение функции вызова с двумя параметрами. Наоборот, f((1, 2)) является выражением вызова функции с одним параметром, который является Подвыражением 1, 2, который будет оценивать до 2.

+0

Потому что запятая здесь оператор! Возвращается результат самого правильного выражения. Просто для разъяснения любому читателю –

8

Я выполнил поиск по проекту стандарта. В принципе, в грамматике -list производятся те, у которых есть запятые в них для разделения разных предметов. Следующие результаты относятся к C++ 03. В C++ 0x, список-выражение непосредственно делегирует список-инициализатор, потому что в C++ 0x скобки могут также встречаться в аргументах функции и конструктора.

  • выражение-лист Для функциональных аргументов/конструктор (в том числе функциональных слепков)
  • перечислитель-лист Перечень предметов в перечисления
  • INIT-описатель-лист Различные названия, заявленные в одном объявлении

    Примера:

    int a, b; 
    
  • параметр декларирование списокпараметра списка декларации (! Сюрприз) из функции
  • инициализатор-лист списка похож на список_выражения, но могут включать в себя списки расширенных выражений. Используется для совокупной инициализации (инициализация массивов или структур)
  • член-описатель-лист Подобный список описатель инициализации, но для деклараций членов в классах.

    Пример:

    struct A { int a, b; }; 
    
  • база спецификатор-лист Список базовых классов класса.
  • мем-инициализатора-лист Список инициализаторах для членов

    Пример:

    struct A { A():a(0), b(0) { } int a; int b; }; 
    
  • шаблон-список параметров Список из параметров шаблона деклараций.
  • template-argument-list Список аргументы в шаблоне принят к шаблону.
  • Type-ID-лист Перечень видов для спецификации исключений

    Пример:

    void f() throw(int, bool) { } 
    

Существует идентификатор-лист для макро параметров тоже, что я не попали в этот список, потому что это действительно часть грамматики препроцессора.