通过基类访问派生类private成员?

时间:2022-09-07 21:20:07
#include <iostream>
struct B{
 virtual void f(){ std::cout << "B::f\n"; }
};
struct D: B{
    private:
void f(){ std::cout << "D::f\n"; }
};

int main()
{
    D d;
    B *pd = &d;
    pd->f();  //为什么可以调用D的私有函数f()呢?结果是D::f.
}
是不是虚拟继承与访问级别没关系啊?

22 个解决方案

#1


因为:
    D d;
    B *pd = &d;
   指针pd实际上还是指向一个D的对象的,所以调用D的void f()

#2


但是D的void f()是private的呀...

#3


问得好!

#4


B *pd = &d; 动态绑定可以这样实现

#5


这个问题好像在哪个地方有详细的说过,是不是effective c++上面哪?
不记得了...有谁记得么?

#6


很奇怪的问题

#7


这违反了面向对象的一些规则啊:子类只能扩大范围而不能缩小范围,对于Java来说类似的程序就是非法的,估计当时设计C++的人有自己的想法吧

#8


和你上次的问题一样哦!

#9


是一个很有趣的现象。

private、protected和public是类的访问限定符:public成员在类域内和类域外都能被访问;protected成员在类域内能被访问,但是在类域外,只限于类的派生类访问;private成员只能在类域内被访问。对于类的友元,可以*访问类的成员,上述访问限定符不起作用。

在本题中,在类域外直接通过D的对象d来访问 f 函数是不行的,因为受到private的访问限制。但是通过指向其基类的指针的访问是可以的,因为基类提供了一个访问 virtual 函数 f 的公共接口,通过这个公共接口可以在类域内访问私有成员。

也就是说访问限定符限制的是通过类的成员访问。对于其它方式的成员访问,如上述访问方式或者是友元访问等,类的限定符是不起作用的。

#10


是一个很有趣的现象。

private、protected和public是类的访问限定符:public成员在类域内和类域外都能被访问;protected成员在类域内能被访问,但是在类域外,只限于类的派生类访问;private成员只能在类域内被访问。对于类的友元,可以*访问类的成员,上述访问限定符不起作用。

在本题中,在类域外直接通过D的对象d来访问 f 函数是不行的,因为受到private的访问限制。但是通过指向其基类的指针的访问是可以的,因为基类提供了一个访问 virtual 函数 f 的公共接口,通过这个公共接口可以在类域内访问包括私有成员在内的成员。

也就是说访问限定符限制的是通过类的成员访问。对于其它方式的成员访问,如上述访问方式或者是友元访问等,类的限定符是不起作用的。

#11


这是个好问题,up

#12


to whyglinux(山青水秀):
因为基类提供了一个访问 virtual 函数 f 的公共接口,通过这个公共接口可以在类域内访问包括私有成员在内的成员。
//通过这个接口可以在"类域"内访问private成员.这里可是在main中直接访问呀.

访问限定符限制的是通过类的成员访问。对于其它方式的成员访问
//同上,这里虽然是通过基类的public成员来访问,但是最终定位到的函数却是private的.
//而这是直接在main中访问的.为什么可以呢?

#13


no no ?

#14


不太懂,忘高人答疑!!

#15


我觉得好像是虚拟函数表中的指针越过了访问限定符

#16


经过研究,好像只是在编译期检查访问限定
因为pd在编译期是基类指针,因此通过了编译,运行期可能没有访问限定的检查
所以通过虚拟函数表中的指针调用了派生类中的私有函数

#17


访问限定只具有编译期语义

#18


编译器问题?还是C++语言本身的问题?这成了一个问题 :)

#19


难道还是C++编译器的问题
还个编译器试试

#20


晕,本来就可以这样用啊,跟编译器有什么关系
访问限定只具有编译期语义

#21


1    D d;
2    B *pd = &d;
3    pd->f(); 

行3访问的实际上是d的虚函数表,也就是说:对于重载的虚函数,private失去意义
这也许是C++设计者忽略的一个问题。

#22


众说纷纭,带星的怎么也不回答一下这个问题呀!反正我是说不清楚!我觉得c、c++要比java 难,那就是c,c++最难啦!

#1


因为:
    D d;
    B *pd = &d;
   指针pd实际上还是指向一个D的对象的,所以调用D的void f()

#2


但是D的void f()是private的呀...

#3


问得好!

#4


B *pd = &d; 动态绑定可以这样实现

#5


这个问题好像在哪个地方有详细的说过,是不是effective c++上面哪?
不记得了...有谁记得么?

#6


很奇怪的问题

#7


这违反了面向对象的一些规则啊:子类只能扩大范围而不能缩小范围,对于Java来说类似的程序就是非法的,估计当时设计C++的人有自己的想法吧

#8


和你上次的问题一样哦!

#9


是一个很有趣的现象。

private、protected和public是类的访问限定符:public成员在类域内和类域外都能被访问;protected成员在类域内能被访问,但是在类域外,只限于类的派生类访问;private成员只能在类域内被访问。对于类的友元,可以*访问类的成员,上述访问限定符不起作用。

在本题中,在类域外直接通过D的对象d来访问 f 函数是不行的,因为受到private的访问限制。但是通过指向其基类的指针的访问是可以的,因为基类提供了一个访问 virtual 函数 f 的公共接口,通过这个公共接口可以在类域内访问私有成员。

也就是说访问限定符限制的是通过类的成员访问。对于其它方式的成员访问,如上述访问方式或者是友元访问等,类的限定符是不起作用的。

#10


是一个很有趣的现象。

private、protected和public是类的访问限定符:public成员在类域内和类域外都能被访问;protected成员在类域内能被访问,但是在类域外,只限于类的派生类访问;private成员只能在类域内被访问。对于类的友元,可以*访问类的成员,上述访问限定符不起作用。

在本题中,在类域外直接通过D的对象d来访问 f 函数是不行的,因为受到private的访问限制。但是通过指向其基类的指针的访问是可以的,因为基类提供了一个访问 virtual 函数 f 的公共接口,通过这个公共接口可以在类域内访问包括私有成员在内的成员。

也就是说访问限定符限制的是通过类的成员访问。对于其它方式的成员访问,如上述访问方式或者是友元访问等,类的限定符是不起作用的。

#11


这是个好问题,up

#12


to whyglinux(山青水秀):
因为基类提供了一个访问 virtual 函数 f 的公共接口,通过这个公共接口可以在类域内访问包括私有成员在内的成员。
//通过这个接口可以在"类域"内访问private成员.这里可是在main中直接访问呀.

访问限定符限制的是通过类的成员访问。对于其它方式的成员访问
//同上,这里虽然是通过基类的public成员来访问,但是最终定位到的函数却是private的.
//而这是直接在main中访问的.为什么可以呢?

#13


no no ?

#14


不太懂,忘高人答疑!!

#15


我觉得好像是虚拟函数表中的指针越过了访问限定符

#16


经过研究,好像只是在编译期检查访问限定
因为pd在编译期是基类指针,因此通过了编译,运行期可能没有访问限定的检查
所以通过虚拟函数表中的指针调用了派生类中的私有函数

#17


访问限定只具有编译期语义

#18


编译器问题?还是C++语言本身的问题?这成了一个问题 :)

#19


难道还是C++编译器的问题
还个编译器试试

#20


晕,本来就可以这样用啊,跟编译器有什么关系
访问限定只具有编译期语义

#21


1    D d;
2    B *pd = &d;
3    pd->f(); 

行3访问的实际上是d的虚函数表,也就是说:对于重载的虚函数,private失去意义
这也许是C++设计者忽略的一个问题。

#22


众说纷纭,带星的怎么也不回答一下这个问题呀!反正我是说不清楚!我觉得c、c++要比java 难,那就是c,c++最难啦!