【问题标题】:Disabling visual C++ virtual function override warning for certain methods禁用某些方法的可视 C++ 虚函数覆盖警告
【发布时间】:2015-11-13 01:01:54
【问题描述】:

我想在我们的代码库上启用 C4263 (Visual C++) 警告,但是,该警告给出了一些误报。我们想禁用警告,这样只有误报才会消失。我试图用一些通用代码来简化问题:

class B {
public:
    virtual void funcA();
    virtual void funcB();
};


class D : public B
{
    virtual void funcA(int);    
    virtual void funcB(int);
};

使用此代码,我们会收到以下警告: void D::funcA(int)' : 成员函数不覆盖任何基类虚成员函数 void D::funcB(int)' : 成员函数不覆盖任何基类虚成员函数

我想要实现的是禁用 funcA(或 funcB)的警告,并让类的其余部分受到它的影响。

我试过了

#pragma warning(push)        
#pragma warning(disable:4263)
 .
 .
 .
#pragma warning(pop)    

围绕 funcA 但这并不能解决问题。如果编译指示包含整个类,则两个警告都会消失。

有什么想法吗?

【问题讨论】:

  • 这不是误报。您正在使用 funcA(int) 重载,但没有覆盖 funcA()
  • 这是一个误报,因为我确实想要一个名为 funcA(int) 的方法。这不是 C++ 中的错误,根据具体情况,它可能是有意义的。我想说的是:程序员打算覆盖 funcB() 但未能这样做,因此必须显示警告。在 funcA 的情况下,程序员实际上想要添加一个 funcA(int)(因此无意覆盖 funcA()),因此他/她应该有可能告诉编译器“没关系,不要向我显示警告这个”
  • 不是您问题的答案,但您是否考虑过要求在您的编码标准中使用新的 C++11 override 关键字?在这种情况下,如果程序员真的打算重写 funcB() 并且已经使用override 表示了同样多的内容,他们将得到错误 C3668。
  • 仅仅因为编译器的行为不完全符合您的要求并不意味着它是误报或错误的。警告是 100% 正确的,应根据警告级别发出。如果您想摆脱警告,请在派生类中提供funcA() 的定义,并将其调用到基类中。编译器将(在大多数情况下)通过调度表中的条目优化调用。

标签: c++ visual-c++ virtual-functions overloading overriding


【解决方案1】:

鉴于它的文档,这是一个奇怪的错误:

https://msdn.microsoft.com/en-us/library/ay4h0tc9.aspx?f=255&MSPPError=-2147217396

'function' : 成员函数不覆盖任何基类 virtual 成员函数

类函数定义与虚函数同名 一个基类,但参数的数量或类型不同。这 有效地隐藏了基类中的虚函数。

最后一句很有意思,它提示我如果取消隐藏基类函数,警告将不再出现。

确实如此。以下代码不输出C4263:

class B {
public:
    virtual void funcA();
    virtual void funcB();
};

class D : public B
{
    using B::funcA;
    using B::funcB;
    virtual void funcA(int);    
    virtual void funcB(int);
};

警告似乎有点奇怪。如果您从基类指针调度,派生类隐藏哪些函数并不重要,因为使用基类指针时它们不会被隐藏。但答案就在这里!

这里实际发生的是编译器在猜测您的意图。因为您正在引入一个新的签名,这意味着您将使用派生指针(而不是基指针)使用多态或非多态调度。如果你不这样做,就不可能调用你的重载。编译器认为,如果您这样做,您将隐藏未覆盖的函数。这就是警告的内容。

举个例子:

struct Base
{
    virtual void DoThing(int)
    {
        std::cout << "INT  " << std::endl;
    }
};

struct Derived: public Base
{
    virtual void DoThing(char) // Add a function to handle chars
    {
        std::cout << "CHAR  " << std::endl;
    }
};

int main()
{
    Derived *derived = new Derived;
    Base *base = derived;

    base->DoThing(1);
    derived->DoThing(1);
    derived->DoThing('a');
}

这个输出:

INT CHAR 字符

其目的可能是添加一个重载来处理不同的情况,但它隐藏了所有现有的重载。鉴于语言规则,警告是正确的。警告并不准确,确定它没有被调用但它应该被调用的情况是微不足道的。它实际上与错误警告相反:)

要消除此警告,应使用 using 声明。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-22
    • 2012-02-19
    • 2015-06-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多