友谊和继承有什么区别?

What's the difference between friendship and inheritance?

本文关键字:区别 什么 继承 友谊      更新时间:2023-10-16

假设有两个类A和B:

class A {};
class B {};

以下两个示例在哪些方面有所不同?

示例 1:

class C : public A, public B {}; 

示例 2:

class C
{
    //private
    friend class A;
    friend class B;
}

friend可以触摸它的朋友的private部分(双关语只是稍微有意!;)(,但AB都不是C的一部分 - 它只是意味着"AB可以触摸C的私人位"(。任何"小于"private的东西当然也可供AB使用,因此,如果Cprotectedpublic成员,那也将可用。

当您继承时,AB成为C的一部分。AB的任何private部分都不适用于C。在"is-a"与"has-a"命名法中,C现在是A和is B - 换句话说,它是从A继承而来的,所以它"从界面的角度来看就像A一样。

有几个很大的区别。 继承和友谊是非常不同的。

有了友谊,C类不是A类或B类的实例。 因此,如果您有如下函数:

void processMyClass(A* a);

你不能给它传递一个 C 的实例,而如果 C 子类 A(公开(,它是 A 的实例。

有了友谊,A类和B类可以接触到C类的所有私有会员数据和功能。 通过继承,C 类可以接触 A 和 B 的公共和受保护成员。

友谊不是遗传的。 这意味着,例如:

class D : public C
{
private:
   void foo() {
      // A and B cannot call this function
   }
}

在你使用的上下文中,为了尽我所能回答你的问题,朋友只是允许你的类共享受保护/私有数据,而继承也会这样做,除了会有更深层次的关系,其中类是相同的(例如使用强制转换(。

虽然你得到的答案相当准确,但我认为它们并不完整。特别是,尽管它们解释了友谊和继承之间的区别,但它们并没有真正解释您应该在何时使用哪个,或者差异如何影响您的代码。

继承(在 C++ 中(的主要用途是在基类中定义接口,并在多个派生类中的每一个中实现该接口。派生类必须实现的接口部分通常由基类中的纯虚函数表示。

friend 在 C++ 中发布的主要用途是定义构成接口一部分的内容,但由于语法原因不能成为成员函数。一个非常常见的例子是流插入或提取运算符。若要将这些函数实现为成员函数,它们必须是流类的成员。由于我们不想不断修改流类,因此它们是自由函数,它们将对流的引用作为其左参数,并将对它们插入/提取的类型(可能是 const(对象的引用作为其右操作数。

这些不一定是类friend - 它们可以编写为仅使用类的公共接口。但是,如果这样做,这通常意味着该类在其公共接口中公开的内容比其他必要内容要多。界面不再最小,这往往表明设计有问题。

但需要注意的是:您可以在类定义定义一个友元函数:

class Foo { 
// ...
    friend std::ostream &operator<<(std::ostream &os, Foo const &f) { 
        // ...
    }
};

乍一看,这可能看起来很奇怪(语法上确实如此(。即使它是在类定义中定义的,friend也意味着这不是成员函数。至少在我看来,这相当准确地反映了它的情况:从概念上讲,它是类的一部分。它可以访问私有成员,就像类的任何其他成员一样。它是一个自由函数而不是成员函数这一事实纯粹是一个实现工件,本质上与代码的设计无关。

这也指出了friend交付和继承之间的另一个区别:使用继承时,通常主要处理成员函数。每个成员函数仍接收一个this指针,因此每个成员函数都直接与类的特定实例相关联。是的,如果需要,您可以将其定义为接收(指针或引用(类的另一个实例,但无论如何,它始终接收this。朋友(函数或类(不明白这一点 - friend声明只是意味着该其他类私有的名称friend可见。要访问该类的实际实例,通常需要将其作为参数或该顺序传递。

最后,我要指出,前面的那种忽略了私有或受保护继承的可能性。私有继承通常意味着派生类是按照基类实现的。如果(例如(派生类与基类相似,但在设计中不相关,则这可能很方便 - 即,您没有断言派生类的实例可以在需要基类实例的任何地方使用。它对基类的使用是世界其他地方不需要知道或关心的实现细节。

受保护的继承几乎是一个错误。这是允许的,因为它与publicprivateprotected成员一致(这确实有意义(,但对于继承,受保护似乎根本没有完成任何有用的事情。