none
VC++项目从vs2005迁移到vs2008时函数覆盖CString和LPCTSTR返回值出现错误 RRS feed

  • 问题

  • 操作系统Windows Server 2003,在VS2005中程序运行正常,但是迁移到VS2008就出现了编译错误。具体的,
    基类A有一个如下的方法
    virtual LPCTSTR GetName (LANGID lang);
    子类B覆盖该方法,方法标签为
    const CString    RepNavReport::GetName(const LANGID nlID/*= 0 */);
    在VS2008下编译时会遇到如下的错误提示:
    error C2555: 'B::GetName': overriding virtual function return type differs and is not covariant from 'A::GetName'。

    但是在VS2005下这个是正常编译的。不知道VS2008有什么不同的地方。
    2008年12月11日 7:19

答案

  • VS2005对标准的支持没有VS2008好,它错误的将f(int)和f(const int)当成了不同的函数原型。

     

    默认VS2005会对前面的代码报如下的warning

    warning C4301: 'B::fun': overriding virtual function only differs from 'A::fun' by const/volatile qualifier
            sourceFile.cpp(12) : see declaration of 'A::fun'

     

    如果你将代码中的B::fun(const int)改成B::fun(int),VS2005就会给出正确的报错信息

    error C2555: 'B::fun': overriding virtual function return type differs and is not covariant from 'A::fun'
            sourceFile.cpp(12) : see declaration of 'A::fun'

     

    PS:你会发现VS2008中已经没有warning C4301了

    2008年12月12日 4:39

全部回复

  • 你的代码不符合C++标准,所以报错。

    在C++中,函数参数前面的const和默认参数都不属于函数原型的一部分,所以你子类和父类的GetName的声明除了返回值之外都是相同的。在这种情况下,如果基类的方法不是virtual,那么子类的声明就会覆盖(hide)父类的声明。如果基类的方法是virtual的,就会成为重写(override),因此两者的返回值必须相同或者covariant,就是说父类返回Base&,子类返回Derived&这种(具体参见C++03, 10.3/5)

     

    Code Snippet

    class A

    {

    public:

    //virtual

    int fun(const int);

    };

    class B:public A

    {

    public:

    long fun(int);

    };

    int main()

    {

    }

     

     

    2008年12月11日 17:44
  • 你说的对。但是,我的这个工程在VS2005中的确可以编译通过。当然如果我新建一个简单的工程,出现类似这种函数覆盖(override)并且返回值分别是LPCTSTR和CString,那么编译也是会报错的。我不知道是不是有什么特殊的设置让我原来的工程能够编译通过。
    2008年12月12日 1:57
  • 将编译警告级别设为最高,所有的警告都应当被看作潜在错误而被修正。

    2008年12月12日 2:15
  • VS2005对标准的支持没有VS2008好,它错误的将f(int)和f(const int)当成了不同的函数原型。

     

    默认VS2005会对前面的代码报如下的warning

    warning C4301: 'B::fun': overriding virtual function only differs from 'A::fun' by const/volatile qualifier
            sourceFile.cpp(12) : see declaration of 'A::fun'

     

    如果你将代码中的B::fun(const int)改成B::fun(int),VS2005就会给出正确的报错信息

    error C2555: 'B::fun': overriding virtual function return type differs and is not covariant from 'A::fun'
            sourceFile.cpp(12) : see declaration of 'A::fun'

     

    PS:你会发现VS2008中已经没有warning C4301了

    2008年12月12日 4:39
  • to vbvan
    你的说法完全正确,我也发现这个问题了。但是有没有办法使得VS2008下不用改代码也能编译通过(修改代码太复杂了)?
    2008年12月12日 8:00
  • 建议你还是修改代码,VS2005虽然能够编译通过,但是运行期的行为是未知的。凑巧sizeof(CString)==4,所以看上去行为是对的。不过很有可能你通过基类指针调用B::GetName的时候,返回的CString不会被析构,从而产生内存泄露
    2008年12月12日 16:59