2012-05-07 82 views
6

以下标准是否符合?你能引用该部分吗?虚拟函数是否覆盖基类中同名的非虚函数?

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

struct B 
{ 
    void func(){} 
}; 

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

我得到的指向func的声明在派生类最多相当于但是更复杂的代码在VS2010一个奇怪的编译器警告: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

“等价但更复杂的代码......不能在更简单的示例中重新报警”。那么他们可能不等同。 –

+0

上面的代码不会产生您在VS2010中提到的警告。它没有任何语义错误,但设计的选择对我来说很奇怪。 – AJG85

+0

我仍在试图弄清楚如何重新制作警告 - 我将在/如果我这样做时进行编辑。 – David

回答

3

该代码格式良好。 C::func覆盖A::funcB::func是一个不相关的功能。该规范读取(10.3/2):

如果虚拟成员函数vf在类Base和在类Derived被声明,直接或间接从Base,成员函数vf具有相同名称,参数导出-type-list,cv-qualification和ref-qualifier(或缺少相同的)作为Base::vf被声明,那么Derived::vf也是虚拟的(不论它是否被声明)并且它覆盖111 Base::vf

C::func具有相同的名称作为A::funcA::func是虚拟的,因此C::func覆盖A::funcB::funcA::func无关;我不知道规范中是否有明确说明该场景的语言。

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

0

Let me google it for you.

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

给定的功能是局部的,在所述模块的本体未引用;因此,该功能是死码。

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

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

+1

我做过谷歌它,谢谢。这仅适用于“本地”功能。我什至不知道如何编译器会知道一个函数是否未使用,它必须是链接器,在这种情况下,它将是一个链接器警告。你曾经在课堂上看到关于一个未使用的虚拟功能的警告吗? EVER? – David

+0

@Dave:该函数被(隐式)声明为“inline”,这意味着如果任何其他编译单元使用它,它将不得不出现在其他编译单元中。所以编译器不必担心外部引用该函数,它可以将其视为本地。 –

+0

啊。有趣。但是,它是虚拟的 - 如果它被称为或不在该级别上,它真的可以解决吗?实际上,我回到了以前的立场:你有没有在你自己的代码中看到这样的警告,例如一个带有访问器或增变器的模板类,它没有被调用,并且是内联的,因为它在模板类中?这是相同的情况吗? – David

1

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

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

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

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

但是,生成警告是毫无意义的,因为会出现大量的误报(当其他编译单元中的函数使用odod-and生成代码时)。

相关问题