Jef*_*eff 86 c++ inheritance language-design friend
为什么友谊至少可以在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. */ };
Run Code Online (Sandbox Code Playgroud)
接受的答案:正如Loki所说,通过在受限制的基类中创建受保护的代理函数,可以或多或少地模拟效果,因此不需要向类或虚方法层次结构授予友谊.我不喜欢需要样板代理(有条件的基础有效地成为),但我认为这被认为比大多数时候更容易被滥用的语言机制更可取.我想这可能是我购买和阅读Stroupstrup的C++的设计和演变的时候了,我已经看到这里有足够多的人推荐,以便更好地洞察这些类型的问题......
Mar*_*ork 83
因为我可能会写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);
}
};
Run Code Online (Sandbox Code Playgroud)
wil*_*ilx 43
为什么友谊至少可以在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(); }
};
Run Code Online (Sandbox Code Playgroud)
这允许比可选的传递性更精细的控制.例如,get_cash可以是protected或可以强制执行运行时受限访问的协议.
C++标准,第11.4/8节
友谊既不是遗传也不是传递.
如果友谊会被继承,那么一个不打算成为朋友的类会突然有权访问你的类内部并且违反了封装.