6

是否符合以下标准?你能引用那个部分吗?

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. 我不知道为什么编译器认为类中声明的虚函数是本地的;但是我无法在更简单的示例中重现该警告。

编辑:

我想出了一个用于警告的小型复制案例。我认为我走错了路,假设它与功能隐藏有关。这是复制案例:

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 错误。

4

3 回答 3

3

代码格式正确。 C::func覆盖A::func. B::func是一个不相关的函数。规范读取(10.3/2):

如果在一个类和一个类vf中声明了一个虚成员函数,直接或间接地派生自一个与被声明,然后也是虚拟的(无论它是否被声明)并且它覆盖 111 。BaseDerivedBasevfBase::vfDerived::vfBase::vf

C::func与 同名A::func并且A::func是虚拟的,因此C::func覆盖A::func. B::func与 无关A::func;我不知道规范中有任何语言明确解决了这种情况。

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

于 2012-05-07T19:54:00.617 回答
1

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

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

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

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

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

于 2012-05-07T19:58:22.510 回答
0

让我为你谷歌它。

function: 未引用的本地函数已被删除

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

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

编译器静态确定该函数未被使用,因此它没有为该函数生成代码并警告您有无用的代码。比通常的未使用变量警告涉及更多,但效果大致相同:死代码气味。

于 2012-05-07T19:56:09.427 回答