纯虚函数=未引用的局部变量警告

Pure virtual function = unreferenced local variable warning

本文关键字:局部变量 警告 引用 函数      更新时间:2023-10-16

给即将到来的读者的结论

函数内部的抽象类不是一个好主意(至少在VS2013 Update 3中,它可能是一个bug)。参见编辑3和Leon的回答了解更多细节。

原始文章

我从来没有收到过这个警告,我不知道发生了什么。我将我的项目设置为将警告视为错误。

class BaseFoo
{
public:
    virtual ~BaseFoo() = default;
    virtual void doIt(const std::string& x, const uint8 y) = 0;
}; // class BaseFoo
class Foo : public BaseFoo
{
    void doIt(const std::string& x, const uint8 y) override
    {
    }
}; // class Foo
class Executer
{
public:
    void doIt(BaseFoo* f)
    {
        f->doIt("hello", 0);
        f->doIt("world", 1);
    }
}; // class Executer
Executer exec;
BaseFoo* f = new Foo();
exec.doIt(f);
delete f;

MSVC (VS2013 Update 3)说:

警告C4101: 'BaseFoo::doIt':未引用的局部变量

一个纯虚函数怎么可能是"未引用的局部变量"?我一定是一个土豆还是我发现了一个编译器错误?

编辑:

如果我将代码放入Foo::doIt函数(例如:std::cout),没有任何变化。

如果我将BaseFoo::doIt更改为非纯的,只是一个"简单的"虚函数,它不做任何事情,警告消失。

编辑2:可编译的单个文件

所以我"复制粘贴"代码到一个可编译的主函数(我知道,argv, argc, meh…:))。我还复制了项目设置:

  • 警告级别3:/W3
  • 将警告视为错误:Yes/WX
  • 优化:Disabled/Od
  • 最小重建:Enabled/Gm
  • RTTI: No/GR-

代码如下:

#include <iostream>
#include <string>
typedef unsigned __int8 uint8;
int main()
{
    class BaseFoo
    {
    public:
        virtual ~BaseFoo() = default;
        virtual void doIt(const std::string& x, const uint8 y) = 0;
    }; // class BaseFoo
    class Foo : public BaseFoo
    {
        void doIt(const std::string& x, const uint8 y) override
        {
            std::cout << x << y;
        }
    }; // class Foo
    class Executer
    {
    public:
        void doIt(BaseFoo* f)
        {
            f->doIt("hello", 0);
            f->doIt("world", 1);
        }
    }; // class Executer
    Executer exec;
    BaseFoo* f = new Foo();
    exec.doIt(f);
    delete f;
    return 0;
}

编辑3:

对于Leon来说,如果我将类从主函数中移出,警告就会消失。然而,我不知道为什么我错了,如果我在主函数内定义这些类。所以下面的代码编译时没有任何警告:

#include <iostream>
#include <string>
typedef unsigned __int8 uint8;
class BaseFoo
{
public:
    virtual ~BaseFoo() = default;
    virtual void doIt(const std::string& x, const uint8 y) = 0;
}; // class BaseFoo
class Foo : public BaseFoo
{
    void doIt(const std::string& x, const uint8 y) override
    {
        std::cout << x << y;
    }
}; // class Foo
class Executer
{
public:
    void doIt(BaseFoo* f)
    {
        f->doIt("hello", 0);
        f->doIt("world", 1);
    }
}; // class Executer
int main()
{
    Executer exec;
    BaseFoo* f = new Foo();
    exec.doIt(f);
    delete f;
    return 0;
}

我认为问题在于您将类声明为局部函数,没有机会让任何人继承BaseFoo并覆盖其doIt()方法。

试试这个:

class BaseFoo
{
public:
    virtual ~BaseFoo() = default;
    // As a pure-virtual is intrinsically a "do-nothing"
    // the name of the parameters doesn't matter for the compiler
    virtual void doIt(const std::string& /* x */, const uint8 /* y */) = 0;
}; // class BaseFoo
class Foo : public BaseFoo
{
    // Other compilers are even Nazi-er than VS and emit a whinge... 
    // errr, pardon my mouth, I meant to say...
    // a warning for any unused parameter ('g++ -Wall', I'm looking at you)        
    // The same works too for keeping them happy and silent.
    void doIt(const std::string& /* x */, const uint8 /* y */) override
    {
    }
}; // class Foo