我应该在这里使用朋友类吗?

Should I use a friend class here?

本文关键字:朋友 在这里 我应该      更新时间:2023-10-16

我刚刚和我的一个朋友重新开始学习c++。我正在编写一款基于文本的基本地下城游戏,试图让玩家上下左右移动。我的问题有两个部分。

我创建了一个Map类,一个Player类和一个gamelloop类。发生的一切显然都在我的gamelloop中。Map类有一个叫做Move()的函数来移动玩家。在地图类中,我应该让我的玩家类有友谊访问地图类吗?我不太清楚什么时候该使用好友类。我想知道游戏循环函数是否应该使用map.Move(),或者我是否应该将Move()放入Player类中,使它们成为朋友,并使用Player .Move()。

我的Map类保存了坐标的私有数据,这是我的玩家所在的位置。

我知道这可能有点主观,但我有点笼统地说。使用友类比直接使用Map对象更有效吗?

关于我的第二个问题。我知道类很常见,但我想知道对象是否也很常见。是否应该为每个类至少创建一个对象,或者您甚至可以创建一个类并使用它而不创建对象?

类是有用的,因为它们可以有方法和状态/数据。一般来说,如果类中有任何数据,那么不创建任何对象是没有意义的。然而,您可以实现仅由公共静态函数组成的实用程序类。在这种情况下,您不必创建任何对象。

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);

在您的例子中,不需要使用静态类和友类,如我们所见

对我来说,朋友课是我最不愿意去的。根据你的描述,你可以让move()成为player类的公共方法,因为它是真正"移动"的玩家,而不是map。此外,您需要向我们清楚地说明您的map类是做什么的。

编辑:如果你的地图类简单到可以移除,你可以将玩家的坐标移动到玩家类。

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

作为friends是两个类可以拥有的最紧密的耦合。通常,您希望避免高耦合中隐含的依赖关系。让您的Player类使用Map类的公共接口,除非您绝对必须使用friend

我会这样做:

void MainLoop() {
    // ... Read input and so on ...
    player.Move(input);
    map.Update(player.GetPosition());
}

关于效率:friend实际上与效率无关,因为公共/保护/私有检查是在编译时应用的。即使是这样,使用friend来实现效率也是一个过早优化的典型例子——你应该避免。

如果你的类有一些或只有静态成员,它可以在不实例化对象的情况下使用。更常见的情况是,您有一个类,但没有成员是抽象接口。这些类被设计成定义接口的基类,以后的类可以继承和实现接口。

正如您所说的答案是主观的,我更愿意将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;
}

我将对你的问题的两个一般方面作出反应,并避免你所指的特殊情况。你没有提供太多细节,我希望一般情况能帮助你决定你是否需要使用友谊。

我对何时使用friend类有点困惑。

friendpublicprivate更像protected,因为它授予部分选择性访问权。当您特别想要授予对单个类或函数的访问权限,而不是授予对任何人的访问权限时,通常需要使用friend声明。

你在一个岩石和一个困难的地方:你必须授权访问,所以你不能使用private;然后你必须再次封装你的数据,所以你不能使用public。在这些情况下,friendprotected可以让您挤出那个紧张的位置。

friendprotected的基本区别在于后者在授予访问权限的实体数量上是开放的

如果你想要更多的细节或示例,c++ FAQ中有一个关于friends的很好的部分。

我知道这可能有点主观,但我有点笼统地说。使用友类比直接使用Map对象更有效吗?

这与主观无关。访问限制仅在编译期间使用,而不是在程序运行时使用。因此,它们不会产生运行时开销。如果引用的数据成员是通过简单的内联getter函数访问的,那么也不应该产生开销。无论如何,在我排除了一堆其他情况之前,我不会开始调查这个问题,因为这很可能不是您的瓶颈。