所以我有一个没有抽象方法的抽象基类。为了增强抽象性,我已经将(非平凡的)析构函数声明为纯虚函数:

class AbstractClass
{
public:
  AbstractClass()
  {
    std::wcout << L"AbstractClass::AbstractClass()" << std::endl;
  }
  virtual ~AbstractClass() = 0
  {
    std::wcout << L"AbstractClass::~AbstractClass()" << std::endl;
  }
};

class ConcreteClass : public AbstractClass
{
public:
  ConcreteClass()
  {
    std::wcout << L"ConcreteClass::ConcreteClass()" << std::endl;
  }
  virtual ~ConcreteClass()
  {
    std::wcout << L"ConcreteClass::~ConcreteClass()" << std::endl;
  }
};

这可以按预期进行构建和运行;简单定义ConcreteClass实例的代码块的输出为

    AbstractClass::AbstractClass()
    ConcreteClass::ConcreteClass()
    ConcreteClass::~ConcreteClass()
    AbstractClass::~AbstractClass()

Now, when I have derive AbstractClass from another class used as an interface class, itself having a (trivial) virtual destructor (pure or otherwise), it still works:

class IAlpha
{
public:
  virtual ~IAlpha() = 0 {}
};

class AbstractClass : public IAlpha
{
public:
  AbstractClass()
  {
    std::wcout << L"AbstractClass::AbstractClass()" << std::endl;
  }
  virtual ~AbstractClass() = 0
  {
    std::wcout << L"AbstractClass::~AbstractClass()" << std::endl;
  }
};

class ConcreteClass : public AbstractClass
{
public:
  ConcreteClass()
  {
    std::wcout << L"ConcreteClass::ConcreteClass()" << std::endl;
  }
  virtual ~ConcreteClass()
  {
    std::wcout << L"ConcreteClass::~ConcreteClass()" << std::endl;
  }
};

当我尝试以这种方式实现两个不同的接口(interface)时,就会出现问题:
class IAlpha
{
public:
  virtual ~IAlpha() = 0 {}
};

class IBeta
{
public:
  virtual ~IBeta() = 0 {}
};

class AbstractClass : public IAlpha, public IBeta
{
public:
  AbstractClass()
  {
    std::wcout << L"AbstractClass::AbstractClass()" << std::endl;
  }
  virtual ~AbstractClass() = 0
  {
    std::wcout << L"AbstractClass::~AbstractClass()" << std::endl;
  }
};

class ConcreteClass : public AbstractClass
{
public:
  ConcreteClass()
  {
    std::wcout << L"ConcreteClass::ConcreteClass()" << std::endl;
  }
  virtual ~ConcreteClass()
  {
    std::wcout << L"ConcreteClass::~ConcreteClass()" << std::endl;
  }
};

此时,在构建时,我会收到以下警告:

警告C4505:'AbstractClass::~~ AbstractClass':
未引用的本地功能已被删除

奇怪的是,输出仍然显示AbstractClass::~AbstractClass()被调用。

这是MSVC9(VS 2008)中的错误吗?我可以安全地忽略此警告吗?

编辑:我也尝试过从类定义中分离纯虚拟方法定义,因为= 0 {}语法显然是无效的。不幸的是,无论我是否指定inline,C4505仍然显示。

由于我发现仅针对这些方法就无法用#pragma发出此警告(警告是从代码的其他部分触发的),因此我可能不得不从AbstractClass中删除纯虚拟说明符,并依赖于使构造函数受到保护。这不是一个理想的解决方案,但是它胜过重新构造类层次结构以避开错误的警告。

最佳答案

这是MSVC++ 2010和更早版本中的错误。该代码实际上得到了
即使编译器声称已删除代码也被调用。好像是
已在MSVC++ 2012中修复。其他编译器(例如gcc或clang)不会发出警告。
根据C++ 03标准第10.4.2节,语法“... = 0 {...}”是非法的(即使MSVC++没有提示),因为它已经指出:



但是,一般而言,定义纯虚拟析构函数并不违法,第12.4.7节指出:



我禁用警告的方法是在标题中添加以下几行:

#if defined(_MSC_VER) && (_MSC_VER <= 1600)
#  pragma warning(disable:4505)
#endif

如果要在本地禁用警告,则#pragma warning( push )#pragma warning( pop )可能会有所帮助。参见http://msdn.microsoft.com/en-us/library/2c8f766e(v=vs.80).aspx

由于代码似乎已被调用,因此我认为您可以忽略警告。

09-07 11:06