朋友功能在这里得到继承吗?

Is friend function getting inherited here?

Derived class 中的方法 fun() 是私有的。当我们通过运行时间多态调用函数ptr->fun()时,它正在执行。 但这违反了 Derived class.

的封装 属性
#include<iostream>
using namespace std;

class Derived;

class Base {
private:
    virtual void fun() { cout << "Base Fun"; }
friend int main();
};

class Derived: public Base {
private:
    void fun() { cout << "Derived Fun"; }
};

int main()
{
Base *ptr = new Derived;
ptr->fun();
return 0;
}

谁能解释一下这是怎么回事?

发生这种情况是因为您已将 fun 声明为虚拟。 在运行时搜索 vtable 时,它​​会找到 Derived::fun() 的条目,因此跳转到该地址。

但是友元函数没有被继承,你可以用这个检查。

class Base {
private:
    virtual void fun() { cout << "Base Fun"; }
    friend int main();
    int z = 20;
};

class Derived : public Base {
private:
    void fun() { cout << "Derived Fun"; }
    int m = 10;
};

int main()
{
    Base *ptr = new Derived;
    ptr->z = 10; //Accepted
    ptr->m = 5; //error
    return 0;
}

此处 Derived m 的私有成员无法被 main 访问。

Friend 函数从不参与继承。

这里发生了什么?
当在Baseclass中定义虚方法时,会创建一个虚table,其中包含Baseclass的fun方法的地址。由于 Derived class 继承了它,因此 VTABLE 还包含 Derived class fun 方法的地址。现在,由于 mainBase class 的友元函数,编译器允许其成员访问 main 方法,而不管它们的访问说明符如何。因此,main 获取 Derived::fun 的地址,Derived class fun 在运行时被调用。

首先,你的 Derived::fun() 也是 virtual,因为如果派生 class 中的函数与基 class 中的虚函数具有相同的声明], derived class 中的函数自动获取 virtual,即使没有明确指定。

其次,通过 public 基类 class 中间函数访问私有虚函数是完全可以的,例如,参见 this answer and its links, particularly Virtuality by Herb Sutter。示例代码可能像

#include<iostream>
using namespace std;

class Derived;

class Base {
private:
    virtual void fun() { cout << "Base Fun"; }
public:
    void funInt() { fun(); }
};

class Derived: public Base {
private:
    virtual void fun() { cout << "Derived Fun"; }
};

int main()
{
Base *ptr = new Derived;
ptr->funInt();
return 0;
}

所以,我认为你的情况是类似的情况:允许 main 访问 ptr->fun(),但由于虚拟性,这个 fun() 恰好是Derived::fun().

UPD:扩展评论

But doesn't this sound a little alarming.. I mean, all the functions that derive from the Base class, will have their private members accessible to the friend functions of the Base class

不,并不是Derived的所有功能都可以被Base的朋友访问,只有那些可以通过Base指针访问的功能。例如:

class Base { 
    virtual void fun();
    friend int main(); 
}
class Derived: public Base {
    virtual void fun();
    virtual void foo();
    void bar();
}

只能从 main:

访问 Derived::fun()
int main() {
    Derived *ptr = new Derived;
    Base* baseptr = ptr;
    baseptr->fun(); // ok, calls Derived::fun()
    baseptr->foo(); // error, no such function in Base
    ptr->foo(); // error, foo is private
    return 0;
}

请注意,virtual 函数是有意扩展的,Derived 中对 virtual 函数的任何重写都意味着可以通过 Base 指针调用该函数;这是 virtual 函数的主要目的。如果 Derived 使其覆盖函数 private,仍然应该意识到可以通过 Base 指针访问该函数,因为这是 virtual 函数背后的主要思想。