C ++ 11删除重写方法 [英] C++11 Delete overridden Method

查看:128
本文介绍了C ++ 11删除重写方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

前言:

这是关于应用C ++ 11时引入的删除运算符的新含义的最佳实践的问题改为继承父母虚拟方法的子类。

This is a question about best practices regarding a new meaning of the delete operator introduced with C++11 when applied to a child class overriding an inherited parent's virtual method.

背景:

根据标准,引用的第一个用例是明确禁止某些类型的调用函数,否则转换将是隐含的,例如最新 C ++ 11标准草案

Per the standard, the first use case cited is to explicitly disallow calling functions for certain types where conversions would otherwise be implicit such as the example from §8.4.3 of the latest C++11 standard draft:

struct sometype {
    sometype() = delete; // OK, but redundant
    some_type(std::intmax_t) = delete;
    some_type(double);
};

以上示例清晰且有目的。但是,下面的示例中,通过将新运算符定义为已删除来覆盖新运算符并阻止其被调用,这让我想到了我稍后在问题部分中确定的其他方案(下面的示例来自 C ++ 11标准草案): / p>

The above example is clear and purposeful. However, the following example where the new operator is overridden and prevented from being called by defining it as deleted started me thinking about other scenarios that I later identify in the question section (the example below is from §8.4.3 of the C++11 standard draft):

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[]

问题:

通过将这种思想扩展到继承,我很好奇其他人对以下用法示例是否是一个明确有效的用例或是否是一个不明确的滥用的想法新增功能。请为您的答案提供理由(将提供最有说服力的推理的例子)。在下面的示例中,设计尝试通过使第二个版本的库继承自第一个版本来维护两个版本的库(需要实例化库)。这个想法是允许错误修复或对第一个库版本所做的更改自动传播到第二个库版本,同时允许第二个库版本只关注它与第一个版本的差异。要弃用第二个库版本中的函数,删除运算符用于禁止调用被覆盖的函数:

By extension of this thought to inheritance, I am curious to other's thoughts regarding whether the following usage example is a clear and valid use-case or if it is an unclear abuse of the newly added feature. Please provide justification for your answer (the example that provides the most compelling reasoning will be accepted). In the example that follows, the design attempts to maintain two versions of library (the library is required to be instantiated) by having the second version of the library inherit from the first. The idea is to allow bug fixes or changes made to the first library version to automatically propagate to the second library version while allowing the second library version to focus only on its differences from the first version. To deprecate a function in the second library version, the delete operator is used to disallow a call to the overridden function:

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继承关系被打破了。我已经阅读了很多文章,强烈建议不要使用任何继承来表达一种即按关系,而是使用包含函数的组合来清楚地识别类的关系。虽然下面经常讨厌的例子需要更多的努力来实现和维护(关于为这段代码编写的行数,因为每个公开可用的继承函数必须由继承类显式调用),如上所述的删除在很多方面非常相似:

Though I can see many benefits to such an approach, I think I tend more toward the thought that it is an abuse of the feature. The primary pitfall I see in the above example is that the classic "is-a" relationship of inheritance is broken. I have read many articles that strongly recommend against any use of inheritance to express a "sort-of-is-a" relationship and to instead use composition with wrapper functions to clearly identify the relationships of the classes. While the following often-frowned-upon example requires more effort to implement and maintain (regarding the number of lines written for this piece of code, since every inherited function to be available publicly must be explicitly called out by the inheriting class), the use of delete as depicted above is very similar in many ways:

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 */ }
};

提前感谢您的答案,并进一步了解这种潜在的删除用例。

Thank you in advance for your answers and further insight into this potential use-case of delete.

推荐答案

C ++标准的第8.4.3 / 2段间接禁止删除覆盖虚函数的函数:

Paragraph 8.4.3/2 of the C++ Standard indirectly forbids deleting a function which overrides a virtual function:

引用已删除的函数隐式或显式的程序,除了声明它之外,都是格式错误的。 [注意:此包括隐式调用函数或显式调用函数并形成指向函数的指针或指针成员

"A program that refers to a deleted function implicitly or explicitly, other than to declare it, is ill-formed. [ Note: This includes calling the function implicitly or explicitly and forming a pointer or pointer-to-member to the function"

通过指向基类的指针调用重写虚函数是尝试隐式调用该函数。因此,根据8.4.3 / 2,允许这种情况的设计是非法的。另请注意,没有符合C ++ 11标准的编译器可以删除覆盖的虚函数。

Invoking an overriding virtual function through a pointer to the base class is an attempt to implicitly invoke the function. Therefore, per 8.4.3/2, a design that allows this is illegal. Also notice that no C++11 conforming compiler will let you delete an overriding virtual function.

更明确地说,第10.3 / 16段规定了相同的内容:

More explicitly, the same is mandated by Paragraph 10.3/16:

具有删除定义的函数(8.4)不得覆盖没有删除定义的函数。同样,没有删除定义的函数应不要覆盖已删除定义的函数。

这篇关于C ++ 11删除重写方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆