在析构函数中调用成员变量的虚函数会导致 seg 错误
Calling member variable's virtual function within destructor causes seg fault
我遇到了一个非常奇怪的问题,我希望有人能发现。
class Letter
{
public:
Letter()
virtual ~Letter()
virtual std::string get() const = 0;
};
class A : public Letter
{
public:
A()
~A()
virtual std::string get() const { return "A"; }
};
class Board
{
public:
Board(){}
~Board()
{
std::cout << "Removing: " << letter->get() << std::endl;
delete letter;
}
void setLetter(Letter * l) { letter = l }
private:
Letter * letter;
}
int main()
{
Board b;
b.setLetter(new A());
}
当Board在析构函数中调用虚函数letter->get()的那一行超出作用域时,程序导致segfault。我使用的是gcc 4.1.2。什么好主意吗?
好的,看起来实际代码中实际发生的事情相当于这样:
class Board
{
public:
Board(){}
~Board()
{
std::cout << "Removing: " << letter->get() << std::endl;
}
void setLetter(Letter * l) { letter = l; }
private:
Letter* letter;
};
int main()
{
Board b;
A a;
b.setLetter(&a);
return 0;
}
在这种情况下,当虚函数被调用时,A已经超出了作用域
我只能猜测您试图将get()返回的std::字符串转换为char*。否则我看不出崩溃的原因。
#include <iostream>
#include <string>
using namespace std;
class Letter
{
public:
Letter() {}
virtual ~Letter() {}
virtual std::string get() const = 0;
};
class A : public Letter
{
public:
A() {}
~A() {}
virtual std::string get() const { return "A"; }
};
class Board
{
public:
Board(){}
~Board()
{
std::cout << "Removing: " << letter->get() << std::endl;
delete letter;
}
void setLetter(Letter * l) { letter = l; }
private:
Letter * letter;
};
int main()
{
Board b;
b.setLetter(new A());
return 0;
}
我没有意识到一个对象正在从堆栈传递给setLetter(),所以A在b之前超出了作用域。
Board b;
A a;
b.setLetter(&a);
一些编译器不允许普通C/c++构造函数或析构函数调用虚方法,这似乎也不符合(ANSI) c++规范。这是不推荐的。
有时候这个要求是有用的。有些语言,如Object Pascal,明确允许在构造函数和析构函数中调用虚方法。
你可以使用"Fake Virtual Constructor Pattern":
class MyClass
{
public:
// constructor
MyClass
{
// anything but virtual methods
}
// destructor
~MyClass
{
// anything but virtual methods
}
virtual void MyFakeConstructor()
{
MyVirtualMethod();
}
virtual void MyFakeDestructor()
{
MyVirtualMethod();
}
virtual void MyVirtualMethod()
{
// more stuff
}
// more members
}
int main(char[][] Args)
{
MyClass MyObject = new MyClass();
MyObject->MyFakeConstructor(); // <-- calls "MyVirtualMethod()"
MyObject->DoSomething1();
MyObject->DoSomething2();
MyObject->DoSomething3();
MyObject->MyFakeDestructor(); // <-- calls "MyVirtualMethod()"
delete MyObject;
return 0;
} // int main()
另一个解决方案是你安排你的代码,使你显式调用你的虚方法外的析构函数。
欢呼。
相关文章:
- "error: no matching function for call to"构造函数错误
- 为什么类中的ostringstream类型的成员会导致";调用隐含删除复制构造函数";错误
- 尝试将unique_ptrs推送到向量时使用纯虚拟函数错误
- C++ OpenCV 卡尔曼滤波器构造函数错误
- C++:用户定义的显式类型转换函数错误
- C++ 合并字符串以'system'函数错误
- C++ wmain 函数错误时使用 Unicode
- 结构数组的构造函数错误,错误消息:没有构造函数实例与参数列表匹配
- C++ 中常量属性的初始化构造函数错误
- 线程 std::调用未知类型,无法专门化函数错误
- 表单显示对话框函数错误,并且不执行下面的语句
- 函数错误 C2059:语法错误:'>'不起作用
- STL向量上出现奇怪的复制构造函数错误
- C++ Visual Studio 重载函数错误:没有重载函数的实例与指定的类型匹配
- C++引用已删除函数错误
- 为什么通过带有文字编号的引用调用会出现"无匹配函数"错误?
- C++ 乘法定义的构造函数错误消息似乎错误
- 在 c++ 代码中将数组传递给函数错误
- FFMPEG avcodec_decode_video2函数错误代码
- 为什么我会收到转换函数错误