публичная функция друга в C ++? - PullRequest
8 голосов
/ 05 мая 2011

Я видел некоторый код на C ++ и у меня возник вопрос:

  class CRectangle {
        int width, height;
      public:
        friend CRectangle duplicate (CRectangle);
    };

Переменные width и height являются частными, а метод duplicate() является открытым.Ключевое слово friend предназначено для доступа к закрытым и защищенным функциям вне объекта CRectangle, но duplicate() уже открыт.Если к нему можно получить доступ извне, зачем нам нужен «друг»?

Означает ли это, что хотя мы и вызываем открытый метод, такой как duplicate(), вне класса, если метод обращается к некоторому частномупеременная, она также не разрешена, и мы должны объявить ее как «друг?»

Это реализация функции duplicate();Я просто хочу прояснить вопрос:

CRectangle duplicate (CRectangle rectparam)
{
  CRectangle rectres;
  rectres.width = rectparam.width*2;
  rectres.height = rectparam.height*2;
  return (rectres);
}

Ответы [ 4 ]

6 голосов
/ 06 мая 2011

Золотое правило:

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

В вашем примере,

friend CRectangle duplicate (CRectangle); 

объявляется как функция друга в public спецификаторе доступа, но он все равно будет вести себя точно так же, даже если объявлен в private спецификаторе доступа.

Вы ошибочно принимаете функцию за функцию-член и, следовательно, вопрос. Это НЕ . Функция возвращает объект типа CRectangle и является другом того же класса CRectangle.

Функция CRectangle duplicate (CRectangle) может обращаться ко всем private & protected членам класса CRectangle, потому что она объявлена ​​friend of the class, а не потому, что она объявлена ​​в спецификаторе открытого доступа.

6 голосов
/ 05 мая 2011

Если вы удалите friend, эта функция станет методом - function, который объявлен внутри класса и является public method (так как public:)

Если вы ставите friend перед duplicate, это означает, что вы объявляете функцию, которая не является членом класса, которая принимает один аргумент - CRectangle и имеет доступ к private / protected членам класса.

Второй случай требует определения для CRectangle duplicate( CRectangle )

Оба случая разные.


EDIT: Для friend спецификатор доступа не имеет значения.

Под "вторым случаем требуется определение для CRectangle duplicate( CRectangle )", я имею в виду, что в первом случае тоже требуется определение, но оно

//         vvvvvvvvvvvv
CRectangle CRectangle::duplicate( CRectangle )
3 голосов
/ 05 мая 2011

Простой: duplicate не является членом CRectangle.Вы объявляете duplicate бесплатной функцией, которая является другом CRectangle.

class C {
public:
    friend void F(); // declares non-member F
    void F(); // declares member F
};
2 голосов
/ 05 мая 2011

Хороший вопрос, синтаксис немного сбивает с толку.

Синтаксис не означает, что duplicate является функцией-членом класса CRectangle. Скорее это означает, что функция (обычная функция) duplcate имеет доступ к частным данным CRectangle. Это указывает на то, что «разрешение на дублирующую функцию предоставлено».

Функция duplicate может все еще должна быть объявлена ​​и определена как как любая другая обычная функция (за исключением класса CRectangle). Я предпочитаю делать это как напоминание, что это обычная бесплатная функция

...