虚函数是否覆盖基类中同名的非虚函数?

时间:2012-05-07 19:48:57

标签: c++

以下标准是否符合要求?你能举出这个部分吗?

struct A
{
    virtual void func() = 0;
};

struct B
{
    void func(){}
};

struct C : public A, public B
{
    virtual void func(){ B::func(); }
};

我在VS2010中收到了一个奇怪的编译器警告,它在相同但更复杂的代码中指向派生最多类中的func声明:warning C4505: unreferenced local function has been removed。我不知道为什么编译器认为在类中声明的虚函数是本地的;但是我不能在一个更简单的例子中重复这个警告。

编辑:

我想出了一个警告的小责备案例。假设它与函数隐藏有关,我认为我走错了路。这是repro案例:

template<typename T>
struct C
{
    int GetType() const;
    virtual int func() const;   // {return 4;}  //  Doing this inline removes the warning <--------------
};

template<typename T>
int C<T>::GetType() const
{
    return 0;
}

template<>
int C<int>::GetType() const
{
    return 12;
}

template<typename T> 
int C<T>::func() const
{
    return 3; 
}

//  Adding the following removes the warning <--------------------
//  template<>
//  int C<int>::func() const
//  {
//      return 4;
//  }

我很确定这只是一个VS2010错误。

3 个答案:

答案 0 :(得分:3)

代码格式正确。 C::func会覆盖A::funcB::func是一个无关的功能。规范如下(10.3 / 2):

  

如果在类vf和类Base中声明虚拟成员函数Derived,直接或间接地从Base派生,则成员函数{{1声明同名,参数类型列表,cv-qualification和ref-qualifier(或缺少相同),vf也是虚拟的(无论是否为如此声明)并且它覆盖了111 Base::vf

Derived::vfBase::vf同名,C::func为虚拟,因此A::func会覆盖A::funcC::funcA::func无关;我不知道规范中有任何语言明确地解决了这种情况。

Visual C ++ 11 Beta编译器不会为此代码发出任何警告或错误。

答案 1 :(得分:1)

通常,链接器不能将虚函数作为死代码消除,因为它们的地址必须出现在vtable中。但是,如果struct C的vtable被确定为死代码(如果所有构造函数都是死代码,则可能会发生这种情况),那么也可以消除最后剩余的引用。

因为函数声明为inline,所以这个死代码删除优化不必等到链接时间;它可以由编译器完成。标准说(参见第7.1.2节):

  

内联函数应在每个使用它的翻译单元中定义,并且在每种情况下都应具有完全相同的定义(3.2)。 [注意:在定义出现在翻译单元之前,可能会遇到对内联函数的调用。 - 结束注释]如果函数的定义在第一次声明为内联之前出现在翻译单元中,则程序格式不正确。如果是具有外部链接的功能   在一个翻译单元中内联声明,应在其出现的所有翻译单元中内联声明;无需诊断。具有外部链接的inline函数在所有翻译单元中应具有相同的地址。 static函数中的extern inline局部变量始终引用同一对象。 extern inline函数体中的字符串文字是不同翻译单元中的同一对象。 [注意:出现在默认参数中的字符串文字不在内联函数的主体中,因为该表达式用于来自该内联函数的函数调用中。 - 结尾注释] extern inline函数体内定义的类型在每个翻译单元中都是相同的类型。

如果编译器可以确定该函数从未在转换单元中使用,则它知道任何使用该函数的转换单元必须包含其自己的相同定义,并将生成代码。因此它可以跳过代码生成,就像它根本没有外部链接一样。

然而,生成警告是完全没有意义的,因为会有大量的误报(当inline函数被使用并且在其他编译单元中生成代码时)。

答案 2 :(得分:0)

Let me google it for you.

  

function:已删除未引用的本地功能

     

给定的函数是本地的,在模块的主体中​​没有引用;因此,该功能是死代码。

     

编译器没有为这个死函数生成代码。

编译器静态地确定该函数未被使用,因此它不会为该函数生成代码并警告您有无用的代码。比通常的未使用的变量警告更复杂,但效果相同:死代码闻起来。