虚函数是否覆盖基类中同名的非虚函数
Does a virtual function override a non-virtual function of the same name in a base class?
以下标准是否符合?你能引用这个部分吗?
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错误。
代码格式正确。 C::func
将覆盖A::func
。 B::func
是一个不相关的函数。 规范如下 (10.3/2(:
如果一个虚成员函数
vf
是在类Base
和类Derived
中声明的,直接或间接派生自Base
,则成员函数vf
与声明Base::vf
具有相同的名称、参数类型列表、cv-限定符和ref限定符(或不存在相同(,则Derived::vf
也是虚拟的(无论它是否如此声明(,并且它覆盖了111Base::vf
。
C::func
与A::func
同名,A::func
是虚拟的,因此C::func
覆盖A::func
。 B::func
与A::func
无关;我不知道规范中是否有任何语言明确解决了这种情况。
Visual C++ 11 Beta 编译器不会为此代码发出任何警告或错误。
链接器不能将虚拟函数作为死代码消除,因为它们的地址必须出现在 vtable 中。 但是,如果 struct C
的 vtable 被确定为死代码(如果所有构造函数也是死代码,则可能会发生这种情况(,那么最后一个剩余的引用也可以被消除。
因为函数被声明为inline
,所以这个死代码删除优化不必等到链接时间;它可以由编译器完成。 该标准说(见第7.1.2节(:
内联函数应在使用它的每个翻译单元中定义,并且在每种情况下都应具有完全相同的定义 (3.2(。 [ 注意:在内联函数的定义出现在翻译单元中之前,可能会遇到对内联函数的调用。 — 尾注 ] 如果函数的定义出现在翻译单元中,然后才将其第一次声明为内联,则程序格式不正确。 如果具有外部链接的功能是 在一个翻译单元中声明内联,应在出现它的所有翻译单元中声明内联;无需诊断。 具有外部链接的
inline
职能在所有翻译单元中应具有相同的地址。extern inline
函数中的static
局部变量始终引用同一对象。extern inline
函数主体中的字符串文本是不同翻译单元中的同一对象。[ 注意:默认参数中出现的字符串文本不在内联函数的主体中,仅仅是因为该表达式用于该内联函数的函数调用中。 — 尾注 ] 在extern inline
函数主体中定义的类型在每个翻译单元中都是相同的类型。
如果编译器可以确定该函数从未在此翻译单元中使用,则它知道使用该函数的任何翻译单元都必须包含其自己的相同定义,并将生成代码。 因此,它可以跳过代码生成,就像它根本没有外部链接一样。
但是,生成警告是完全没有意义的,因为将存在大量误报(当inline
函数被 ODR 使用并在其他编译单元中生成代码时(。
让我为你谷歌一下。
编译器静态确定该函数给定的函数是本地的,
function
:已删除未引用的本地函数不在模块主体中引用;因此,该函数是死代码。
编译器没有为此死函数生成代码。
未使用,因此它不会为该函数生成代码,并警告您您有无用的代码。比通常未使用的变量警告更复杂一些,但效果大致相同:死代码闻起来。
- 基类中的函数名称解析
- 如何通过派生类函数更改基类中的向量
- 继承:构造函数,初始化C++11中基类的类C数组成员
- 使用基类指针创建对象时,缺少派生类析构函数
- 如果基类包含双指针成员,则派生类的构造函数
- C++ 继承:将子类传递给需要基类的函数并获取子类行为
- 继承和友元函数,从基类访问受保护的成员
- 使用子类覆盖基类中定义的函数
- 如何基于模板化类的基类专门化成员函数
- 基类中的默认析构函数禁用子类中的移动构造函数(如果有成员)
- 使用基类指针调用基类的值构造函数的语法是什么?
- C++重载函数,一个采用基类的参数,另一个采用派生类的参数
- 如何在基类指针向量的元素上应用重载的多态函数
- 如何在不使用指针的情况下将派生类的对象作为参数传递给基类中的函数?
- 被覆盖的函数不会反映在基类中,这是正常行为吗?
- 在初始化列表之外手动调用基类的构造函数
- 重写打印函数而不是覆盖基类
- C++17 使用驱动类常量作为基类构造函数的参数来初始化基类构造函数
- C++虚拟函数:基类函数是调用的,而不是派生的
- 虚拟函数-基类指针