前言:
这是关于在应用于覆盖继承父虚拟方法的子类时,与C ++ 11一起引入的删除运算符的新含义的最佳实践的问题。
背景:
根据标准,引用的第一个用例是明确禁止某些类型的调用函数,否则转换将是隐含的,例如最新的§8.4.3中的示例 C ++ 11标准草案:
struct sometype {
sometype() = delete; // OK, but redundant
some_type(std::intmax_t) = delete;
some_type(double);
};
上面的例子清晰而有目的。但是,下面的例子中,新的运算符被覆盖并且通过将其定义为已删除而无法被调用,这让我想到了我稍后在问题部分中确定的其他场景(以下示例来自§8.4.3) C ++ 11标准草案):
struct sometype {
void *operator new(std::size_t) = delete;
void *operator new[](std::size_t) = delete;
};
sometype *p = new sometype; // error, deleted class operator new
sometype *q = new sometype[3]; // error, deleted class operator new[]
题:
通过将这种思想扩展到继承,我很好奇其他人关于以下用法示例是否是一个明确有效的用例,或者是否是对新添加的功能的不明确滥用的想法。请为您的答案提供理由(将提供最有说服力的推理的例子)。在下面的示例中,设计尝试通过使第二个版本的库继承自第一个版本来维护两个版本的库(需要实例化库)。这个想法是允许错误修复或对第一个库版本所做的更改自动传播到第二个库版本,同时允许第二个库版本只关注它与第一个版本的差异。要弃用第二个库版本中的函数,delete运算符用于禁止对重写函数的调用:
class LibraryVersion1 {
public:
virtual void doSomething1() { /* does something */ }
// many other library methods
virtual void doSomethingN() { /* does something else */ }
};
class LibraryVersion2 : public LibraryVersion1 {
public:
// Deprecate the doSomething1 method by disallowing it from being called
virtual void doSomething1() override = delete;
// Add new method definitions
virtual void doSomethingElse() { /* does something else */ }
};
虽然我可以看到这种方法有很多好处,但我认为我更倾向于认为这是对该功能的滥用。我在上面的例子中看到的主要缺陷是经典的“is-a”继承关系被打破了。我已经阅读了很多文章,强烈建议不要使用任何继承来表达“一种即按”关系,而是使用包含函数的组合来清楚地识别类的关系。虽然下面经常讨厌的例子需要更多的努力来实现和维护(关于为这段代码编写的行数,因为每个公开可用的继承函数必须由继承类显式调用),如上所述的删除在很多方面非常相似:
class LibraryVersion1 {
public:
virtual void doSomething1() { /* does something */ }
virtual void doSomething2() { /* does something */ }
// many other library methods
virtual void doSomethingN() { /* does something */ }
};
class LibraryVersion2 : private LibraryVersion1 {
// doSomething1 is inherited privately so other classes cannot call it
public:
// Explicitly state which functions have not been deprecated
using LibraryVersion1::doSomething2();
// ... using (many other library methods)
using LibraryVersion1::doSomethingN();
// Add new method definitions
virtual void doSomethingElse() { /* does something else */ }
};
提前感谢您的回答,并进一步了解这种潜在的删除用例。