纯虚拟继承、多重继承和C4505
Pure virtual inheritance, multiple inheritance, and 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()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;
}
};
此时,在构建时,我收到以下警告:
警告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节规定:
析构函数可以声明为虚拟的(10.3)或纯虚拟的(10.4);如果该类或任何派生类的任何对象都是在程序,应定义析构函数。如果一个类有基类使用虚拟析构函数,其析构函数(无论是用户还是隐式声明)是虚拟的。
我禁用警告的方法是在标题中添加以下行:
#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
由于代码似乎被调用了,在我看来,您可以忽略这些警告。
您是否尝试以非内联方式定义析构函数?也许这个警告与此有关。
比如这个代码。
代码不应该编译。不能在类定义内部定义纯虚拟函数。将定义移出类:
struct IAlpha {
virtual ~IAlpha() = 0;
};
inline IAlpha::~IAlpha() {}
// similarly for the rest.
除此之外,代码是正确的,应该编译。
不能将虚拟函数定义为内联函数。
因为内联正在编译中。虚拟机正在运行时。
- 关于C++中具有多重继承"this"指针的说明
- C++中模板化异常类的多重继承
- 虚拟继承中是否存在多重继承?
- 如何在 c++ 多重继承中调用父非虚函数?
- 多重继承相同的方法名,没有歧义
- 使用enable_if解决多重继承歧义
- 多重继承导致虚假的模糊虚拟函数过载
- 多重继承和访问不明确的元素
- C++ 多重继承:使用基类 A 的实现实现基类 B 的抽象方法
- 多重继承中的派生类的行为类似于聚合
- 为什么我的 Hippomock 期望在使用多重继承时失败
- 带有此指针的模板类多重继承构造函数不起作用?
- 使用多重继承时出现编译错误
- 增强多重继承的序列化
- 多重继承:跳过'virtual'关键字并拒绝菱形层次结构的使用?
- 仅函数的多重继承 - 没有虚拟和 CRTP
- C++多重继承和鸭子类型
- C++两次从文件保存对象读取多重继承
- 从多重继承中的派生类函数调用适当的父类函数
- 纯虚拟继承、多重继承和C4505