简体   繁体   中英

Why are std::future and std::promise not final?

I wounder why the classes std::future and std::promise are not marked with the final specifier. The destructor is not virtual so why was final not added? What was (is) the rationale?

Have a look at this contrived (admittedly nonsensical) example with std::vector :

template <class T>
struct Example : private std::vector<T> {
   void doStuff(const T& t) { this->push_back(t); }
   T retrieveStuff() { return this->operator[](0); }
};

Example<int> e;

e.doStuff(42);
std::cout << e.retrieveStuff() << "\n";

This works, you can't get into UB due to std::vector::~vector not being virtual because you can't delete an object through a base class pointer ( public inheritance is needed there).

The inheritance here is just an implementation detail. Not recommended practice, but people probably did and do this. Once the decision is made to not break existing code by making std::vector or other container types final , it makes sense to stick to that with different vocabulary types like std::promise or std::future .

As per [derivation]/4 :

All types specified in the C++ standard library shall be non-final types unless otherwise specified.

And std::future or std::promise are not excepted.

And as mentioned in a comment, this issue has been discussed before. Do library implementers have the freedom to add final to non-polymorphic components? .

The resolution of this issue was that it was not considered a defect with the conclusion:

Unless the library uses the keyword final in a specification, the user clearly has freedom to derive from such a class, and so equally clearly, the library vendor does not have freedom to add a final overrider or class attribute.

Absence of any virtual function in a class doesn't make it non-qualifiable as the Base class. In my opinion, adding virtual function(s) to the base class is kind of special case of making the base class as polymorphic. Many programmers careless put virtual to functions, and especially to the destructor of the class (and comment that "Virtual destructor is necessary" ).

ATL, for example, relies heavily on inheritance but doesn't have any virtual functions. The (base) classes are non-polymorphic. Most (if not all) of the C++/STL classes are non-polymorphic.

One may break the rule of "Prefer containment/composition over inheritance" and derive from a class in an illogical form (One example given by lubgr); but this is doable and is valid. Sometimes it is more appropriate to inherit from a non-polymorphic class, rather than containing a class.

Template/Template-meta classes rely on inheritance where no virtual functions are involved. Attribute-inheritance is one example, where a class would inherit from various different classes (multi-inheritance), and inherit the attributes.

One very simple example would be to make a class non_copyable , put copy-constructor/assignment-operator, etc as private/protected; and let other classes inherit from it. This way the "derived" class would inherit the non-copyable "capability/attribute" of the base class.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM