我有一个奇怪的断言错误,我找不到这段代码的错误。
断言表达式为_BLOCK_TYPE_IS_VALID(pHead-> nBlockUse)。
为了更好的可读性,我简化了一些代码。
class Creator
{
public:
virtual ~Creator()
{
for (MyObject* item : _list)
{
delete item; <-- assertion error here
item = 0;
}
_list.clear();
}
template <class T>
T& create()
{
T * item = new T();
_list.push_back(item);
return *item;
}
private:
std::list<MyObject*> _list;
};
class A : public MyObject, public Creator
{
};
class B : public MyObject, public Creator
{
};
int main()
{
A a;
a.create<A>();
} <-- call of destructor
这个想法是一个继承Creator的对象,可以创建任何其他对象,并保持指向这些对象的指针。程序员可以使用引用。当“超级”物体被摧毁时,所有“子”物体也会被摧毁。
如果改为:
,程序就像魅力一样template <class T>
class Creator
{
public:
virtual ~Creator()
{
for (T* item : _list)
{
delete item;
item = 0;
}
_list.clear();
}
T& create()
{
T * item = new T();
_list.push_back(item);
return *item;
}
private:
std::list<T*> _list;
};
class A : public MyObject, public Creator<A>
{
};
class B : public MyObject, public Creator<B>
{
};
int main()
{
A a;
a.create();
}
现在,create方法只创建一种类型的对象(本例中为对象A)。 但我需要,create方法可以创建任何继承MyObject的对象。就像在第一次和平代码中一样。
对此断言错误的任何帮助将不胜感激。感谢。
答案 0 :(得分:1)
问题是您的MyObject类缺少虚拟析构函数,并且您尝试使用指向基类delete
的指针在指向派生类的指针上调用MyObject
。如果基类析构函数不是虚拟的,则通过基类指针在派生对象上发出delete
是未定义的行为。
5.3.5删除(第3段)
在第一个替代(删除对象)中,如果是静态类型的 操作数与其动态类型不同,静态类型应为操作数的动态类型的基类,静态类型应具有虚拟析构函数或行为未定义。
在基类MyClass
中使析构函数变为虚拟后,以下内容在Visual Studio 2013中正常工作:
#include <list>
struct MyObject
{
virtual ~MyObject() {}
};
class Creator
{
public:
virtual ~Creator()
{
for (MyObject* item : _list)
{
delete item;
item = 0;
}
_list.clear();
}
template <class T>
T& create()
{
T * item = new T();
_list.push_back(item);
return *item;
}
private:
std::list<MyObject*> _list;
};
class A : public MyObject, public Creator
{
};
class B : public MyObject, public Creator
{
};
int main()
{
A a;
a.create<A>();
}
答案 1 :(得分:0)
我认为问题在于多重继承。这是重现问题的简化方法。 它可以通过
修复在您的情况下,虚函数方法是最好的,因为建议将基类析构函数设置为虚拟,以通过继承层次结构获取销毁调用。
class A
{
};
class B
{
};
class C : public A, public B
{
};
int main()
{
// Fails with memory heap error
B* pB = new C();
delete pB;
}
修复它
int main()
{
B* pB = new C();
// Casting it to the "full" type will fix it
C* pC = static_cast<C*>(pB);
delete pC;
}
第二个程序有效,因为它与下面的内容类似。
int main()
{
// Pointer to the "full" type works
C* pC = new C();
delete pC;
}
答案 2 :(得分:0)
问题是您尝试通过MyObject指针删除A对象,而MyObject析构函数不是虚拟的。您可以将MyObject的析构函数设置为虚拟,然后可以通过指向MyObject的指针删除子类对象。有关此问题的详细信息,请参阅this问题