2009-06-06 81 views
3

我只是想知道是否是这个下面的代码块中的C++完全有效:这是有效的C++代码吗?

class A 
{ 
public: 
    virtual bool b() = 0; 
}; 

class B 
{ 
public: 
    virtual bool b() = 0; 
}; 

class C: public A, public B 
{ 
public: 
    virtual bool A::b() 
    { 
    return true; 
    } 

    virtual bool B::b() 
    { 
    return false; 
    } 
}; 

使用VS2008但它编译没有任何错误,在海湾合作委员会(MinGW的)3.4.5它给了我这样的错误:

cannot declare member function `A::b' within `C' 

在虚拟方法的实现线上。我很好奇这是否通常被认为是无效的,并且被C++标准禁止的代码(并且在VS中它因此起作用,这要归功于一些MS非标准化的魔术),或者只有GCC中的错误或不支持的语言功能。

回答

17

不,它是无效的。您不能像这样分开重写它们,因为它们具有相同的签名。

这里有一个guru of the week

+1

除此之外,非虚拟dtor是一个滴答作响的炸弹。但那不是问题。 :) – wilhelmtell 2009-06-06 21:43:05

1

限定名称A :: b为不允许作为类C.

1

它不被编译的一个成员的名称,由于具有相同功能名的父母。此外,你不会多次重载函数b。

如果你指的这个创建的虚拟表:

0(beginning of vtable) - A::b() -> B::b() 

你看,因为B类有相同的功能名称作为A类,它覆盖它,因此你现在有B :: B( )来覆盖(因为它仍然是纯粹的)。这是由于多重继承。编译器如何能够区分两者(它们具有相同的签名)?一般来说,这会失败,因为就像我刚才所说的那样,编译器不会做出决定,它应该告诉你存在一个问题。

它在VS上编译,但你试过运行它(包含在它实际创建的文件中)?有时,编译器很懒,不会在未使用的类上弹出错误。

+0

>编译器如何能够区分两者(它们具有相同的签名)? 但是,这也会发生,例如当你有多个基地的自己有一些共同的父母基地的类(你经常需要使用虚拟继承)。当然,编译器无法区分对常用方法的调用(如果我们不使用虚拟继承)并引发模糊调用错误,但可以通过dynamic_cast将该类实例添加到我们想要的基类中来轻松解决。是的,我在VS上使用它,它没有问题。 – RedDragCZ 2009-06-06 17:30:13

+0

@RedDragCZ:就我所使用的虚拟继承而言,只有在您需要从相同基类继承的子类的情况下。如果你看看litb链接,建议的解决方案是使用所谓的辅助类。 – tomzx 2009-06-06 18:11:24

0

正如一个供参考,VC只给出了错误,当您尝试使用b方法:

C:\temp\test.cpp(33) : error C2668: 'C::b' : ambiguous call to overloaded function 
     C:\temp\test.cpp(23): could be 'bool C::b(void)' 
     C:\temp\test.cpp(18): or  'bool C::b(void)' 
     while trying to match the argument list '(void)' 

而对于它的价值,科莫的编译器的行为类似,但有一个更加混乱的错误信息:

"C:\temp\test.cpp", line 33: error: no instance of overloaded function "C::b" 
      matches the argument list 
      object type is: C 
     bool z = c.b();