Функция друга не может получить доступ к частной переменной-члену

У меня два класса, PlayerCharacter и Ability. Класс Ability имеет чисто виртуальную функцию, которую я объявляю как friend до PlayerCharacter. Однако я, похоже, не могу получить доступ к закрытым членам в объявленной функции friend. Это что-то, что я упускаю из виду?

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

player_chracter.h :

#include "ability.h"

class PlayerCharacter : public Character {
private:
    // Friend function
    friend bool Ability::ExecuteAbility(PlayerCharacter& in_player);

    // This doesn't work either
    //friend bool Dash::ExecuteAbility(PlayerCharacter& in_player);

    // Private variable
    float top_speed_;
}

способность.h :

//Forward declaration
class PlayerCharacter;

class Ability {
public:
    Ability();
    ~Ability();
    virtual bool ExecuteAbility(PlayerCharacter& in_player) = 0;
};
//---------------------------------------------------------
class Dash : public Ability {
public:
    Dash();
    ~Dash();
    bool ExecuteAbility(PlayerCharacter& in_player);
};

ability.cpp :

#include "ability.h"
#include "player_character.h"   //Follow through on forward declaraction

bool Dash::ExecuteAbility(PlayerCharacter& in_player) {
    float example = in_player.top_speed_;
}

Почему в приведенном выше коде я не могу получить доступ к top_speed_ и поместить его в переменную float example?


person Hoxbot    schedule 19.02.2019    source источник
comment
Не могли бы вы добавить сообщения об ошибках в обоих случаях, пожалуйста?   -  person Quentin    schedule 19.02.2019


Ответы (2)


Согласно [class.friend]/10, дружба не передается по наследству. Производный класс не становится автоматически другом класса только потому, что его родительский класс является другом этого класса.

Причина, по которой приведенное ниже также не работает, вероятно, заключается в том, что Dash не определена до определения функции ExecuteAbility.

friend bool Dash::ExecuteAbility(PlayerCharacter& in_player);

Однако при правильном порядке определений это сработает. См. DEMO.

person P.W    schedule 19.02.2019
comment
Действительно, похоже, это так. Спасибо за помощь. - person Hoxbot; 19.02.2019

Из cppreference:

Дружба не транзитивна (друг вашего друга не является вашим другом)

Дружба не передается по наследству (дети вашего друга вам не друзья)

Даже если Dash::ExecuteAbility переопределяет функцию friend из своего базового класса, она не получает от этого никакой пользы. Вам придется пересмотреть свой дизайн.

person Quentin    schedule 19.02.2019
comment
Привет, Квентин. Как вы объясните // This doesn't work either //friend bool Dash::ExecuteAbility(PlayerCharacter& in_player); ? - person YSC; 19.02.2019
comment
@YSC В вопросе отсутствует копия ошибки (я ответил слишком рано? Возможно.), но я подозреваю, что это просто случай, когда Dash не был определен заранее. - person Quentin; 19.02.2019