所以我有一个没有抽象方法的抽象基类。为了增强抽象性,我已经将(非平凡的)析构函数声明为纯虚函数:
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由于代码似乎已被调用,因此我认为您可以忽略警告。