Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

C.128, why not use override virutal base class destructor? #1000

Open
franzhollerer opened this issue Jul 23, 2017 · 5 comments
Open

C.128, why not use override virutal base class destructor? #1000

franzhollerer opened this issue Jul 23, 2017 · 5 comments
Assignees

Comments

@franzhollerer
Copy link
Contributor

From rule C.128

If a base class destructor is declared virtual, one should avoid declaring derived class destructors virtual or override. Some code base and tools might insist on override for destructors, but that is not the recommendation of these guidelines.

Can please someone help me to figure out why a destructor in a derived calls should not be declared override if the destructor is declared virtual in the base class.

Actually, this looks to me to be in contrast to the example in rule C.128. Maybe it is worth to address it in a separate rule.

@gdr-at-ms gdr-at-ms self-assigned this Jul 31, 2017
@AndrewPardoe
Copy link
Contributor

Per our editor's discussion, note that the meaning of override differs with destructors.

@robert-andrzejuk
Copy link
Contributor

C.128: Should destructors be marked "override"?
#721

@MikeGitb
Copy link

Well, I personally still disagree: the meaning of override is exactly the same for destructors as for normal members (it ensures that the function in the base class was declared virtual) it is just the destructor that - virtual or not - behaves differently than a normal function as it automatically also calls the base class destructor (but the same can be done in normal virtual member functions as well).
Out of the three bad examples, destructors are immune against the last (you can't make a spelling mistake or use the wrong parameters) but the first one (forgetting the virtual key word in the base class) and the second (not explicitly indicating that you expect it to be virtual) are mistakes you can still make and that would be caught by using override. So imho, this is an unnecessary exception.

But more importantly I think c.128 misses an explanation as to why the guidelines recommend against using override on destructors - maybe a link to #721 would be in order.
Or it could be worded differently, e.g. like:

"Adding override on destructors is not necessary as you can't misspell them."

@bdeeming
Copy link

I agree with @MikeGitb. It is very easy for someone to inherit from a class and to (mistakenly) assume that the base has a virtual destructor, or the reverse, someone performs some maintenance on the base class and in the process innocently removes the virtual from it's destructor, or even just (if it's a new class hierarchy) forgets to put the virtual on the base (we're just human after all).
I'm not really seeing what the downside is to declaring "I'm counting on the base class to have a virtual destructor, warn me if that's not the case", apart from having an extra keyword to type and read (worth it in my opinion).

@sandym
Copy link

sandym commented Mar 27, 2019

+1 for having override on destructors, this is exactly the kind of bugs we've seen in the pass and now catch by using override.

struct Base { virtual ~Base(){} };

struct SubClass : Base
{ ~SubClass() { std::cout << "It works!\n"; } };

int main()
{
	std::unique_ptr<Base> ptr = std::make_unique<SubClass>();
}

Someone remove the virtual in the base class as part of a clean up and things stop working.

Not sure I understand why it's considered good to protect ourselves against this kind of error for methods but not for the destructor.

llvm-git-migration pushed a commit to llvm/llvm-project that referenced this issue May 3, 2019
Summary:
According to [C128] "Virtual functions should specify exactly one
of `virtual`, `override`, or `final`", I've added override where a
virtual function is overriden but the explicit `override` keyword
was missing. Whenever both `virtual` and `override` were specified,
I removed `virtual`. As C.128 puts it:

> [...] writing more than one of these three is both redundant and
> a potential source of errors.

I anticipate a discussion about whether or not to add `override` to
destructors but I went for it because of an example in [ISOCPP1000].
Let me repeat the comment for you here:

Consider this code:

```
    struct Base {
      virtual ~Base(){}
    };

    struct SubClass : Base {
      ~SubClass() {
        std::cout << "It works!\n";
      }
    };

    int main() {
      std::unique_ptr<Base> ptr = std::make_unique<SubClass>();
    }
```

If for some odd reason somebody removes the `virtual` keyword from the
`Base` struct, the code will no longer print `It works!`. So adding
`override` to destructors actively protects us from accidentally
breaking our code at runtime.

[C128]: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c128-virtual-functions-should-specify-exactly-one-of-virtual-override-or-final
[ISOCPP1000]: isocpp/CppCoreGuidelines#1000 (comment)

Reviewers: teemperor, JDevlieghere, davide, shafik

Reviewed By: teemperor

Subscribers: kwk, arphaman, kadircet, lldb-commits

Tags: #lldb

Differential Revision: https://reviews.llvm.org/D61440

llvm-svn: 359868
dtzWill pushed a commit to llvm-mirror/lldb that referenced this issue May 3, 2019
Summary:
According to [C128] "Virtual functions should specify exactly one
of `virtual`, `override`, or `final`", I've added override where a
virtual function is overriden but the explicit `override` keyword
was missing. Whenever both `virtual` and `override` were specified,
I removed `virtual`. As C.128 puts it:

> [...] writing more than one of these three is both redundant and
> a potential source of errors.

I anticipate a discussion about whether or not to add `override` to
destructors but I went for it because of an example in [ISOCPP1000].
Let me repeat the comment for you here:

Consider this code:

```
    struct Base {
      virtual ~Base(){}
    };

    struct SubClass : Base {
      ~SubClass() {
        std::cout << "It works!\n";
      }
    };

    int main() {
      std::unique_ptr<Base> ptr = std::make_unique<SubClass>();
    }
```

If for some odd reason somebody removes the `virtual` keyword from the
`Base` struct, the code will no longer print `It works!`. So adding
`override` to destructors actively protects us from accidentally
breaking our code at runtime.

[C128]: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c128-virtual-functions-should-specify-exactly-one-of-virtual-override-or-final
[ISOCPP1000]: isocpp/CppCoreGuidelines#1000 (comment)

Reviewers: teemperor, JDevlieghere, davide, shafik

Reviewed By: teemperor

Subscribers: kwk, arphaman, kadircet, lldb-commits

Tags: #lldb

Differential Revision: https://reviews.llvm.org/D61440

git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@359868 91177308-0d34-0410-b5e6-96231b3b80d8
MrSidims pushed a commit to MrSidims/llvm that referenced this issue May 17, 2019
Summary:
According to [C128] "Virtual functions should specify exactly one
of `virtual`, `override`, or `final`", I've added override where a
virtual function is overriden but the explicit `override` keyword
was missing. Whenever both `virtual` and `override` were specified,
I removed `virtual`. As C.128 puts it:

> [...] writing more than one of these three is both redundant and
> a potential source of errors.

I anticipate a discussion about whether or not to add `override` to
destructors but I went for it because of an example in [ISOCPP1000].
Let me repeat the comment for you here:

Consider this code:

```
    struct Base {
      virtual ~Base(){}
    };

    struct SubClass : Base {
      ~SubClass() {
        std::cout << "It works!\n";
      }
    };

    int main() {
      std::unique_ptr<Base> ptr = std::make_unique<SubClass>();
    }
```

If for some odd reason somebody removes the `virtual` keyword from the
`Base` struct, the code will no longer print `It works!`. So adding
`override` to destructors actively protects us from accidentally
breaking our code at runtime.

[C128]: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c128-virtual-functions-should-specify-exactly-one-of-virtual-override-or-final
[ISOCPP1000]: isocpp/CppCoreGuidelines#1000 (comment)

Reviewers: teemperor, JDevlieghere, davide, shafik

Reviewed By: teemperor

Subscribers: kwk, arphaman, kadircet, lldb-commits

Tags: #lldb

Differential Revision: https://reviews.llvm.org/D61440

llvm-svn: 359868
MrSidims pushed a commit to MrSidims/llvm that referenced this issue May 24, 2019
Summary:
According to [C128] "Virtual functions should specify exactly one
of `virtual`, `override`, or `final`", I've added override where a
virtual function is overriden but the explicit `override` keyword
was missing. Whenever both `virtual` and `override` were specified,
I removed `virtual`. As C.128 puts it:

> [...] writing more than one of these three is both redundant and
> a potential source of errors.

I anticipate a discussion about whether or not to add `override` to
destructors but I went for it because of an example in [ISOCPP1000].
Let me repeat the comment for you here:

Consider this code:

```
    struct Base {
      virtual ~Base(){}
    };

    struct SubClass : Base {
      ~SubClass() {
        std::cout << "It works!\n";
      }
    };

    int main() {
      std::unique_ptr<Base> ptr = std::make_unique<SubClass>();
    }
```

If for some odd reason somebody removes the `virtual` keyword from the
`Base` struct, the code will no longer print `It works!`. So adding
`override` to destructors actively protects us from accidentally
breaking our code at runtime.

[C128]: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c128-virtual-functions-should-specify-exactly-one-of-virtual-override-or-final
[ISOCPP1000]: isocpp/CppCoreGuidelines#1000 (comment)

Reviewers: teemperor, JDevlieghere, davide, shafik

Reviewed By: teemperor

Subscribers: kwk, arphaman, kadircet, lldb-commits

Tags: #lldb

Differential Revision: https://reviews.llvm.org/D61440

llvm-svn: 359868
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants