求助:虚函数重写错误C3668
本帖最后由 eleqi 于 2013-03-22 10:10:25 编辑 请看下面三个简单的类
class base1
{
public:
class Delegate
{
public:
virtual void f1()=0;
protected:
virtual ~Delegate(){}
};
base1(){}
virtual ~base1(){}
};
class base2:public base1::Delegate
{
public:
class Delegate
{
public:
virtual void f2()=0;
protected:
virtual ~Delegate(){}
};
typedef Delegate base2Delegate;
base2(){}
virtual ~base2(){}
};
class child:public base2::Delegate
{
public:
// 显示重写base2::Delegate定义的接口,但2005不认。将f2改为f1或者将基类声明为base2::base2Delegate则正常编译。
virtual void f2() override;
};
int _tmain(int argc, _TCHAR* argv[])
{
return 0;
}
使用Visual Studio 2005 SP1编译出现:
overide.cpp(108) : error C3668: “child::f2”: 包含重写说明符“override”的方法没有重写任何基类方法
使用Visual Studio 2010编译一切正常。
求解决方法,是否有相关补丁什么的?非常感谢!
Visual?Studio?2005 C3668 显示重写虚函数
[解决办法]
帮你试了一下 g++-4.7 和 vs 2012 都没问题,目测编译器的问题了。
[解决办法]
楼主可以试试1楼提到的编译器,你所用的编译器编译不能通过,证明已经不属于规范之列的啦
[解决办法]
没用过 vs2005,我从 03 直接跳到 10 的。要是编译器的 bug,只能上官网找补丁了,不知道 ms 还维护 05 吗,这都 8 年了。
[解决办法]
很明显这里发生了非直觉的类型绑定。
class child : public base2::Delegate
child从base2::Delegate继承的时候,vs05先去查找了base2的基类,于是找到了base1中的Delegate这个名称,因为base2从base1::Delegate继承,所以这里Delegate这个名字在base2中是可见的。
#include <iostream>
#include <typeinfo>
using namespace std;
class A {};
class B : public A {};
int main(int argc, char **argv) {
cout << typeid(B::A).name() << endl;
return 0;
}
从上面的代码可以看出,派生类名::基类名 这一写法是没有问题的。
然后,vs05就认为child是从base1::Delegate中那个类继承的。于是你将f2改为f1就正确了。这里很明显违背我们的直觉了。
如果从base2::base2Delegate继承的话,因为base2的基类中没有base2Delegate这个类型,所以编译器必须去base2中查找这一类型。因为typedef在class Delegate之后,所以此时base2中的Delegate覆盖了base2基类名称Delegate,此时编译器认为child是从base2中那个Delegate继承的。f2声明为override也就正常了。
当然,这种违背直觉的绑定是语言和编译器都要尽量避免的。现在的编译器基本都可以正确处理这种情况了。
要在vs05中解决这个问题,我建议你将base1和base2中的Delegate都声明为private,然后分别为他们typedef一个名称。
class base1
{
class Delegate
{
public:
virtual void f1()=0;
protected:
virtual ~Delegate(){}
};
public:
typedef Delegate delegate_type;
base1(){}
virtual ~base1(){}
};
class base2 : public base1::delegate_type
{
class Delegate
{
public:
virtual void f2()=0;
protected:
virtual ~Delegate(){}
};
public:
// 如果没有这个typedef,base2::delegate_type绝对是不存在的
typedef Delegate delegate_type;
base2(){}
virtual ~base2(){}
};
class child:public base2::delegate_type
{
public:
virtual void f2() override;
};
这样子应该不会再发生那种错误了。当然,我手上没有vs05,不能测试,你自己测一下。有结果了顺便告诉我一声~