标准中的哪个位置转发到这些情况下所需的基类?

时间:2010-05-29 02:21:02

标签: c++ override multiple-inheritance pure-virtual

可能更好的是:为什么标准要求在这些情况下转发到基类? (是的,是的,为什么? - 因为。)

class B1 {
public:
    virtual void f()=0;
};
class B2 {
public:
    virtual void f(){}
};
class D : public B1,public B2{
};
class D2 : public B1,public B2{
public:
    using B2::f;
};
class D3 : public B1,public B2{
public:
    void f(){
        B2::f();
    }
};
D d;
D2 d2;
D3 d3;

MS给出:

sourceFile.cpp
sourceFile.cpp(24) : error C2259: 'D' : cannot instantiate abstract class
        due to following members:
        'void B1::f(void)' : is abstract
        sourceFile.cpp(6) : see declaration of 'B1::f'
sourceFile.cpp(25) : error C2259: 'D2' : cannot instantiate abstract class
        due to following members:
        'void B1::f(void)' : is abstract
        sourceFile.cpp(6) : see declaration of 'B

,类似于MS编译器。

可能购买第一个案例,D。但是在D2-f中,使用声明定义了明确,为什么编译器不足以填写vtable?

标准中的哪种情况定义了这种情况?

添加回复

关于我接受的以下答案:

为什么这在规范中似乎不是错误? - 如果一个具有一系列非虚拟f()的继承层次结构,则派生类中的使用由使用语句确定,并且一个将基类中的f的decl更改为virtual然后可以更改哪个f在派生类中调用,使用using语句来选择它们的f。这是一个我不知道的c ++“陷阱”。它可能是语言的一部分,但这种“远距离行动”让我感到不安,对我来说似乎违反了某种正确/维护原则(我现在还不能完全表达)。

但我可以举个例子:

#include <iostream>
using std::cout;


namespace NonVirtual_f{

class C0 {
public:
    void f(){cout<<"C0::f()"<<'\n';}
};

class C1 : public C0{
public:
    void f(){cout<<"C1::f()"<<'\n';}
};

class C2 : public virtual C1{
public:
    void f(){cout<<"C2::f()"<<'\n';}
};

class D3 : public virtual C1, public C2{
public:
    using C1::f;
};


}//namespace NonVirtual_f

namespace Virtual_f{


class C0 {
public:
    virtual void f(){cout<<"C0::f()"<<'\n';}
};

class C1 : public C0{
public:
    void f(){cout<<"C1::f()"<<'\n';}
};

class C2 : public virtual C1{
public:
    void f(){cout<<"C2::f()"<<'\n';}
};

class D3 : public virtual C1, public C2{
public:
    using C1::f;
};



}//namespace Virtual_f




int main(int argc,const char* const*argv){

    NonVirtual_f::D3 nv3;
    nv3.f();

    Virtual_f::D3 v3;
    v3.f();

    return 0;    
} 

输出:

C1::f()
C2::f()

所有改变的是C0中f的虚拟性。特别是一旦选择了基类中f的非虚拟性,如果某些派生类(通常一个 不能 知道),就无法在没有维护问题的情况下进行更改在上面的例子中已经“覆盖”了。

如果您反击“嗯,不要在非虚拟案例中覆盖那种方式”,我同意这是不好的做法,但这似乎不仅仅是这样。对我来说,语言应该:

不允许在NonVirtual :: D3中使用(目前不可能,因为可能会有其他重载的f引入[除非在功能案例中使用允许的签名])

完全禁止使用函数语句并强制转发

在所有情况下都使用了实际覆盖

允许函数的一些语法声明(基本上是一个函数使用),如:

void f(*signature*) = C2::f;

我到底错过了什么? 有人能想出一个方案来澄清标准中这个选择的“原因”吗?

1 个答案:

答案 0 :(得分:3)

C ++标准在§10.3/ 2中说:

  

成员查找规则(10.2)用于确定派生类范围内虚函数的最终覆盖,但忽略 using-declarations 引入的名称。

因此,即使您使用using B2::f;B2::f()带入派生类,也不会将其视为覆盖B1::f()

因此,D2是抽象的,因为§10.4/ 4:

  

如果一个类包含或继承了至少一个纯虚函数,那么该类是抽象的,最终的覆盖是纯虚函数。