工作随记-构造调用虚函数
- 代码编译警告
- 原因
- 解决方法
- 示例
- 代码重构示例
- 总结
代码编译警告
Call to virtual method 'CoordinateConversionTool::Reset' during construction bypasses virtual dispatch [clang-analyzer-optin.cplusplus.VirtualCall]
这个警告信息来自 Clang 静态分析工具,指出在构造函数中调用了虚函数 CoordinateConversionTool::Reset
,这会绕过虚拟调度机制。C++ 中,在构造函数和析构函数中调用虚函数是不安全的,因为在这些情况下,虚函数不会表现为虚函数,而是表现为普通的成员函数调用。
原因
在 C++ 中,当一个对象的构造函数正在执行时,对象的多态性尚未完全建立。具体来说,基类的构造函数调用时,派生类的构造函数还没有被调用,因此调用虚函数会导致调用基类的实现,而不是派生类的实现。
解决方法
要解决这个问题,可以通过以下几种方式:
- 避免在构造函数中调用虚函数。可以将虚函数调用移动到构造函数外部,比如在对象构造完成后再调用。
- 使用初始化函数。定义一个非虚的初始化函数,在构造函数中调用这个初始化函数,避免直接调用虚函数。
示例
假设你有以下代码:
class CoordinateConversionTool {
public:CoordinateConversionTool() {Reset(); // 这里调用了虚函数}virtual ~CoordinateConversionTool() {}virtual void Reset() {// 虚函数实现}
};
可以重构为:
class CoordinateConversionTool {
public:CoordinateConversionTool() {Initialize();}virtual ~CoordinateConversionTool() {}virtual void Reset() {// 虚函数实现}private:void Initialize() {// 在这里调用虚函数Reset();}
};
代码重构示例
如果你的 CoordinateConversionTool
类如下:
class CoordinateConversionTool {
public:CoordinateConversionTool() {Reset(); // 这里调用了虚函数}virtual ~CoordinateConversionTool() {}virtual void Reset() {// 虚函数实现}
};
重构为:
class CoordinateConversionTool {
public:CoordinateConversionTool() {Initialize();}virtual ~CoordinateConversionTool() {}virtual void Reset() {// 虚函数实现}private:void Initialize() {// 在这里调用虚函数Reset();}
};
这样,在 Initialize
函数中调用虚函数 Reset
,以确保在对象完全构造后才调用虚函数。
总结
通过将虚函数调用移到一个非虚的初始化函数中,可以避免在构造函数中直接调用虚函数,从而避免 Clang 静态分析工具发出的警告,并确保代码的正确性。