求助:虚函数重写错误C3668

eleqi 2013-03-22 10:03:10
请看下面三个简单的类
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编译一切正常。

求解决方法,是否有相关补丁什么的?非常感谢!
...全文
1373 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
tofu_ 2013-03-23
  • 打赏
  • 举报
回复
很明显这里发生了非直觉的类型绑定。 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,不能测试,你自己测一下。有结果了顺便告诉我一声~
eleqi 2013-03-23
  • 打赏
  • 举报
回复
非常感谢 ri_aje 和 tofu_ 的回复和详细的解释!在VS2005中可以正常编译了并且完全符合tofu_所说。
eleqi 2013-03-22
  • 打赏
  • 举报
回复
非常感谢ri_aje的耐心测试和回复! 这样非得绕个弯才能正常编译很不爽,求教是否有个补丁什么的来解决此问题
ri_aje 2013-03-22
  • 打赏
  • 举报
回复
引用 2 楼 eleqi 的回复:
非常感谢ri_aje的耐心测试和回复! 这样非得绕个弯才能正常编译很不爽,求教是否有个补丁什么的来解决此问题
没用过 vs2005,我从 03 直接跳到 10 的。要是编译器的 bug,只能上官网找补丁了,不知道 ms 还维护 05 吗,这都 8 年了。
ri_aje 2013-03-22
  • 打赏
  • 举报
回复
帮你试了一下 g++-4.7 和 vs 2012 都没问题,目测编译器的问题了。
_sunshine 2013-03-22
  • 打赏
  • 举报
回复
引用 2 楼 eleqi 的回复:
非常感谢ri_aje的耐心测试和回复! 这样非得绕个弯才能正常编译很不爽,求教是否有个补丁什么的来解决此问题
楼主可以试试1楼提到的编译器,你所用的编译器编译不能通过,证明已经不属于规范之列的啦

64,644

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧