40

In C++98, the null pointer was represented by the literal 0 (or in fact any constant expression whose value was zero). In C++11, we prefer nullptr instead. But this doesn't work for pure virtual functions:

struct X
{
    virtual void foo() = nullptr;
};

Why does this not work? Would it not make total sense? Is this simply an oversight? Will it be fixed?

fredoverflow
  • 237,063
  • 85
  • 359
  • 638
  • 5
    To be honest, even though = 0 works, I would actually like the `= nullptr` or `= abstract` syntax better. –  Dec 31 '13 at 17:57
  • 4
    http://stackoverflow.com/questions/2156634/why-pure-virtual-function-is-initialized-by-0 – marcinj Dec 31 '13 at 18:23

8 Answers8

44

Because the syntax says 0, not expression or some other non-terminal matching nullptr.

For all the time only 0 has worked. Even 0L would be ill-formed because it does not match the syntax.

Edit

Clang allows = 0x0, = 0b0 and = 00 (31.12.2013). That is incorrect and should be fixed in the compiler, of course.

Johannes Schaub - litb
  • 466,055
  • 116
  • 851
  • 1,175
  • 3
    @TemplateRex: only where `NULL` is defined as the single character literal `0`. – Cheers and hth. - Alf Dec 31 '13 at 17:58
  • Oops doesn't seem to like `NULL` on ideone: http://ideone.com/VWT1vV but it works with a custom `#define foo 0`, so `NULL` isn't defined as `0` for that compiler (apparently). – stefan Dec 31 '13 at 18:00
  • 1
    @stefan: it rarely is, a common definition for example is `(void*)0` in C. – Matthieu M. Dec 31 '13 at 18:13
  • 1
    @MatthieuM.: in C++ `NULL` must be integral integer zero, `(void*)0` (as in C) is not permitted. – Cheers and hth. - Alf Dec 31 '13 at 18:18
  • @TemplateRex Microsoft use to have a macro `PURE` defined as `= 0` for just this purpose. As long as the macro evaluates (at the preprocessor level) to `= 0`, it doesn't matter what you put there to define it as abstract. If you want to use `ABSTRACT` to be used, just have a macro `#define ABSTRACT = 0` somewhere. – Zac Howland Dec 31 '13 at 18:25
  • 1
    @Zac Right, because the macro is replaced by the time it gets to the compiler. The misnomer here (even though it's already been explained the syntax must be `= 0`) is that people are associating `NULL` with `0`. Somebody should copy [David Rodríguez - dribeas](http://stackoverflow.com/questions/2156634/why-pure-virtual-function-is-initialized-by-0#comment2100034_2156634)'s quote: ".. vtable is not a language requirement, but just an implementation option for virtual methods. ... different implementation (that is, without vtable, and without any element there being 0)" –  Dec 31 '13 at 18:38
  • @stefan In g++, `NULL` is defined as `__null` – jerry Jan 07 '14 at 20:56
  • I voted this down, because answers of the form "because that's how it is" without explanation are worthless in response to "why" questions. All of the other current answers to this question are better. – Nye Feb 02 '14 at 17:24
  • 1
    @Nye thanks for commenting, so that I can cleanup with the misunderstanding. I told him that the syntax says that "= 0" is expected. I specifically did *not* say "because that's how it is", because I myself will downvote such answers. – Johannes Schaub - litb Feb 02 '14 at 18:44
29

The = 0 notation for virtual functions wasn't literally "assign null" but rather a special notation which is actually deceptive: a pure virtual function can also be implemented.

With various context keywords it would make more sense to allow abstract rather than = nullptr and have abstract be a context keyword.

Dietmar Kühl
  • 141,209
  • 12
  • 196
  • 356
  • 4
    FWIW, the reason we got `= 0` instead of `abstract` is (briefly) that Bjarne felt that he couldn't push another keyword past the C++ committee back in the dawn of history. I think it's on his list of personal regrets, albeit a minor one. – Macke Jan 01 '14 at 13:31
17

This is just how the grammar is defined, if we look at the draft C++ standard section 9.2 Class members the relevant grammar is as follows:

[...]
member-declarator:
 declarator virt-specifier-seqopt pure-specifieropt
[...]
pure-specifier:
  = 0
  ^^^

The grammar specifically indicates that a pure-specifier is = 0 and not an integer literal or expression, that does not seem to leave any wiggle room. If I attempt things like:

virtual void foo() = 0L;

or:

virtual void foo() = NULL ;

gcc tells me:

error: invalid pure specifier (only '= 0' is allowed) before ';' token

and clang says:

error: initializer on function does not look like a pure-specifier

Although the following does work in both:

#define bar 0
//...
virtual void foo() = bar;

It also seems like clang allows octal literal, hexadecmical literal and binary literal zero which is incorrect behavior.

Update

Apparently Visual Studio accepts NULL and any zero integer literal including 0L, 0x0, 00 etc... Although it does not accept nullptr.

Shafik Yaghmour
  • 143,425
  • 33
  • 399
  • 682
10

= 0 has a fixed meaning there. It's not really an integer zero there. Therefore, you can't simply replace it like that.

user2345215
  • 617
  • 5
  • 9
6

The = 0 syntax wasn't used to initialize a pointer, it was simply to indicate syntactically that the provided virtual was pure.

Hence the = 0 syntax for declaring pure virtuals is unchanged.

John Dibling
  • 94,084
  • 27
  • 171
  • 303
6

The whole point of nullptr (or most of the point anyway) is that can only be assigned to (or used to initialize) pointers.

In this case, you're not initializing or assigning to a pointer, so it doesn't even make sense that you would be able to use it in this situation.

Jerry Coffin
  • 437,173
  • 71
  • 570
  • 1,035
  • Why not? Functions usually degrade to function pointers, so I don't see why that syntax wouldn't make sense. They just didn't have the `nullptr` keyword available back then. – user2345215 Dec 31 '13 at 18:00
  • @user2345215: Because `=0` in this context doesn't mean "assign null to this pointer," it means something entirely different. – John Dibling Dec 31 '13 at 18:02
  • It doesn't literally mean that. But I would argue it still makes sense. It would set the address of the function to the zero pointer (if you could actually modify it), as if the function took you nowhere. But that's the point of pure virtual functions. – user2345215 Dec 31 '13 at 18:06
  • @user2345215: Except that's not necessarily true. As Dietmar already pointed out, you can make a function pure virtual *and* implement that function, in which case that slot in the vtable will contain the address of an actual function. – Jerry Coffin Dec 31 '13 at 18:09
  • 2
    @user2345215: You only know that a null pointer is going to be assigned somewhere (except the cases noted by Jerry) because you are familiar with your platform's implementation of virtuals. The C++ Standard doesn't dictate that vtbl's must be used, or anything about *how* virtual is to be implemented -- only what the effects should be. By conflating `nullptr` to indicate `pure`, the Standard would implicitly be acknowledging platform specifics. – John Dibling Dec 31 '13 at 18:12
2

That doesn't mean it is a pointer, or that it has to be equal to nullptr.

= 0 is sufficient and means that the virtual function is to be pure.

Stephane Rolland
  • 34,892
  • 31
  • 111
  • 159
1

The C++11 grammar only allows 0 here (and it doesn't mean a pointer). As nullptr is not 0, it fails. NULL only works when NULL is defined to be 0 (sometimes it's the case, but not always). Just use 0 here, or use following define (if you really want to use a null, when it's not a pointer).

#define VIRTUAL_NULL 0
struct X
{
    virtual void foo() = VIRTUAL_NULL;
};
Konrad Borowski
  • 9,885
  • 2
  • 50
  • 68