csisy csisy - 1 month ago 20
C++ Question

Pure virtual function = unreferenced local variable warning

Conclusion for upcoming readers

An abstract class inside a function is not a good idea (at least with VS2013 Update 3, it might be a bug). See Edit 3 and Leon's answer for more detail.

Original Post

I've never got this warning and I have no idea what's happening. I set up my project to treat warnings as errors.

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) says:


warning C4101: 'BaseFoo::doIt' : unreferenced local variable


How can a pure virtual function be "unreferenced local variable"? I must be a potato or I found a compiler bug?

Edit:

If I put code into the
Foo::doIt
function (eg. an std::cout), nothing changes.

If I change
BaseFoo::doIt
to non-pure just a "simple" virtual function, which does nothing, the warning disappears.

Edit 2: Compilable single file

So I've "copy-pasted" the code into a compilable main function (I know, argv, argc, meh... :)). I've also copied the project settings:


  • Warning Level3: /W3

  • Treat warnings as errors: Yes /WX

  • Optimization: Disabled /Od

  • Minimal rebuild: Enabled /Gm

  • RTTI: No /GR-



And here is the code:

#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;
}


Edit 3:

The point goes for Leon, if I move the classes out from the main function, the warning disappears. However I'm not sure why I'm wrong if I define those classes inside the main function. So the following code compiles without any warning:

#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;
}

Answer

I think that the problem is that you declare your classes as local to a function, leaving no chance for anyone to inherit from BaseFoo and override its doIt() method.