Derived类中的方法fun()
是私有的。当我们通过运行时多态性调用函数ptr->fun()
时,它正在执行。
但这违反了Derived类的封装属性。
#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;
}
有人可以解释一下发生了什么吗?
答案 0 :(得分:2)
首先,您的Derived::fun()
也是virtual
,因为如果派生类中的函数与基类中的虚函数具有相同的声明,则派生类中的函数会自动获取{ {1}},即使没有明确指定。
其次,通过基类的公共中间函数访问私有虚函数是完全可以的,例如,参见this answer及其链接,尤其是Virtuality by Herb Sutter。示例代码可能类似于
virtual
因此,我认为,您的情况会发生类似情况:#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()
恰好是{{} 1}}。
UPD :扩展评论
但这听起来有点令人担忧......我的意思是,所有的功能 派生自Base类的将拥有自己的私有成员 可以访问Base类的友元函数
不,fun()
的朋友不能访问Derived::fun()
的所有功能,只能查看可通过Derived
指针访问的功能。例如:
Base
只能从main访问Base
:
class Base {
virtual void fun();
friend int main();
}
class Derived: public Base {
virtual void fun();
virtual void foo();
void bar();
}
请注意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
函数的任何覆盖意味着可以通过virtual
指针调用该函数;这是Derived
函数的主要目的。如果Base
使其重写函数virtual
,它仍然应该意识到可以通过Derived
指针访问该函数,因为这是private
函数背后的主要思想。
答案 1 :(得分:1)
Friend
函数从不参与继承。
这里发生了什么?
在Base
类中定义虚方法时,会创建一个虚拟表,其中包含fun
类Base
方法的地址。由于Derived
类继承了它,因此VTABLE还包含Derived
类fun
方法的地址。现在,由于main
是Base
类的友元函数,编译器允许其成员访问main
方法,而不管其访问说明符如何。因此,main
获取Derived::fun
的地址,并在运行时调用Derived
类fun
。
答案 2 :(得分: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
的私人成员无法访问。