2011-04-11 71 views
2

在问之前,我已经参考了这个older question。但我仍然有疑问。为什么纯虚拟机制不考虑继承函数?

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-64 g ++)
  3. 哪个函数用于using关键字,B2::fun()B2::fun(int)? (有该行没有歧义)

回答

0

哪个函数用于使用关键字,B2 ::乐趣()或B2 ::乐趣(INT)?(没有 歧义的
该行)

从ISO/IEC 14882:2003(E)7.3.3.12

当使用声明从带来的名字基类转换为派生类作用域,派生类中的成员函数会覆盖和/或隐藏基类中具有相同名称和参数类型的成员函数(而不是冲突)。

[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] 

[注:2使用-声明可能与 相同的名称和相同的参数类型介绍的功能。如果对于一个不合格的 函数名称的调用,函数重载决议选择由这样的使用声明引入的功能 ,函数调用是格式不正确的。 ]

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

2
using B2::fun; 

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

+0

由于B1是虚拟的,所以必须在D中定义方法。或者,您可以使用B2:B1,然后使用D:B2。 – Jess 2011-04-11 05:37:08

+0

@Jess:两者都可以工作,请检查RageD的答案,它解释了它是如何工作的。 – 2011-04-11 05:45:21

0

好的。尽管我只是基于逻辑推理得出了第一个答案。假设,标准接受继承的方法来解决pure virtual机制,那么对于普通的“虚拟”功能将存在不明确性。

即即假设B1::fun()是正常的虚拟函数,那么B1::fun()B2::fun()之间会有选择混淆。所以最好避免考虑遗传成员,至少对于virtual机制。

0

using只调整名称查找过程。它不会将函数导入给定范围,或者定义一个新函数。

所以,你只需要定义一个新的覆盖virtual

0

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

  1. 我认为,B1和B2,从编译器的角度来看,是碰巧有一个方法,两个完全不同的类每个中都有相同的名字。即使涉及到D的范围,编译器也没有理由使用B2的fun()实现来实现B1中的fun()。我们可以看到为什么B2 :: fun()对B1的乐趣没有帮助()。)

  2. “using “指令只是使符号”有趣“在D的范围内可见。 “使用”不会将任何fun()实现附加到D类(但是D需要针对B1 :: fun())的实现。

  3. 嗯......“使用”这里指令实际上并没有“使用”(或者说“援引”)二者中的任何。 “使用”只是向D的范围引入了名称(在D范围内使名称可见,类似于再次声明它们)。