Определение функции-друга класса, который находится внутри пространства имен. - PullRequest
2 голосов
/ 29 июля 2011

Я читаю C ++ Primer, и автор говорит:

"Если класс определен внутри пространства имен, тогда в этом же пространстве имен объявляется необъявленная функция друга:

      namespace A {
        class C {
          public:
            friend void f(const C&); // makes f a member of namespace A
        };
      }

Разве это не означает, что мне не нужно снова объявлять функцию f () внутри пространства имен?

Когда я просто определяю функцию f () вне пространства имен как

void
A::f(const C& obj)
{
  std::cout << "f(const C&) " << std::endl;
}

Я получаю ошибку от g ++ 4.5, говоря:

FriendDeclarations1.cpp:40:23: error: ‘void A::f(const A::C&)’ should have been declared inside ‘A’

Может кто-нибудь сказать, что подразумевает автор?

Ответы [ 3 ]

3 голосов
/ 29 июля 2011

Автор имеет в виду, что функция Friend неявно объявляется в том же пространстве имен класса, если ее пространство имен не указано явно.

Поэтому f необходимо определить в пространстве имен A

#include <iostream>

namespace A {
  class C {
    friend void f(const C&); // makes f a member of namespace A
    int i;

    public:
      C() : i(42) {}
  };

  void f(const A::C& obj)
  {
    std::cout << "f(const A::C&) " << std::endl;
    std::cout << "obj.i = " << obj.i << std::endl;      // access private member
  }
}

int main()
{
  A::C ac;

  f(ac);
  return 0;
}

Вы можете изменить это поведение, явно указав пространство имен, которому f принадлежит

#include <iostream>

// forward declarations
namespace A { class C; }
namespace B { void f(const A::C&); }

namespace A {
  class C {
    friend void B::f(const C&);
    int i;

  public:
    C() : i(42) {}
  };
}

namespace B {
  void f(const A::C& obj)
  {
    std::cout << "f(const A::C&) " << std::endl;
    std::cout << "obj.i = " << obj.i << std::endl;      // access private member
  }
}

int main()
{
  A::C ac;

  B::f(ac);
  return 0;
}
2 голосов
/ 29 июля 2011

Стандарт 7.3.1.2 / 3:

Каждое имя, впервые объявленное в пространстве имен, является членом этого пространства имен. Если объявление друга в нелокальный класс сначала объявляет класс или функцию83) класс или функция друга является членом самого внутреннего вмещающее пространство имен. Имя друга не может быть найдено при простом поиске по имени, пока не будет предоставлено соответствующее объявление в этой области пространства имен (до или после объявления класса, предоставляющего дружбу).

0 голосов
/ 29 июля 2011

То, что у вас есть, интерпретируется как определение члена класса, для объявления класса, которое выглядит так:

class A {
  void f(const C& obj);
}

Вы должны определить f следующим образом:

namespace A {
  void f(const C& obj)
  {
    std::cout << "f(const C&) " << std::endl;
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...