即使class完全不带virtual函数,被“non-virtual析构函数问题”给咬伤还是有可能的。举个例子,标准string不含任何virtual函数,但有时候程序员会错误的把它当做base class:
1 // 馊主意,std::string有个non-virtual析构函数 2 class SpecialString: public std::string{ 3 ... 4 };
乍看似乎无害,但如果你在程序任意某处无意间将一个pointer to SpecialString
转换成一个pointer to string
,然后将转换所得的那个string指针delete掉,你立刻被流放到“行为不明确”的恶地上。
1 SpecialString* pss = new SpecialString("Impending Doom"); 2 std::string* ps; 3 ... 4 5 // SpecialString* => std::string* 6 ps = pss; 7 ... 8 9 // 未有定义,现实中*ps的SpecialString资源会泄露, 10 // 因为SpecialString的析构函数没被调用 11 delete ps;
相同的分析适用于任何不带virtual析构函数的class,包括所有STL容器,如vector
,list
,set
,tr1::unordered_map
等等。如果你曾经企图继承一个标准容器或任何其他“带有non-virtual析构函数”的class,拒绝诱惑吧。(很不幸C++没有提供类似Java的final class或C#的sealed class那样的“禁止派生”机制)
原文地址:https://www.cnblogs.com/pepetang/p/11669915.html
时间: 2024-10-09 02:40:50