【问题标题】:Private virtual function in derived class [duplicate]派生类中的私有虚函数[重复]
【发布时间】:2012-11-17 03:00:42
【问题描述】:

可能重复:
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. 即使它是私有的,它也可以调用派生类函数。这怎么可能?

现在,如果我将继承访问说明符从 public 更改为 protected/private,我会收到编译错误:

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

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

【问题讨论】:

    标签: c++


    【解决方案1】:

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

    【讨论】:

    • 我想他想知道为什么访问说明符会这样工作,而不是知道错误的根源是什么。
    【解决方案2】:

    在第一种情况下,访问检查是在调用所通过的静态类型上完成的(因为它总是这样做的)。 *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
    }
    

    ——结束示例]

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

    请特别记住“成员函数在定义它的类中的访问(上例中的 D)通常是未知的”。通常,在您的示例中调用b-&gt;doSomething(); 的那一点,编译器可能根本不知道derived(或child),更不用说对derived::doSomething() 的访问是否是私有的了。

    【讨论】:

      【解决方案3】:

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

      在第二种情况下,private 访问说明符导致基类的成员不会暴露给派生类的用户,这实际上使派生类无用。

      【讨论】:

      • OP说的很清楚可以调用派生类函数。根据给定的示例,您对 you can call base's DoSomething as it is public 的推测是错误的,并且不是问题 1 的答案。
      猜你喜欢
      • 2020-07-16
      • 2015-10-24
      • 2021-10-22
      • 1970-01-01
      • 2018-05-11
      • 2016-10-08
      • 2019-06-07
      • 2011-08-23
      相关资源
      最近更新 更多