c – 纯虚拟继承,多重继承和C4505

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

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()

现在,当我从另一个用作接口类的类派生AbstractClass时,它本身具有(普通的)虚拟析构函数(纯或其他),它仍然有效:

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

当我尝试以这种方式实现两个不同的接口时出现问题:

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

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

warning C4505: 'AbstractClass::~AbstractClass' :
unreferenced local function has been removed

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

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

编辑:我也尝试将纯虚方法定义与类定义分开,因为显然= 0 {}语法实际上并不有效.不幸的是,C4505仍然出现,无论我是否指定内联.

由于我发现没有办法只为这些方法#pragma出这个警告(警告从代码的其他部分触发),我可能不得不从AbstractClass中删除纯虚拟说明符并依赖于使构造函数受到保护.这不是一个理想的解决方案,但它可以重新架构类层次结构以绕过错误的警告.

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

Note: a function declaration cannot provide both a pure-specifier and
a definition

但是,定义纯虚拟析构函数通常不违法,第12.4.7节规定:

A destructor can be declared virtual (10.3) or pure virtual (10.4); if
any objects of that class or any derived class are created in the
program, the destructor shall be defined. If a class has a base class
with a virtual destructor, its destructor (whether user- or
implicitly- declared) is virtual.

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

#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

由于代码似乎被调用,你可以忽略我认为的警告.

转载注明原文:c – 纯虚拟继承,多重继承和C4505 - 代码日志