Skip to main content
 首页 » 编程设计

c++之防止指针重新分配

2025年05月04日52shangdawei

我正在阅读 Scott Meyers 的《Effective C++ Third Edition》。

他说一般来说,从不包含虚函数的类继承不是一个好主意,因为如果您以某种方式将派生类的指针转换为基类的指针,然后 delete 可能会出现未定义的行为。它。

这是他给出的(人为的)例子:

class SpecialString: public std::string{ 
   // ... 
} 
 
SpecialString *pss = new SpecialString("Impending Doom"); 
std::string *ps; 
ps = pss; 
delete ps;    // undefined! SpecialString destructor won't be called 

我理解为什么这会导致错误,但是在 SpecialString 中没有什么可以做的吗?防止类似 ps = pss 的类从发生?

Meyers 指出(在本书的不同部分),显式阻止类中允许某些行为的常用技术是声明一个特定函数,但故意不定义它。他给出的例子是复制构造。例如。对于您不想允许复制构造的类,请声明私有(private)复制构造函数但不定义它,因此任何尝试使用它都会导致编译时错误。

我意识到 ps = pss在这个例子中不是复制构造,只是想知道是否可以在这里做任何事情来明确防止这种情况发生(除了“不要那样做”的答案)。

请您参考如下方法:

该语言允许implicit pointer conversions从指向派生类的指针到指向其基类的指针,只要基类是可访问的并且没有歧义。这不是用户代码可以覆盖的东西。此外,如果基类允许销毁,那么一旦将派生指针转换为基指针,就可以通过指针删除基类,从而导致未定义的行为。这不能被派生类覆盖。

因此,您不应该从不是设计为基类的类派生。您的书中缺少变通方法表明缺少变通方法。

上面有两点可能值得再看一遍。第一: “只要基类是可访问的 并且没有歧义”。 (我不想进入“模棱两可”的观点。)您可以通过创建基类 private 来防止在类实现之外的代码中将指向派生的指针强制转换为指向基的指针。 .但是,如果您这样做,则应该花一些时间考虑一下为什么要继承。私有(private)继承通常很少见。通常,不从另一个类派生而是拥有一个类型为另一个类的数据成员会更有意义(或至少同样有意义)。

二: “如果基类允许破坏” .这不适用于您无法更改基类定义的示例,但它确实适用于声明“通常从不包含虚拟 [析构函数] 的类继承不是一个好主意”。还有另一个可行的选择。如果该类的析构函数是 protected,则从没有虚函数的类继承可能是合理的。 .如果一个类的析构函数是 protected ,那么你就不能使用 delete在指向该类的指针上(在类的实现和从它派生的类之外)。因此,只要基类具有虚拟析构函数或 protected 析构函数,就可以避免未定义的行为。