Каковы тонкие различия между методами и свободными функциями? - PullRequest
2 голосов
/ 08 декабря 2011

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

Но, похоже, существуют некоторые различия между методами и функциями; например, при передаче функции в качестве аргумента, почему оператор ссылки & должен использоваться в методах, а не в свободных функциях?

foobar(&MyClass::method);
goobar(freefunction);

Какие еще тонкие технические различия существуют между методами и свободными функциями?

Ответы [ 2 ]

3 голосов
/ 08 декабря 2011

In:

foobar(&MyClass::method);

... & не является "оператором ссылки", но является оператором адреса.Он принимает адрес своего операнда.

Вы действительно все еще «должны» взять адрес свободной функции в коде, например (хотя неявные преобразования доступны):

goobar(freefunction);

Существуют неявные доступные преобразования, которые приводят к тому, что выражение, такое как Foo, затухает в указателе, но у меня было много трудностей с тем, чтобы заставить GCC принимать такой код без ошибок и предупреждений, в тех случаях, когда у MSVC нет проблем.

Кроме этого, есть два основных различия между свободными функциями и нестатическими функциями-членами:

  1. Не static функции-члены работают с экземпляром класса, иесть указатель this, который указывает на сам класс.
  2. Синтаксис для создания и вызова через функцию указателя на свободную отличается от синтаксиса для функции указателя на член.

В случае свободной функции синтаксис тривиален (ish):

void foo();  // Function declaration
void(*f)();  // Declaration of pointer-to-function-returning-void-and-taking-no-parameters

Но в случае указателя на функцию-член, synналог намного сложнее:

struct Bar
{
  void DoIt()
  {
  }
  void DoThat(int n)
  {
    n;
  }
};


void(Bar::*thatfn)(int);    // declares a pointer-to-member-function taking int returning nothing
thatfn = &Bar::DoThat;      // initializes pointer to point to DoThat(int)
(bar.*thatfn)(42);          // call the function
1 голос
/ 08 декабря 2011

Я думаю, что это из-за (§5.3.1 / 3), который говорит,

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

и затем это объясняется как:

[Примечание: то есть выражение & (квалифицированный идентификатор), где квалифицированный идентификатор заключен в круглые скобки, не образует выражение типа «указатель на член». Ни один не делает квалифицированный идентификатор, поскольку существует неявное преобразование из квалифицированного идентификатора для нестатической функции-члена в тип «указатель на функцию-член», поскольку существует значение l-типа функции в тип «указатель на функцию» (4.3). И & unqualified-id также не является указателем на член, даже в пределах класса unqualified-id. ]


Я только что получил две интересные темы, обсуждающие это, особенно ответ @ Йоханнеса, который можно прочитать здесь:

и этот тоже:

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

...