C ++ реализует дружественные / встроенные функции - PullRequest
7 голосов
/ 22 августа 2011

Я не могу найти ответ на этот вопрос новичка.Если у меня есть класс // Заголовочный файл (.h)

Class X {
public:
  friend bool operator==(const X&, const X&);
  inline size_type rows() const;
};

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

// CPP file (.cpp)
#include "X.h"
friend bool operator==(const X&, const X&) {
  //implementation goes here
  //return true/false
}

inline size_type rows() const {
  return r;
}

, или не включать их, т. е. как показано ниже

#include "X.h"
bool operator==(const X&, const X&) { ... }

size_type rows() const { ... }

Ответы [ 3 ]

6 голосов
/ 22 августа 2011

Нет, не следует, то есть вторая версия верна.

friend может использоваться только внутри определения класса (оно не имеет смысла вне его), и компилятор ищет сигнатуру функции, чтобы найти определение функции friend, объявленной в вашем классе X.

inline используется в заголовочных файлах (хотя, я думаю, технически возможно использовать его и в файле cpp, но в этом нет никакого смысла). И обратите внимание, что inline имеет смысл, только если вы на самом деле определяете функцию прямо здесь - это может не иметь никакого эффекта, если вы предоставите определение функции отдельно, в файле cpp.

Смысл inline состоит в том, чтобы намекнуть компилятору, что рассматриваемая функция может быть встроена (однако это не гарантия - компилятор может решить, будет ли он встроен в эту функцию или нет). Если функция встроена, любые обращения к ней заменяются копией тела функции. Это практически всегда делается для повышения производительности, для экономии затрат на вызовы функций, за счет потенциально увеличивающегося размера программы. Теперь, если мы хотим встроить функцию, мы хотим, чтобы она была встроена повсюду, а не только в пределах одного модуля компиляции; вот почему не имеет смысла использовать ключевое слово inline внутри файла реализации.

4 голосов
/ 22 августа 2011

При определении функций friend вы можете использовать одну из двух различных опций:

Определить функцию friend внутри определения класса

namespace Test {
class test {
   int priv;
   friend void foo( test const & t ) { std::cout << t.priv << std::endl; }
};
}

Определить их в окружающем пространстве имен:

namespace Test {
class test {
   int priv;
   friend void foo( test const & t );
};
void foo( test const & t ) {
   std::cout << t.priv << std::endl;
}
}

Но обратите внимание, что существуют различия в поиске.В частности, первый случай является более ограничительным (и поэтому должен быть предпочтительным), поскольку только ADL (Argument Dependent --aka Koening-- Lookup) найдет его, тогда как во втором случае функция будет рассматриваться всякий раз, когда рассматривается это пространство имен.

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

0 голосов
/ 22 августа 2011

Вам не нужен префикс друга в теле функции, только подпись в заголовке.

...