Pure virtual destructor in C++
Asked Answered
D

2

173

Is it wrong to write:

class A {
public:
    virtual ~A() = 0;
};

for an abstract base class?

At least that compiles in MSVC... Will it crash at run time?

Dragelin answered 10/3, 2009 at 16:2 Comment(1)
It may compile, but does it link?Robot
J
229

Yes. You also need to implement the destructor:

class A {
public:
    virtual ~A() = 0;
};

inline A::~A() { }

should suffice.

If you derive anything from A and then try to delete or destroy it, A's destructor will eventually be called. Since it is pure and doesn't have an implementation, undefined behavior will ensue. On one popular platform, that will invoke the purecall handler and crash.

Edit: fixing the declaration to be more conformant, compiled with http://www.comeaucomputing.com/tryitout/

Journal answered 10/3, 2009 at 16:4 Comment(13)
So it should be declared virtual ~A() { }, without the "= 0". It's not pure virtual if you provide an implementationDisable
Um, yes it is. Pure only means a derived class also needs to provide an implementation.Journal
Implementing pure virtual functions is in fact legal. Very useful for providing a default implementation but forcing subclasses to call it explicitly.Foreordain
MSN and note if you have that definition in the header, you need to put "inline" before it to avoid violating the ODR (one definition rule)Saul
Why does A::~A() have to be explicitly defined, since, I thought there is a default destructor for every object? As in any type of inheritance, the chain of destructors is always called and the base class destructor doesn't have to always be defined.Rusert
The base class destructor always has to be defined if it will be invoked. If you never delete or explicitly destroy sublcasses of A, this doesn't matter. If you do, it does.Journal
A better way to put it is that once you declare a destructor, it is not automatically implemented for you.Journal
If you don't provide a definition for A::~A(), you should get a compile-time error—a link error.Gerah
@Journal , what do you mean by this undefined behavior and crash? pastebin.com/Uz2Ny4z0 This program does not crash on Windows. Is that the popular platform? The output is: pastebin.com/PJNdktPYTarnetgaronne
@Gerah "If you don't provide a definition for A::~A(), you should get a compile-time" -- not possible to see for the compiler. Only linker will detect it.Furmenty
Would I, according to this cpp core guideline need to =default the other special member methods as well?Relish
Just a node: even though you "force" the derived class to declare the destructor by making it pure, it will be OK to have a derived class without any (user defined) destructor. godbolt.org/z/x7TckoInfarction
Look at this, I did not know that you could write virtual ~A() = 0 {};.Stelle
F
49

Private destructors: they will give you an error when you create an object of a derived class -- not otherwise. A diagnostic may appear though.

12.4 Destructors

6 A destructor can be declared virtual (10.3) or pure virtual (10.4); if any objects of that class or any derived class are created in the program, the destructor shall be defined.

A class with a pure virtual destructor is an abstract class. Note well:

10.4 Abstract classes

2 A pure virtual function need be defined only if called with, or as if with (12.4), the qualified-id syntax (5.1).

[Note:a function declaration cannot provide both a pure-specifier and a definition —end note ]

Taken straight from the draft:

struct C {
   virtual void f() = 0 { }; // ill-formed
};
Fireworks answered 10/3, 2009 at 16:19 Comment(9)
+1. I think Herb Sutter also has some good info on this: gotw.ca/gotw/031.htm. It's interesting to note that any pure virtual function may have an implementation provided, not just destructors.Momentous
Yes, it's something you do in an interview to freak your interviewers ;)Fireworks
It's actually not all that uncommon, in my experience.Kyliekylila
@Neil Butterworth: Which one?Fireworks
@Dirk - the "any function" scenario. It's not uncommon to find it used to implement some common behaviour.Kyliekylila
@Neil: Ah, I see. I do use that often enough. Very handy.Fireworks
Which version of C++ is required for that syntax? I tested it on g++ C++11 and didn't compileEscape
wait wait, is it safe to use = 0 { }; if the compiler accepts it?Curtain
@IvanSanz-Carasa, even citation of 10.4.2 above clearly states that it's not.Posset

© 2022 - 2024 — McMap. All rights reserved.