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

C++ 纯虚函数=未引用的局部变量警告,c++,C++,即将出版的读者的结论 函数中的抽象类不是一个好主意(至少在VS2013更新3中,它可能是一个bug)。有关更多详细信息,请参见编辑3和Leon的答案 原创帖子 我从来没有收到过这样的警告,我也不知道发生了什么。我将项目设置为将警告视为错误 class BaseFoo { public: virtual ~BaseFoo() = default; virtual void doIt(const std::string& x, const uint8 y) = 0; };

即将出版的读者的结论

函数中的抽象类不是一个好主意(至少在VS2013更新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更新3)表示:

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

纯虚函数如何可以是“未引用的局部变量”?我一定是个马铃薯或者我发现了一个编译器错误

编辑:

如果我将代码放入
Foo::doIt
函数(例如std::cout),则不会发生任何变化

如果我将
BaseFoo::doIt
更改为非纯的,只是一个“简单”的虚拟函数,它什么也不做,警告就会消失

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

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

  • 警告级别3:/W3
  • 将警告视为错误:是/WX
  • 优化:禁用/Od
  • 最小重建:已启用/Gm
  • RTTI:否/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;
}
#包括
#包括
typedef unsigned__int8uint8;
int main()
{
BaseFoo类
{
公众:
virtual~BaseFoo()=默认值;
虚空doIt(const std::string&x,const uint8 y)=0;
};//类BaseFoo
Foo类:公共BaseFoo
{
void doIt(const std::string&x,const uint8 y)重写
{
std::cout doIt(“世界”,1);
}
};//类执行器
执行者执行者;
BaseFoo*f=newfoo();
执行董事doIt(f);
删除f;
返回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;
}
#包括
#包括
typedef unsigned__int8uint8;
BaseFoo类
{
公众:
virtual~BaseFoo()=默认值;
虚空doIt(const std::string&x,const uint8 y)=0;
}; // BaseFoo类
Foo类:公共BaseFoo
{
void doIt(const std::string&x,const uint8 y)重写
{
std::cout doIt(“世界”,1);
}
}; // 类执行器
int main()
{
执行者执行者;
BaseFoo*f=newfoo();
执行董事doIt(f);
删除f;
返回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

无法在VS2013中重新编程,明显的变化是将位放在
main
的末尾。请发布一个完整的可编译示例,并说明您使用的是哪个版本的VS。使用此代码,我只在/W4处获得x和y的“未引用形式参数”,我希望(MSVC 2013)在这里是相同的,在vs2015No中没有复制。不是一个测试项目。一个简单的.cpp文件,包含所有声明和一个文件中的所有内容(包括main)-然后您的问题将显示出来。我可以用
main
中的所有内容来确认这一点。在我看来这是个bug,因为
BaseFoo::doIt
实际上是在
Executer::doIt
中使用的。函数类的本地都是
MCVE
请求的一部分。实际上这就是问题所在。如果我从主函数中移出这些类,警告就会消失。然而,我认为这应该是可行的,因为Foo继承自BaseFoo。这应该是一个bug吗?@csisy我认为你不应该把这个警告标记为bug。如果抽象类是局部的,那么它就没有多大意义。抽象类的引入是为了鼓励子类化它们,如果它们隐藏在函数中,这是不可能的。这并不意味着它不是一个bug。这只是一种只能由几乎没有用处的代码触发的bug。我仍然认为这并不违反标准。如果我想要一个本地
BaseFoo
基类并从中继承多个
Foo
s,该怎么办?用于测试目的。没关系,我可以将这些类从函数中移出,但我认为这应该也可以。无论如何,你已经解决了这个问题,明白了吗如果我将这些类保留在主函数中(如在我的OP中),问题仍然存在,警告是关于doIt函数本身的,而不是它的参数。但是谢谢你的提示!“不幸的是,警告是关于doIt函数本身的,而不是它的参数。”啊,好的。很高兴知道。