为什么纯虚拟机制不考虑继承函数?

Why pure virtual mechanism doesn't consider inherited functions?

本文关键字:继承 函数 不考虑 机制 虚拟 虚拟机 为什么      更新时间:2023-10-16

在问这个问题之前,我参考了这个老问题。但我仍有疑问。

struct B1 {
  virtual void fun () = 0;
};
struct B2 {
  void fun () { cout<<"B2::fun()n"; }
  void fun (int i) {}
};
struct D : B1, B2 {
  using B2::fun;  // This line doesn't help
};
int main ()
{
  B1 *pB1 = new D;  // Error: cannot allocate 'D' because 'B1::fun()' is abstract
  pB1->fun();
}
  1. c++标准不接受继承的成员函数来解析pure virtual机制的原因是什么?
  2. 为什么using关键字不能帮助解决这个错误?(编译器:linux- 64g++)
  3. using关键字B2::fun()B2::fun(int)使用哪个功能?(这一行没有歧义)
using B2::fun;

只允许您使用B2::fun方法,但由于B1是一个抽象类,您必须实现该类的纯虚函数fun才能创建其对象。

使用关键字B2::fun()或B2::fun(int)时使用哪个函数?(没有模棱两可的
那一行)

从ISO/IEC 14882:2003 (E) 7.3.3.12

当using声明将基类中的名称引入派生类作用域时,派生类中的成员函数覆盖和/或隐藏基类中具有相同名称和参数类型的成员函数(而不是冲突)。

[Example:
    struct B { 
        virtual void f(int);
        virtual void f(char); 
        void g(int); 
        void h(int);
    };
    struct D : B { 
        using B::f;
        void f(int);   // OK: D::f(int) overrides B::f(int);
        using B::g; 
        void g(char);  // OK
        using B::h; 
        void h(int);   // OK: D::h(int) hides B::h(int)
    };
    void k(D* p) {
        p->f(1);    //calls  D::f(int)
        p->f(’a’);  //calls  B::f(char)  // Notice the call being resolved
        p->g(1);    //calls  B::g(int)
        p->g(’a’);  //calls  D::g(char)
    }
— end example] 

[注意:两个using声明可能会引入带有的函数相同的名称和相同的参数类型。如果,为一个不合格的人打电话函数名,函数重载解析选择引入的函数通过这样的using声明,函数调用的形式是错误的。)

因此,在您提供的示例中根本没有歧义。根据传递的参数,可以决定调用方法

好的。我通过逻辑推理得到了第一个问题的答案。假设标准接受继承方法来解决pure virtual机制,那么对于普通的"虚"函数就会有歧义。

。假设B1::fun()是普通虚函数,那么在B1::fun()B2::fun()之间就会出现选择混淆。因此,至少对于virtual机制,最好避免考虑继承成员。

using仅调整名称查找过程。它不会将函数导入给定的作用域,也不会定义一个新函数。

因此,您只需要定义一个新的virtual覆盖。

我绝不是一个c++编程专家,但让我试一试:

  1. 我认为B1和B2,从编译器的角度来看,是两个完全不同的类,恰好在每个类中都有相同名称的方法。即使涉及到D的范围,编译器也没有理由使用B2的fun()实现来实现B1的fun()。(我想如果我们研究一下虚表机制,我们可能会弄清楚一些事情。从这里我们可以看出为什么B2::fun()对B1的fun()没有帮助

  2. using指令只是让符号"fun"在D的作用域中可见。"using"并没有给D类添加任何fun()实现(但是D类需要为B1::fun()实现)。

  3. 嗯…这里的"using"指令实际上并没有"使用"(或者我们说的"调用")这两者中的任何一个。"using"只是将名称引入D作用域(也就是使名称在D作用域中可见,类似于再次声明它们)。