Why are std::future and std::promise not final? Announcing the arrival of Valued Associate #679: Cesar Manara Planned maintenance scheduled April 23, 2019 at 23:30 UTC (7:30pm US/Eastern) Data science time! April 2019 and salary with experience The Ask Question Wizard is Live!Are C++11 standard containers “final”?When to use virtual destructors?Where and why do I have to put the “template” and “typename” keywords?Do I need to explicitly call the base virtual destructor?Why is “using namespace std” considered bad practice?Why do we need virtual functions in C++?Why should C++ programmers minimize use of 'new'?Why are elementwise additions much faster in separate loops than in a combined loop?Why is it faster to process a sorted array than an unsorted array?Futures vs. PromisesWhy should I use a pointer rather than the object itself?
Why does BitLocker not use RSA?
Why not use the yoke to control yaw, as well as pitch and roll?
How do you write "wild blueberries flavored"?
What does 丫 mean? 丫是什么意思?
malloc in main() or malloc in another function: allocating memory for a struct and its members
"Destructive power" carried by a B-52?
Shimano 105 brifters (5800) and Avid BB5 compatibility
How many time has Arya actually used Needle?
Does a random sequence of vectors span a Hilbert space?
What is the proper term for etching or digging of wall to hide conduit of cables
Did pre-Columbian Americans know the spherical shape of the Earth?
IC on Digikey is 5x more expensive than board containing same IC on Alibaba: How?
Was the pager message from Nick Fury to Captain Marvel unnecessary?
How do you cope with tons of web fonts when copying and pasting from web pages?
Marquee sign letters
newbie Q : How to read an output file in one command line
Table formatting with tabularx?
Is the Mordenkainen's Sword spell underpowered?
Do i imagine the linear (straight line) homotopy in a correct way?
How do I find my Spellcasting Ability for my D&D character?
Why is there so little support for joining EFTA in the British parliament?
Determine whether an integer is a palindrome
Where and when has Thucydides been studied?
Short story about astronauts fertilizing soil with their own bodies
Why are std::future and std::promise not final?
Announcing the arrival of Valued Associate #679: Cesar Manara
Planned maintenance scheduled April 23, 2019 at 23:30 UTC (7:30pm US/Eastern)
Data science time! April 2019 and salary with experience
The Ask Question Wizard is Live!Are C++11 standard containers “final”?When to use virtual destructors?Where and why do I have to put the “template” and “typename” keywords?Do I need to explicitly call the base virtual destructor?Why is “using namespace std” considered bad practice?Why do we need virtual functions in C++?Why should C++ programmers minimize use of 'new'?Why are elementwise additions much faster in separate loops than in a combined loop?Why is it faster to process a sorted array than an unsorted array?Futures vs. PromisesWhy should I use a pointer rather than the object itself?
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;
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?
c++ c++11 c++14 language-lawyer
|
show 4 more comments
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?
c++ c++11 c++14 language-lawyer
9
no class in the standard library is marked final.
– bolov
Apr 17 at 10:49
2
stackoverflow.com/questions/9298450/…
– bolov
Apr 17 at 10:52
7
Inheriting from a class with a non-virtual destructor is not inherently bad. You just have to be careful how you use it. If you never delete a derived object through a base class pointer, then you don't need a virtual destructor.
– Jesper Juhl
Apr 17 at 11:33
2
"I can't think of a reason to do it" is not the same as "nobody could possibly want to do it". I've been surprised many times by things I thought were obvious nonsense that turned out to be useful when viewed from a different perspective.
– Pete Becker
Apr 17 at 12:15
2
@Mirko: b). Adding member is fine, as state above, it is calling destructor of derived object from base class which is UB (even if same size). c). Whereas I see cases for strong typedef forint
/float
, I don't see forstd::vector<int>
:)
– Jarod42
Apr 17 at 13:43
|
show 4 more comments
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?
c++ c++11 c++14 language-lawyer
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?
c++ c++11 c++14 language-lawyer
c++ c++11 c++14 language-lawyer
edited Apr 17 at 11:16
P.W
19.1k41860
19.1k41860
asked Apr 17 at 10:39
Sonic78Sonic78
392214
392214
9
no class in the standard library is marked final.
– bolov
Apr 17 at 10:49
2
stackoverflow.com/questions/9298450/…
– bolov
Apr 17 at 10:52
7
Inheriting from a class with a non-virtual destructor is not inherently bad. You just have to be careful how you use it. If you never delete a derived object through a base class pointer, then you don't need a virtual destructor.
– Jesper Juhl
Apr 17 at 11:33
2
"I can't think of a reason to do it" is not the same as "nobody could possibly want to do it". I've been surprised many times by things I thought were obvious nonsense that turned out to be useful when viewed from a different perspective.
– Pete Becker
Apr 17 at 12:15
2
@Mirko: b). Adding member is fine, as state above, it is calling destructor of derived object from base class which is UB (even if same size). c). Whereas I see cases for strong typedef forint
/float
, I don't see forstd::vector<int>
:)
– Jarod42
Apr 17 at 13:43
|
show 4 more comments
9
no class in the standard library is marked final.
– bolov
Apr 17 at 10:49
2
stackoverflow.com/questions/9298450/…
– bolov
Apr 17 at 10:52
7
Inheriting from a class with a non-virtual destructor is not inherently bad. You just have to be careful how you use it. If you never delete a derived object through a base class pointer, then you don't need a virtual destructor.
– Jesper Juhl
Apr 17 at 11:33
2
"I can't think of a reason to do it" is not the same as "nobody could possibly want to do it". I've been surprised many times by things I thought were obvious nonsense that turned out to be useful when viewed from a different perspective.
– Pete Becker
Apr 17 at 12:15
2
@Mirko: b). Adding member is fine, as state above, it is calling destructor of derived object from base class which is UB (even if same size). c). Whereas I see cases for strong typedef forint
/float
, I don't see forstd::vector<int>
:)
– Jarod42
Apr 17 at 13:43
9
9
no class in the standard library is marked final.
– bolov
Apr 17 at 10:49
no class in the standard library is marked final.
– bolov
Apr 17 at 10:49
2
2
stackoverflow.com/questions/9298450/…
– bolov
Apr 17 at 10:52
stackoverflow.com/questions/9298450/…
– bolov
Apr 17 at 10:52
7
7
Inheriting from a class with a non-virtual destructor is not inherently bad. You just have to be careful how you use it. If you never delete a derived object through a base class pointer, then you don't need a virtual destructor.
– Jesper Juhl
Apr 17 at 11:33
Inheriting from a class with a non-virtual destructor is not inherently bad. You just have to be careful how you use it. If you never delete a derived object through a base class pointer, then you don't need a virtual destructor.
– Jesper Juhl
Apr 17 at 11:33
2
2
"I can't think of a reason to do it" is not the same as "nobody could possibly want to do it". I've been surprised many times by things I thought were obvious nonsense that turned out to be useful when viewed from a different perspective.
– Pete Becker
Apr 17 at 12:15
"I can't think of a reason to do it" is not the same as "nobody could possibly want to do it". I've been surprised many times by things I thought were obvious nonsense that turned out to be useful when viewed from a different perspective.
– Pete Becker
Apr 17 at 12:15
2
2
@Mirko: b). Adding member is fine, as state above, it is calling destructor of derived object from base class which is UB (even if same size). c). Whereas I see cases for strong typedef for
int
/float
, I don't see for std::vector<int>
:)– Jarod42
Apr 17 at 13:43
@Mirko: b). Adding member is fine, as state above, it is calling destructor of derived object from base class which is UB (even if same size). c). Whereas I see cases for strong typedef for
int
/float
, I don't see for std::vector<int>
:)– Jarod42
Apr 17 at 13:43
|
show 4 more comments
3 Answers
3
active
oldest
votes
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
.
1
It is cleaner to do inheritance if you're exposing base functions viausing
. That could help you to avoid reimplementing anoperator[]
that only refers tomember[]
for every possible case.
– Mirko
Apr 17 at 12:21
Also, you could extend functionality as in your example using public inheritance, given that you don't add any members that change the size of the class.
– Mirko
Apr 17 at 12:27
3
@Mirko The example is intended to only show some non-ill-formed, non-UB use case related to the OP's question. Andpublic
inheritance opens the door for UB, as it allows invoking the non-virtual
destructor..
– lubgr
Apr 17 at 12:28
7
@Mirko "there's no problem invoking base class non virtual destructor" really? Or is it that it appears fine all the times you tried?
– Caleth
Apr 17 at 14:41
2
@Mirko You can add semantics to a derived class that require calling the proper destructor, without increasing the size of the class, so yourstatic_assert
is not necessarily sufficient. And in any case, the point of the answer was not to show the best way to inherit from something, just a legal way to derive fromstd::vector
.
– Max Langhof
Apr 17 at 17:03
|
show 2 more comments
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 afinal
overrider or class attribute.
add a comment |
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.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55725646%2fwhy-are-stdfuture-and-stdpromise-not-final%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
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
.
1
It is cleaner to do inheritance if you're exposing base functions viausing
. That could help you to avoid reimplementing anoperator[]
that only refers tomember[]
for every possible case.
– Mirko
Apr 17 at 12:21
Also, you could extend functionality as in your example using public inheritance, given that you don't add any members that change the size of the class.
– Mirko
Apr 17 at 12:27
3
@Mirko The example is intended to only show some non-ill-formed, non-UB use case related to the OP's question. Andpublic
inheritance opens the door for UB, as it allows invoking the non-virtual
destructor..
– lubgr
Apr 17 at 12:28
7
@Mirko "there's no problem invoking base class non virtual destructor" really? Or is it that it appears fine all the times you tried?
– Caleth
Apr 17 at 14:41
2
@Mirko You can add semantics to a derived class that require calling the proper destructor, without increasing the size of the class, so yourstatic_assert
is not necessarily sufficient. And in any case, the point of the answer was not to show the best way to inherit from something, just a legal way to derive fromstd::vector
.
– Max Langhof
Apr 17 at 17:03
|
show 2 more comments
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
.
1
It is cleaner to do inheritance if you're exposing base functions viausing
. That could help you to avoid reimplementing anoperator[]
that only refers tomember[]
for every possible case.
– Mirko
Apr 17 at 12:21
Also, you could extend functionality as in your example using public inheritance, given that you don't add any members that change the size of the class.
– Mirko
Apr 17 at 12:27
3
@Mirko The example is intended to only show some non-ill-formed, non-UB use case related to the OP's question. Andpublic
inheritance opens the door for UB, as it allows invoking the non-virtual
destructor..
– lubgr
Apr 17 at 12:28
7
@Mirko "there's no problem invoking base class non virtual destructor" really? Or is it that it appears fine all the times you tried?
– Caleth
Apr 17 at 14:41
2
@Mirko You can add semantics to a derived class that require calling the proper destructor, without increasing the size of the class, so yourstatic_assert
is not necessarily sufficient. And in any case, the point of the answer was not to show the best way to inherit from something, just a legal way to derive fromstd::vector
.
– Max Langhof
Apr 17 at 17:03
|
show 2 more comments
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
.
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
.
answered Apr 17 at 11:05
lubgrlubgr
16k32456
16k32456
1
It is cleaner to do inheritance if you're exposing base functions viausing
. That could help you to avoid reimplementing anoperator[]
that only refers tomember[]
for every possible case.
– Mirko
Apr 17 at 12:21
Also, you could extend functionality as in your example using public inheritance, given that you don't add any members that change the size of the class.
– Mirko
Apr 17 at 12:27
3
@Mirko The example is intended to only show some non-ill-formed, non-UB use case related to the OP's question. Andpublic
inheritance opens the door for UB, as it allows invoking the non-virtual
destructor..
– lubgr
Apr 17 at 12:28
7
@Mirko "there's no problem invoking base class non virtual destructor" really? Or is it that it appears fine all the times you tried?
– Caleth
Apr 17 at 14:41
2
@Mirko You can add semantics to a derived class that require calling the proper destructor, without increasing the size of the class, so yourstatic_assert
is not necessarily sufficient. And in any case, the point of the answer was not to show the best way to inherit from something, just a legal way to derive fromstd::vector
.
– Max Langhof
Apr 17 at 17:03
|
show 2 more comments
1
It is cleaner to do inheritance if you're exposing base functions viausing
. That could help you to avoid reimplementing anoperator[]
that only refers tomember[]
for every possible case.
– Mirko
Apr 17 at 12:21
Also, you could extend functionality as in your example using public inheritance, given that you don't add any members that change the size of the class.
– Mirko
Apr 17 at 12:27
3
@Mirko The example is intended to only show some non-ill-formed, non-UB use case related to the OP's question. Andpublic
inheritance opens the door for UB, as it allows invoking the non-virtual
destructor..
– lubgr
Apr 17 at 12:28
7
@Mirko "there's no problem invoking base class non virtual destructor" really? Or is it that it appears fine all the times you tried?
– Caleth
Apr 17 at 14:41
2
@Mirko You can add semantics to a derived class that require calling the proper destructor, without increasing the size of the class, so yourstatic_assert
is not necessarily sufficient. And in any case, the point of the answer was not to show the best way to inherit from something, just a legal way to derive fromstd::vector
.
– Max Langhof
Apr 17 at 17:03
1
1
It is cleaner to do inheritance if you're exposing base functions via
using
. That could help you to avoid reimplementing an operator[]
that only refers to member[]
for every possible case.– Mirko
Apr 17 at 12:21
It is cleaner to do inheritance if you're exposing base functions via
using
. That could help you to avoid reimplementing an operator[]
that only refers to member[]
for every possible case.– Mirko
Apr 17 at 12:21
Also, you could extend functionality as in your example using public inheritance, given that you don't add any members that change the size of the class.
– Mirko
Apr 17 at 12:27
Also, you could extend functionality as in your example using public inheritance, given that you don't add any members that change the size of the class.
– Mirko
Apr 17 at 12:27
3
3
@Mirko The example is intended to only show some non-ill-formed, non-UB use case related to the OP's question. And
public
inheritance opens the door for UB, as it allows invoking the non-virtual
destructor..– lubgr
Apr 17 at 12:28
@Mirko The example is intended to only show some non-ill-formed, non-UB use case related to the OP's question. And
public
inheritance opens the door for UB, as it allows invoking the non-virtual
destructor..– lubgr
Apr 17 at 12:28
7
7
@Mirko "there's no problem invoking base class non virtual destructor" really? Or is it that it appears fine all the times you tried?
– Caleth
Apr 17 at 14:41
@Mirko "there's no problem invoking base class non virtual destructor" really? Or is it that it appears fine all the times you tried?
– Caleth
Apr 17 at 14:41
2
2
@Mirko You can add semantics to a derived class that require calling the proper destructor, without increasing the size of the class, so your
static_assert
is not necessarily sufficient. And in any case, the point of the answer was not to show the best way to inherit from something, just a legal way to derive from std::vector
.– Max Langhof
Apr 17 at 17:03
@Mirko You can add semantics to a derived class that require calling the proper destructor, without increasing the size of the class, so your
static_assert
is not necessarily sufficient. And in any case, the point of the answer was not to show the best way to inherit from something, just a legal way to derive from std::vector
.– Max Langhof
Apr 17 at 17:03
|
show 2 more comments
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 afinal
overrider or class attribute.
add a comment |
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 afinal
overrider or class attribute.
add a comment |
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 afinal
overrider or class attribute.
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 afinal
overrider or class attribute.
answered Apr 17 at 11:09
P.WP.W
19.1k41860
19.1k41860
add a comment |
add a comment |
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.
add a comment |
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.
add a comment |
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.
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.
answered Apr 18 at 6:54
AjayAjay
13.7k94179
13.7k94179
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55725646%2fwhy-are-stdfuture-and-stdpromise-not-final%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
9
no class in the standard library is marked final.
– bolov
Apr 17 at 10:49
2
stackoverflow.com/questions/9298450/…
– bolov
Apr 17 at 10:52
7
Inheriting from a class with a non-virtual destructor is not inherently bad. You just have to be careful how you use it. If you never delete a derived object through a base class pointer, then you don't need a virtual destructor.
– Jesper Juhl
Apr 17 at 11:33
2
"I can't think of a reason to do it" is not the same as "nobody could possibly want to do it". I've been surprised many times by things I thought were obvious nonsense that turned out to be useful when viewed from a different perspective.
– Pete Becker
Apr 17 at 12:15
2
@Mirko: b). Adding member is fine, as state above, it is calling destructor of derived object from base class which is UB (even if same size). c). Whereas I see cases for strong typedef for
int
/float
, I don't see forstd::vector<int>
:)– Jarod42
Apr 17 at 13:43