我明白为什么我得到我得到的错误(调用纯虚函数)。我试图从我的基类的析构函数中调用纯虚函数,如下所示。但是,我不知道如何修改我的代码以防止这种情况发生。以下是基类和派生类(无论如何都是相关部分):
基类:
TailFileManager::TailFileManager(const std::string &filename, const int fileOpenPeriod_ms)
: m_Stop(false)
{
m_WorkerThread.reset(new boost::thread(boost::bind(&TailFileManager::TailFile, this, filename, fileOpenPeriod_ms)));
}
TailFileManager::~TailFileManager()
{
m_Stop = true;
m_WorkerThread->join();
}
void TailFileManager::TailFile(const std::string &filename, const int fileOpenPeriod_ms)
{
std::ifstream ifs(filename.c_str());
while (! ifs.is_open())
{
boost::this_thread::sleep(boost::posix_time::milliseconds(fileOpenPeriod_ms));
ifs.open(filename.c_str());
}
ifs.seekg(0, std::ios::end);
while (! m_Stop)
{
ifs.clear();
std::string line;
while (std::getline(ifs, line))
{
OnLineAdded(line);
}
OnEndOfFile();
}
ifs.close();
}
派生类:
ETSLogTailFileManager::ETSLogTailFileManager(const std::string &filename, const int heartbeatPeriod_ms)
: TailFileManager(filename, heartbeatPeriod_ms),
m_HeartbeatPeriod_ms(heartbeatPeriod_ms),
m_FoundInboundMessage(false),
m_TimeOfLastActivity(0)
{
}
ETSLogTailFileManager::~ETSLogTailFileManager()
{
}
void ETSLogTailFileManager::OnLineAdded(const std::string &line)
{
// do stuff...
}
void ETSLogTailFileManager::OnEndOfFile()
{
// do stuff...
}
原文由 Andrew 发布,翻译遵循 CC BY-SA 4.0 许可协议
您不应该在构造或销毁期间调用虚函数,因为调用不会按照您的想法进行,如果他们这样做了,您仍然会不高兴。如果你是一个正在恢复的 Java 或 C# 程序员,请密切关注这个 Item,因为这是那些语言曲折而 C++ 曲折的地方。
重新设计你的设计,即你可以在对象被破坏之前调用一些清理函数,如果你正在使用 C++,想法只是在 const/dest 期间避免虚函数(如果有的话!)……
虚拟调用的规则不同。 C++ 2003,第 12.7 节“构造和破坏”,说:
让我们刷新一些旧的记忆……
成员函数,包括虚函数 (10.3),可以在构造或销毁 (12.6.2) 期间调用。当从构造函数(包括从数据成员的 mem-initializer)或从析构函数直接或间接调用虚函数时,调用应用的对象是正在构造或销毁的对象,调用的函数是在构造函数或析构函数自己的类或其基类之一中定义的函数,但不是在派生自构造函数或析构函数类的类中覆盖它的函数,或在最派生对象的其他基类之一中覆盖它的函数(1.8 )。如果虚函数调用使用显式类成员访问(5.2.5)并且对象表达式引用正在构造或销毁的对象,但其类型既不是构造函数或析构函数自己的类也不是其基类之一,则调用未定义。
由于这种行为差异,建议您在构造或销毁对象时不要调用对象的虚函数。
在构造或破坏期间切勿调用虚函数 摘自 Effective C++,第三版,Scott Meyers 2005 年 6 月 6 日
http://www.artima.com/cppsource/nevercall.html