虚拟功能打破私人访问

时间:2011-04-16 09:17:02

标签: c++ virtual

我最近在IBM site上看过这篇文章。以下是示例代码

#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();
}

我们现在能够调用D.的私有函数了。我想知道这不是破解C ++封装吗?

P.S。 :请转到虚拟功能中的虚拟功能访问部分。我不知道为什么在粘贴时我没有得到确切的链接。

3 个答案:

答案 0 :(得分:6)

在运行时评估调用bptr->f(),具体取决于bptr指向的对象类型。在编译时,编译将bptr->f()调用视为对B::f()的调用,并且由于B::f()public,编译器不会仅报告错误。只有在运行时才会评估实际的函数调用D::f()

这不违反Encapsulation原则这是C ++的一个名为Run-time PolymorphismDynamic Polymorphism

的功能

您无法直接调用dptr->f(),因为D::f()Private访问说明符下声明,您无法从类外访问私有声明的成员。

答案 1 :(得分:2)

这是设计的。

B :: f 是公开的。允许用户通过 B 指针访问 f 。由于 f 是虚拟的,因此调用将被分派到派生类' f

但是 D :: f 是私密的,您无法通过指针访问 f D

答案 2 :(得分:2)

Access-specifiers是编译时构造,因此,编译器会在编译时(显然)根据对象(或指针)的 static 类型检测到任何违反访问规则的行为。在运行时无法检测到此类违规。

所以bptr->f()有效,因为编译器发现bptr静态类型是B,其public函数{{1}已定义,因此表达式f()通过了编译器的测试。因此它有效。

但是bptr->f()不起作用,因为dptr->f()静态类型是dptr,它具有私有函数D,因此代码甚至不会编译!

现在它是否打破封装,是一个非常主观的问题,并会得到主观的答案。它完全取决于人们如何定义它以及直接从它流出的参数。没有一个通用的定义。我的个人意见是,如果语言允许的话,那么(这意味着)根据C ++社区,它不会破坏封装,或者如果确实如此,那么C ++允许它实现非常诺贝尔(否则是不可能的)。否则,我会说它只是另外一个C ++的错误,如下所示:

Default argument in the middle of parameter list?