朋友功能在这里得到继承吗?
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
函数从不参与继承。
这里发生了什么?
当在Base
class中定义虚方法时,会创建一个虚table,其中包含Base
class的fun
方法的地址。由于 Derived
class 继承了它,因此 VTABLE 还包含 Derived
class fun
方法的地址。现在,由于 main
是 Base
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
函数背后的主要思想。
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
函数从不参与继承。
这里发生了什么?
当在Base
class中定义虚方法时,会创建一个虚table,其中包含Base
class的fun
方法的地址。由于 Derived
class 继承了它,因此 VTABLE 还包含 Derived
class fun
方法的地址。现在,由于 main
是 Base
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
函数背后的主要思想。