虚函数破坏私有访问
我最近在 IBM 站点。下面是示例代码
#include "iostream"
class B {
public:
virtual void f()
{
std::cout<<"\n In class B";
}
};
class D : public B {
private:
int i;
void f()
{
std::cout<<"\n In class D i = "<<i;
}
public:
D(int i_num):i(i_num)
{}
};
int main() {
D dobj(10);
B* bptr = &dobj;
D* dptr = &dobj;
// valid, virtual B::f() is public,
// D::f() is called
bptr->f();
// error, D::f() is private
//dptr->f();
}
我们现在可以调用 DI 的私有函数,想知道这是否会破坏 C++ 封装?
PS:请参阅虚拟功能中的虚拟功能访问部分。我不知道为什么粘贴时没有得到确切的链接。
I recently came across this article on IBM site. Below is the sample code
#include "iostream"
class B {
public:
virtual void f()
{
std::cout<<"\n In class B";
}
};
class D : public B {
private:
int i;
void f()
{
std::cout<<"\n In class D i = "<<i;
}
public:
D(int i_num):i(i_num)
{}
};
int main() {
D dobj(10);
B* bptr = &dobj;
D* dptr = &dobj;
// valid, virtual B::f() is public,
// D::f() is called
bptr->f();
// error, D::f() is private
//dptr->f();
}
We are now able to call private function of D.I wanted to know doesn't this break C++ encapsulation ?
P.S. : Please go to Virtual function access section in Virtual function. I do not know why I am not getting exact link when I do paste.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
调用
bptr->f()
在运行时根据bptr
指向的对象类型进行评估。在编译时,编译将bptr->f()
调用视为对B::f()
的调用,并且自B::f()< /code> 是
public
编译器不仅仅报告错误。仅在运行时才会评估实际的函数调用D::f()
。这并没有违反
封装
原则,这是C++的一个特性,称为运行时多态性
或动态多态性
你不能直接调用
dptr->f()
因为D::f()
是在Private
访问说明符下声明的,并且您无法从类外部访问私有声明的成员。The call
bptr->f()
is evaluated at run time depending on the type of objected pointed bybptr
. At compile time the compile sees thebptr->f()
call as call toB::f()
and sinceB::f()
ispublic
the compiler doesn't report only error. It is only at runtime that actual function callD::f()
is evaluated.This doesn't break the
Encapsulation
principle this is a feature of C++ calledRun-time Polymorphism
orDynamic Polymorphism
You cannot directly call
dptr->f()
becauseD::f()
is declared underPrivate
Access specifier and You cannot access privately declared members from outside the class.访问说明符是编译时构造,因此,编译器(显然)根据对象(或指针)的静态类型在编译时检测到任何违反访问规则的行为。这种违规行为无法在运行时检测到。
所以
bptr->f()
可以工作,因为编译器认为bptr
的 static 类型是B
其中定义了public
函数f()
,因此表达式bptr->f()
通过了编译器的测试。因此它有效。但是 dptr->f() 不起作用,因为 dptr 的静态类型是 D,有一个私有函数
f()
,因此代码甚至无法编译!现在是否破坏封装,是一个非常主观的问题,并且会得到主观的答案。这完全取决于人们如何定义它以及直接从中得出的论点。没有一个通用的定义。我个人的观点是,如果语言允许,那么(这意味着)根据 C++ 社区,它不会破坏封装,或者如果它破坏了封装,那么 C++ 允许它实现一些非常诺贝尔的东西(否则是不可能的)。否则,我会说它只是 C++ 的另一个错误功能,如下所示:
默认参数在参数列表中间?
Access-specifiers are compile-time construct, and so, the compiler detects any violation of access-rules at compile-time (obviously) based on the static type of the object (or pointer). Such violation cannot be detected at runtime.
So
bptr->f()
works, because the compiler sees that the static type ofbptr
isB
which has apublic
functionf()
defined, so the expressionbptr->f()
passes the compiler's test. Hence it works.But
dptr->f()
doesn't work, since the static type ofdptr
isD
which has a private functionf()
, hence the code wouldn't even compile!Now whether it breaks encapsulation or not, is a very subjective question and will receive subjective answers. It entirely depends on how one defines it and the arguments directly flows from it. There is no one universal definition. My personal opinion is, if the language allows it, then (it would imply that) according to the C++ community, it doesn't break encapsulation, or if it does, then C++ allows it so as to achieve something very nobel (which otherwise isn't possible). Otherwise, I would say its just yet another misfeature of C++ just like the following:
Default argument in the middle of parameter list?
这是设计使然。
B::f 是公开的。允许用户通过指向B的指针访问f。由于 f 是虚拟的,因此调用将被分派给派生类的 f。
但是D::f是私有的,你不能通过指针doD访问f。
It is by design.
B::f is public. User access of f via a pointer to B is allowed. Since f is virtual, the call would be dispatched to derived classes' f.
But D::f is private, you can't access f via a pointer do D.