Pure virtual functions may not have a built-in definition. What for?

Pure virtual functions are those member functions that are virtual and have a pure-specifier ( = 0; )

Paragraph 10.4 of paragraph 2 of C ++ 03 tells us what an abstract class is, and as a side note:

[Note: a function declaration cannot provide either a pure-specifier or a -end note definition] [Example:

 struct C { virtual void f() = 0 { }; // ill-formed }; 

-end example]

For those who are not very well versed in this problem, note that pure virtual functions may have definitions , but the provision mentioned above prohibits such definitions from appearing on the line (lexically in the class). (For the purpose of using pure virtual functions, you can see, for example, this GotW )

Now for all other types and types of functions it is allowed to provide a definition in the class, and this restriction seems at first glance completely artificial and inexplicable. Think about it, it seems that this is the second and subsequent glances :) But I believe that the restriction would not be there if there was no specific reason for this.

My question is: does anyone know these specific reasons? Good guesses are also welcome.

Notes:

  • MSVC allows PVF to have built-in definitions. So do not be surprised :)
  • the word inline in this question does not refer to the keyword inline. Supposedly that means lexically in class
+56
c ++ language-lawyer pure-virtual
Nov 13 '10 at 21:08
source share
5 answers

In the SO thread, "Why is a pure virtual function initialized to 0?" Jerry Coffin provided this quote from Bjarne Stroustrup & ss "Design and Evolution of C ++", section Β§13.2.3, where I added some emphasis on the part that seems relevant to me:

Curious syntax =0 obvious alternative was chosen, the new keyword is pure or abstract, because at that time I did not see any chance of getting a new keyword accepted. If I suggested pure version 2.0 comes without abstract classes. Given the choice between stronger syntax and abstract classes, I chose abstract classes. Instead of risking a delay and causing certain fights to be clean, I used the C and C ++ tradition of using 0 to represent "not there." The syntax =0 corresponds to My opinion that the body of the function is the initializer for the function , and also with (simplified, but usually adequate) representation of the set of virtual functions is implemented as a vector of function pointers. [& hellip; ]

So, when choosing the syntax, Bjarn thought of the body of the function as part of the initializer of the declarator, and =0 as an alternative form of the initializer, which indicated "no body" (or, in his words, "no").

It is clear that one cannot say no and have a body. in this conceptual picture.

Or, still in this conceptual picture that has two initializers.

Now, regarding my telepathic abilities, google-foo and soft-reasoning. I guess no one was interested Enough and trade; formulate a proposal to the committee that this purely syntactic restriction be lifted, and monitor all work that entails. So this is still the case.

+51
Nov 18. 2018-10-18
source share

You should not believe so much in the standardization committee. Not everything has a deep reason to explain this. Something like this happens because at first no one thought differently and after no one thought that its change is important enough (I think it is); for things old enough, this might even be an artifact of the first implementation. Some of them are the result of evolution - at the same time there was a deep reason, but the reason was eliminated, and the original solution was not reconsidered (this could also be where the original solution was caused by the fact that any definition of a pure function was forbidden). Some of them are the result of negotiations between different POVs, and as a result, there is a lack of coherence, but this shortcoming was deemed necessary to reach consensus.

+8
Nov 14 '10 at 9:48
source share

Good guesses ... well, given the situation:

  • it is legal to declare an inline function and provide an explicitly built-in body (outside the class), so there is clearly no objection to the only practical meaning of the declaration inside the class.
  • I see no potential ambiguities or conflicts introduced into the grammar, so there is no logical reason for excluding definitions of in situ functions.

My assumption: the use of bodies for pure virtual functions was realized after the grammar was formulated = 0 | { ... } = 0 | { ... } and the grammar has simply not been revised. It’s worth considering that there are many proposals for language changes / improvements - including to make such things more logical and consistent - but the number that someone picks up and writes down as official sentences is much smaller, and the number of those that have The committee has time to consider, and believes that compiler manufacturers will be ready for implementation, much less. Such things need a champion, and perhaps you are the first person to see a problem in him. To get a feel for this process, check out http://www2.research.att.com/~bs/evol-issues.html .

+7
Nov 24 '10 at 2:54
source share

Good guesses are welcome, you say?

I think = 0 in the ad comes from implementation. Most likely, this definition means that you get a NULL record in RTTI vtbl of class information - the place where the runtime addresses of class member functions are stored.

But in fact, when you install a function definition in your *.cpp file, you enter a name in the object file for the linker: the address in the *.o file where you can find a specific function.

The base linker then needs to know about C ++. It can just connect together, although you declared it as = 0 .

I think I read that what you described is possible, although I forgot about the behavior :-) ...

+2
Nov 22 '10 at 20:27
source share

Putting destructors aside, the implementation of pure virtual functions is a strange thing, because they are never called in a natural way. that is, if you have a pointer or reference to your base class, the base object will always be some Derived, which overrides the function and will always be called.

The only way to get the calling implementation is to use the Base :: func () syntax from one of the overloaded derived classes.

This actually, in some way, makes it the best target for embedding, since the moment the compiler wants to call it, it is always clear which overload is being called.

In addition, if implementations for pure virtual functions were forbidden, there would be an obvious workaround for some other (possibly protected) non-virtual function in the Base class, which you could just call in the usual way from your derived function. Of course, the volume will be less limited, since you could call it any function.

(By the way, I believe that Base::f() can only be called with this syntax from Derived::f() , and not from Derived::anyOtherFunc() . Am I correct with this assumption?).

Pure virtual destructors are a completely different story, in a way. It is used as a method simply so that someone does not instantiate the derived class without having any pure virtual functions elsewhere.

The answer to the actual question β€œwhy” is not resolved, in fact simply because the standards committee said so, but my answer sheds some light on what we are trying to achieve anyway.

0
Jan 03 '13 at 12:12
source share



All Articles