派生类中的私有虚函数

时间:2012-11-29 04:45:46

标签: c++

  

可能重复:
  C++: overriding public\private inheritance

class base {
public:
  virtual void doSomething() = 0;
};

class derived : public base {
private:   // <-- Note this is private

  virtual void doSomething()
  { cout << "Derived fn" << endl; }
};

现在,如果我执行以下操作:

base *b = new child;
b->doSomething();    // Calls the derived class function even though that is private

问题:

  1. 即使它是私有的,它也可以调用派生类函数。这怎么可能?
  2. 现在,如果我将继承访问说明符从public更改为protected / private,我会收到编译错误:

    'type cast' : conversion from 'Derived *' to 'base *' exists, but is inaccessible
    

    注意:我知道继承访问说明符的概念。所以在第二种情况下,因为它是派生私有/受保护的,所以它是不可访问的。但我想知道第一个问题的答案。任何意见都将受到高度赞赏。

3 个答案:

答案 0 :(得分:6)

访问控制在编译时实现,而不是在运行时实现,而多态(包括使用虚函数)是运行时功能。

答案 1 :(得分:6)

在第一种情况下,访问检查在完成调用的静态类型上完成(因为它总是完成)。 *b的静态类型为base,在这种情况下,doSomething()public

C ++ 03 11.6“访问虚拟功能”说:

  

虚拟功能的访问规则(第11节)由确定   它的声明并且不受函数规则的影响   以后覆盖它。 [实施例:

class B {
public:
    virtual int f();
};

class D : public B {
private:
    int f();
};

void f()
{
    D d;
    B* pb = &d;
    D* pd = &d;

    pb->f(); //OK:B::f()is public,
             // D::f() is invoked
    pd->f(); //error:D::f()is private
}
     

-end example]

     

使用表达式的类型在调用点检查访问,该表达式用于表示调用成员函数的对象(上例中为B *)。成员函数在定义它的类中的访问(上例中的D)通常是未知的。

请特别注意“成员函数在其定义的类中的访问权限(上例中的D)通常是未知的”。通常,在您的示例中调用b->doSomething();时,编译器可能根本不了解derived(或child),更不用说是否访问{ {1}}是私有的。

答案 2 :(得分:0)

私有函数意味着对外部世界和派生类隐藏。虽然您要覆盖父级DoSomething的访问说明符并将其设为私有,但您要实例化基类;所以在第一种情况下,你可以调用base的DoSomething,因为它是公开的。如果要阻止派生自派生类的人员,可以使用此方案。

在第二种情况下,private访问说明符导致基类的成员不会向派生类的用户公开,这有效地使派生类无用。