8

Intro

Pure virtual functions are delcared with the common syntax :

virtual f() = 0; 

Yet, since c++11 there's a way to communicate the explicit non existence of a (special) member function :

Mystruct() = delete; // eg default constructor

Q

Why isn't this syntax extended to pure virtual functions in order to achieve uniformity in communicating such operations ? :

virtual f() = delete; 

Note

I know the obvious answer is because the Standard says so!. I'm wondering about the reason(ing) behind this and whether there ever was a proposal (or an intention) for something like this.

Nikos Athanasiou
  • 29,616
  • 15
  • 87
  • 153
  • 2
    `virtual ~MyStruct() = delete;` is already taken and acts very differently. – chris Jul 25 '14 at 14:41
  • @chris Yep, strong point. Even if there was the intention, there can't be an implementation. – Nikos Athanasiou Jul 25 '14 at 15:37
  • 1
    `= delete` is already permitted on non-special member functions (including virtual functions) and non-member functions, and means "a call to this function is a compile-time error" – Oktalist Jul 25 '14 at 15:47
  • 1
    Keep in mind that the syntax `virtual f() = 0` has no reasoning behind it either. According to Bjarne Stroustrup, he saw no chance of getting a new keyword accepted at the time – Nasser Al-Shawwa Jul 25 '14 at 15:53
  • Strictly speaking, `virtual f() = 0` can't actually compile because we can't have a pure virtual constructor. It would have to have a type in there somewhere for it to not be a constructor. – Edward Jul 25 '14 at 16:02

4 Answers4

12

Roughly speaking, the difference is that this:

virtual void f() = 0; 

says "This class is abstract, and I may not have written an implementation of this member function" (though you are allowed to).

However, this:

void f() = delete;

says "This member function literally does not exist, and none shall pass."

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • 1
    I never have used this `delete` notation and I'm curious what advantage it confers over simply not defining a function. Any suggestions? – Logicrat Jul 25 '14 at 16:41
  • 2
    @Logicrat: It's useful for copy constructors and such. If you simply do not declare a copy constructor then, in some/many circumstances, one is declared for you. You have to mark it as `private` in order to prevent its use, and then the compile errors are not terribly clear. _`=delete` documents intent and improves diagnostics._ – Lightness Races in Orbit Jul 25 '14 at 16:49
  • Are there cases where I would use `delete` on regular functions, not operators? In [this Godbolt example](https://godbolt.org/z/WEnf3zPjo), does class A make any sense? Class C doesn't even compile. – Thomas Weller Nov 16 '21 at 19:09
10

= delete; means something entirely different from making a function pure virtual. Unlike deleted functions, a pure virtual function does not make ill-formed a program that selects it as the result of overload resolution.

R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
  • `does not make ill-formed a program that selects it` Since there can't be instances of abstract classes a pure virtual function can never be selected after overload resolution – Nikos Athanasiou Jul 25 '14 at 16:03
  • 4
    `abstract_class* a = new derived_class; a->pure_virtual_function();` – R. Martinho Fernandes Jul 25 '14 at 16:14
  • @R.MartinhoFernandes I don't think that overload resolution is going to choose `pure_virtual_function()` of base class. – 101010 Jul 25 '14 at 16:17
  • @R.MartinhoFernandes This example is exactly what I meant. Is dynamic dispatching considered a step after overload resolution ? Because from a high level always the implementation in derived classes is chosen. – Nikos Athanasiou Jul 25 '14 at 16:28
  • 4
    @NikosAthanasiou: Dynamic dispatch occurs at runtime, based on whichever object is actually being used at that time. Overload resolution occurs at compile time. – Dave S Jul 25 '14 at 16:39
  • @DaveS So overload resolution actually chooses the function in the base class (the pure virtual function) and then the "correct" function is invoked. Yes, ofcourse makes sense – Nikos Athanasiou Jul 25 '14 at 16:42
  • @DaveS Thnx for the info. I [asked](http://stackoverflow.com/q/24960909/2567683) a follow up q on this (mainly on "then why explicitly resolving the function breaks compilation) – Nikos Athanasiou Jul 25 '14 at 17:07
  • @40two there's no other function to choose. Consider `void f(abstract_class& a) { a.pure_virtual_function(); }`. At the time overload resolution takes place, `derived_class` need not even exist. – R. Martinho Fernandes Jul 25 '14 at 17:09
7

There is a big difference in what the two things mean. Roughly speaking, the difference is that this:

virtual void f() = 0; 

says "I may have not written an implementation of this function."

However this:

f() = delete;

says "Attention compiler: do not create an implementation of this function."

Edward
  • 6,964
  • 2
  • 29
  • 55
  • 7
    The latter says even more! It also says "if you find me trying to use this, punish me for I have been a very naughty boy". – R. Martinho Fernandes Jul 25 '14 at 14:51
  • 2
    The former does not mean that at all. It is perfectly valid to produce a definition for a pure virtual function. See my answer for _the Truth_. – Lightness Races in Orbit Jul 25 '14 at 15:51
  • 1
    @LightnessRacesinOrbit: The intent was to convey a rough approximation to aid in comprehension rather than quoting chapter and verse from the standard. With that said, I rather like R. Martinho Fernandes explanation for `delete`. – Edward Jul 25 '14 at 15:57
  • 2
    @Edward: Well if by "convey a rough approximation" you really mean "propagate a dangerous and popular misconception" then you're doing a great job! Instead, aid in comprehension by telling the truth; by telling non-truths you are actually _hurting_ comprehension (which should be self-evident). – Lightness Races in Orbit Jul 25 '14 at 16:01
  • @LightnessRacesinOrbit: I will leave *the Truth* to those who feel they have a monopoly on it. I only offer an answer which may or may not be useful to the person who asks a question. – Edward Jul 25 '14 at 16:05
  • @Edward: I'm telling you right now that it will not be useful. They may or may not be misled into thinking that it will be. :) – Lightness Races in Orbit Jul 25 '14 at 16:09
2

There are a few automatically generated member functions: default constructor, destructor, copy-constructor, assignment and there are some new move constructors too.

The purpose of being able to delete them is to ensure the compiler will not allow them to be invoked. The old trick was to declare them private and not give them an implementation.

This was cumbersome to do, but significantly it did not completely block calling them as a friend class (or even the class itself) might accidentally invoke a copy or assignment and although you would get a linker error, it is not ideal as you cannot see where the error is, and really you want a compiler error.

Declaring a function as virtual with =0 does not prevent it from being called. It has a special meaning in making your class abstract so you cannot create an instance, and means that the function does not need an implementation, but it has a different meaning to deleting it.

CashCow
  • 30,981
  • 5
  • 61
  • 92