为什么C ++不允许继承友谊?
为什么友谊至少不能在C ++中继承? 我明白传递性和反身性因为显而易见的原因被禁止(我说这只是为了阻止简单的常见问题引用答案),但是缺乏类似于virtual friend class Foo;
困惑我。 有人知道这个决定背后的历史背景吗? 友谊真的只是一个有限的黑客,因为它已经找到了一些晦涩的可敬的用途?
编辑澄清:我在谈论以下场景,而不是A的孩子接触B或B和它的孩子。 我还可以设想可以选择授予对朋友函数等的覆盖访问权限。
class A {
int x;
friend class B;
};
class B {
// OK as per friend declaration above.
void foo(A& a, int n) { a.x = n; }
};
class D : public B { /* can't get in A w/o 'friend class D' declaration. */ };
接受的答案:正如Loki所说,通过在友善的基类中进行受保护的代理函数,可以或多或少地模拟这种影响,所以不需要为班级或虚拟方法提供友谊。 我不喜欢使用样板代理(好友基地有效地成为代理),但是我认为这比在大多数情况下更可能被误用的语言机制更可取。 我认为这可能是我购买和阅读Stroupstrup的C ++设计和演变的时间了 ,我已经看到了足够多的人在这里推荐,以更好地洞察这些类型的问题。
因为我可能会写Foo
和它的朋友Bar
(因此存在信任关系)。
但是,我相信编写从Bar
派生的类的人吗?
不是真的。 所以他们不应该继承友谊。
一个类的内部表示的任何变化都需要对依赖于该表示的任何事情进行修改。 因此,班级的所有成员以及班级的所有朋友都需要修改。
因此,如果Foo
的内部表示被修改,那么Bar
也必须被修改(因为友谊将Bar
紧紧绑定到Foo
)。 如果友谊被继承,那么所有从Bar
派生出来的类都将与Foo
紧密结合,因此如果Foo
的内部表示被改变,则需要修改。 但我不知道派生类型(我也不应该,他们甚至可能由不同的公司开发)。 因此,我将无法更改Foo
因为这样做会在代码库中引入重大更改(因为我无法修改从Bar
派生的所有类)。
因此,如果友谊被遗传了,你无意中引入了修改班级能力的限制。 这是不可取的,因为你基本上渲染了公共API的概念。
注:一个孩子Bar
可以访问Foo
通过Bar
,只要在方法Bar
保护。 然后, Bar
的孩子可以通过调用其父类来访问Foo
。
这是你想要的吗?
class A
{
int x;
friend class B;
};
class B
{
protected:
// Now children of B can access foo
void foo(A& a, int n) { a.x = n; }
};
class D : public B
{
public:
foo(A& a, int n)
{
B::foo(a, n + 5);
}
};
为什么友谊至少不能在C ++中继承?
我认为你的第一个问题的答案是在这个问题上:“你父亲的朋友可以接触你的私人吗?”
朋友们可以通过访问者函数公开其朋友,然后通过这些访问者授予访问权限。
class stingy {
int pennies;
friend class hot_girl;
};
class hot_girl {
public:
stingy *bf;
int &get_cash( stingy &x = *bf ) { return x.pennies; }
};
class moocher {
public: // moocher can access stingy's pennies despite not being a friend
int &get_cash( hot_girl &x ) { return x.get_cash(); }
};
这允许比可选传递性更好的控制。 例如, get_cash
可能会protected
或者可能会强制执行运行时限制访问的协议。
上一篇: Why does C++ not allow inherited friendship?
下一篇: How to initialize all members of an array to the same value?