Должен ли я использовать класс друга здесь? - PullRequest
1 голос
/ 01 мая 2011

Я только что вернулся в C ++ с моим другом. Я пишу основную текстовую игру с подземельями, пытаясь заставить игрока двигаться вверх, вниз, влево и вправо. Ну, мой вопрос состоит из двух частей.

Я создал класс Map, класс Player и класс GameLoop. Все, что происходит, очевидно происходит внутри моего GameLoop. Класс Map имеет функцию Move () для перемещения игрока. В классе Map, я должен позволить моему классу Player иметь дружеский доступ к классу Map? Я немного запутался с тем, когда использовать классы друзей. Мне интересно, должна ли функция игрового цикла использовать map.Move (), или мне следует поместить Move () в класс Player, завести их в друзья и использовать player.Move ().

Моя Класс карты содержит личные данные координат, в которых находится мой игрок.

Я знаю, что это может быть немного субъективно, но я вообще-то говорю. Является ли использование класса друга более эффективным, чем непосредственное использование объекта Map?

На мой второй вопрос. Я знаю, что классы очень распространены, но мне интересно, есть ли объекты. Должен ли по крайней мере один объект быть создан для каждого класса, или вы могли бы даже создать класс и использовать его, не создавая объект?

Ответы [ 4 ]

2 голосов
/ 01 мая 2011

Быть friends - самая тесная связь, которую могут иметь два класса.В общем, вы хотите избежать зависимостей, подразумеваемых в высокой связи.Пусть ваш класс Player использует открытый интерфейс класса Map, если только у вас нет для использования friend.

. Я бы сделал что-то вроде этого:

void MainLoop() {
    // ... Read input and so on ...

    player.Move(input);
    map.Update(player.GetPosition());
}

Относительно эффективности: friend на самом деле не имеет отношения к эффективности, поскольку публичные / защищенные / частные проверки применяются во время компиляции.И даже если бы это было так, использование friend для достижения эффективности было бы ярким примером преждевременной оптимизации, чего следует избегать.

Если в вашем классе есть несколько или только статические члены, его можно использовать без создания экземпляровобъект.Более распространенный случай, когда у вас есть класс, но нет членов, которые являются абстрактными интерфейсами.Эти классы предназначены для того, чтобы быть базовыми классами, определяющими интерфейс, который затем наследуют и реализуют классы.

2 голосов
/ 01 мая 2011

Классы полезны, потому что они могут иметь методы и состояние / данные .Вообще говоря, если в вашем классе есть какие-либо данные, бессмысленно, что вы не создаете никаких объектов.Однако вы можете реализовать служебный класс, который состоит только из общедоступных статических функций.В таком случае вам не нужно создавать какой-либо объект.

Class CMyHelper
{
public:
    static double calculateDistance(CPoint A, CPoint B);
    static double calculateArea(double length, double width);
    //...
private:
    // You can even explictly say, I don't want make objects of this class.
    // You'll get a compile-time error if someone tries.
    CMyHelper();
    CMyHelper(const CMyHelper&);
}

CPoint A(100, 200);
CPoint B(50, 100);
//Call static method without instantiation
CMyHelper::calculateDistance(A, B);

В вашем случае нет необходимости использовать статический класс и класс Friend, как мы видим.

Для меня занятия с друзьями - это последнее, к чему я прибегну.Согласно вашему описанию, вы можете сделать move() публичным методом класса player, так как именно игрок фактически «двигается» вместо map.Кроме того, вам необходимо прояснить нам, что делает ваш map класс.

Редактировать: Вы можете переместить координату игрока в класс игрока, если ваш класс карты достаточно умен, чтобы удалить.

Class CPlayer
{
public:
    void move()
    {
        // moves up, down, left, or right
        // update m_position
    }
}

private:
    CCoordinate m_position;
}
0 голосов
/ 01 мая 2011

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

Меня немного смущает, когда использовать классы друзей.

friend больше похоже на protected, чем public или private в том смысле, что оно предоставляет частичный или выборочный доступ. Обычно вам нужно использовать объявление friend, когда вы конкретно хотите предоставить доступ к одному классу или функции, а не предоставлять доступ кому-либо.

Вы находитесь в трудном положении: вы должны предоставить доступ, поэтому вы не можете использовать private; затем вы должны инкапсулировать свои данные, поэтому вы не можете использовать public. В этих случаях friend и protected позволяют вам выжать это узкое место.

Основное различие между friend и protected состоит в том, что последнее составляет с открытым окончанием в количестве объектов, которым вы предоставляете доступ.

Если вам нужны подробности или примеры, в C ++ FAQ есть отличный раздел о друзьях .

Я знаю, что это может быть немного субъективно, но я вроде говорю вообще. Является ли использование класса-друга более эффективным, чем непосредственное использование объекта Map?

Это не имеет ничего общего с субъективностью. Ограничения доступа используются только во время компиляции, а не во время выполнения программы. Поэтому они не несут накладных расходов во время выполнения. Если к указанному элементу данных получают доступ через простую встроенную функцию получения, это также не должно повлечь за собой дополнительных затрат. В любом случае, я бы не стал расследовать это, пока я исключил кучу других случаев, так как это вероятно не ваше узкое место.

0 голосов
/ 01 мая 2011

Как вы сказали, ответ субъективен, я бы предпочел оставить Move() внутри player класса, так как он выполняет действие на Player.

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

Можете ли вы даже создать класс и использовать его без создания объекта?
Да, внутри класса можно иметь класс и иметь статические методы, которые затем можно вызывать, даже не создавая объект класса. Хотя я не могу придумать практического примера.

Пример кода:

class MyClass
{
    static int i;

    public:
    static void incrementCount()
    {
         i++;
    }

    static int returnCount()
    {
         return i;
    }
};

int MyClass::i = 0;

int main()
{

    int count;
    //Do Some processing

    MyClass::incrementCount();

    //Do Some More processing

    count = MyClass::returnCount();        

    return 0;

}
...